Search code examples
windows-7inno-setupparallels

Colours of controls on custom wizard page are not correct on Windows 7 - Parallels (Inno Script)


Context:

  • MacBook Pro (latest Big Sur 11.1)
  • Parallels (latest)
  • Windows 7 (all updates)

When I run my setup, my custom page looks like this:

enter image description here

Some text is showing black. This issue does not happen when you run my installer on native Windows 10 on a PC.

My custom page is designed like this:

// ================================================
// Automatic Backup Settings Page
// ================================================

[Code]

{ Constants }
const
  BackupWhat_None = 0;
  BackupWhat_Complete = 1;
  BackupWhat_Essential = 2;

    BackupMode_Automatic = 0;
  BackupMode_Manual = 1;

    BackupPrompt_Never = 0;
    BackupPrompt_Daily = 1;
    BackupPrompt_Weekly = 2;
    BackupPrompt_Monthly = 3;

{ Global Variables }
var
  pageAutoBackup: TWizardPage;
  pnlBackupWhat: TPanel;
  lblBackupWhat: TLabel;
  radBackupWhatNone: TNewRadioButton;
  radBackupWhatComplete: TNewRadioButton;
  radBackupWhatEssential: TNewRadioButton;
  lblBackupMode: TLabel;
  pnlBackupMode: TPanel;
  radBackupModeAuto: TNewRadioButton;
  radBackupModeManual: TNewRadioButton;
  lblPromptMode: TLabel;
  cmbPromptMode: TNewComboBox;
  lblBackupFolder: TLabel;
  txtBackupFolder: TNewEdit;
  btnSelectBackupFolder: TNewButton;

{ Sets the state of the controls }
procedure EnableAutoBackupSettingPageControls();
var
  bEnable: Boolean;
begin
    bEnable := radBackupWhatComplete.Checked or radBackupWhatEssential.Checked

  pnlBackupMode.Enabled := bEnable;
  lblBackupMode.Enabled := bEnable;
  radBackupModeAuto.Enabled := bEnable;
  radBackupModeManual.Enabled := bEnable;
  lblPromptMode.Enabled := bEnable;
  cmbPromptMode.Enabled := bEnable;
  lblBackupFolder.Enabled := bEnable;
  txtBackupFolder.Enabled := bEnable;
  btnSelectBackupFolder.Enabled := bEnable;

  if(radBackupWhatNone.Checked = True) then
    Wizardform.NextButton.Enabled := True
  else
    Wizardform.NextButton.Enabled := DirExists(txtBackupFolder.Text);
  WizardForm.Update;
end;

{ Ask user to select the backup Folder location }
procedure btnSelectBackupFolder_Click(Sender: TObject);
var
  strFolder: string;
begin
  strFolder := txtBackupFolder.Text;

  { Display Browse Window }
  if(BrowseForFolder('', strFolder, True)) then
  begin
    txtBackupFolder.Text := strFolder;

    Wizardform.NextButton.Enabled := DirExists(txtBackupFolder.Text);
    WizardForm.Update;
  end;
end;

{ Action handler }
procedure radBackupWhat_Click(Sender: TObject);
begin
    { Set control states }
    EnableAutoBackupSettingPageControls();

end;

{ Automatic Backup Settings Custom Page }
function pageAutoBackup_CreatePage(PreviousPageId: Integer): Integer;
var
  iButtonGap: Integer;
begin
  { Create the page }
  pageAutoBackup := CreateCustomPage(PreviousPageId,
                          ExpandConstant('{cm:pageAutoBackupTitle}'),
                          ExpandConstant('{cm:pageAutoBackupDescription}'));

  { pnlBackupWhat (TPanel) }
  pnlBackupWhat := TPanel.Create(pageAutoBackup);
  pnlBackupWhat.Caption := '';
  pnlBackupWhat.BevelOuter := bvNone;
  pnlBackupWhat.BevelInner := bvNone; { default }
  pnlBackupWhat.BevelKind := bkNone;
  pnlBackupWhat.Parent := pageAutoBackup.Surface;
  pnlBackupWhat.Enabled := True;
  pnlBackupWhat.Visible := True;
  pnlBackupWhat.Left := ScaleX(0);
  pnlBackupWhat.Top := ScaleY(0);
  pnlBackupWhat.Width := pageAutoBackup.Surface.Width;
  pnlBackupWhat.Anchors := [akLeft, akRight];

  { lblBackupWhat (TLabel) }
  lblBackupWhat := TLabel.Create(pageAutoBackup);
  lblBackupWhat.Parent := pnlBackupWhat;
  lblBackupWhat.Enabled := True;
  lblBackupWhat.Visible := True;
  lblBackupWhat.Width := pnlBackupWhat.Width;
  lblBackupWhat.Caption := ExpandConstant('{cm:lblBackupWhat}');

  { radBackupWhatNone (TNewRadioButton) }
  radBackupWhatNone := TNewRadioButton.Create(pageAutoBackup);
  radBackupWhatNone.Parent := pnlBackupWhat;
  radBackupWhatNone.Enabled := True;
  radBackupWhatNone.Visible := True;
  radBackupWhatNone.Top := lblBackupWhat.Top + lblBackupWhat.Height + ScaleY(2);
  radBackupWhatNone.Width := pnlBackupWhat.Width;
  radBackupWhatNone.Height := ScaleY(radBackupWhatNone.Height);
  radBackupWhatNone.Checked := False;
  radBackupWhatNone.Caption := ExpandConstant('{cm:radBackupWhatNone}');
  radBackupWhatNone.OnClick := @radBackupWhat_Click;

  { radBackupWhatComplete (TNewRadioButton) }
  radBackupWhatComplete := TNewRadioButton.Create(pageAutoBackup);
  radBackupWhatComplete.Parent := pnlBackupWhat;
  radBackupWhatComplete.Enabled := True;
  radBackupWhatComplete.Visible := True;
  radBackupWhatComplete.Top := radBackupWhatNone.Top + radBackupWhatNone.Height + ScaleY(2);
  radBackupWhatComplete.Width := pnlBackupWhat.Width;
  radBackupWhatComplete.Height := ScaleY(radBackupWhatComplete.Height);
  radBackupWhatComplete.Checked := False;
  radBackupWhatComplete.Caption := ExpandConstant('{cm:radBackupWhatComplete}');
  radBackupWhatComplete.OnClick := @radBackupWhat_Click;

  { radBackupWhatEssential (TNewRadioButton) }
  radBackupWhatEssential := TNewRadioButton.Create(pageAutoBackup);
  radBackupWhatEssential.Parent := pnlBackupWhat;
  radBackupWhatEssential.Enabled := True;
  radBackupWhatEssential.Visible := True;
  radBackupWhatEssential.Top :=  radBackupWhatComplete.Top + radBackupWhatComplete.Height + ScaleY(2);
  radBackupWhatEssential.Width := pnlBackupWhat.Width;
  radBackupWhatEssential.Height := ScaleY(radBackupWhatEssential.Height);
  radBackupWhatEssential.Checked := False;
  radBackupWhatEssential.Caption := ExpandConstant('{cm:radBackupWhatEssential}');
  radBackupWhatEssential.OnClick := @radBackupWhat_Click;

  { Now we can set the panel height! }
  pnlBackupWhat.ClientHeight :=  
          radBackupWhatEssential.Top + radBackupWhatEssential.Height + ScaleY(5);

  { pnlBackupMode (TPanel) }
  pnlBackupMode := TPanel.Create(pageAutoBackup);
  pnlBackupMode.Caption := '';
  pnlBackupMode.BevelOuter := bvNone;
  pnlBackupMode.BevelInner := bvNone; { default }
  pnlBackupMode.BevelKind := bkNone;
  pnlBackupMode.Parent := pageAutoBackup.Surface;
  pnlBackupMode.Enabled := True;
  pnlBackupMode.Visible := True;
  pnlBackupMode.Top := pnlBackupWhat.Top + pnlBackupWhat.Height + ScaleY(2);
  pnlBackupMode.Width := pageAutoBackup.Surface.Width;
  pnlBackupMode.Height := ScaleY(100);
  pnlBackupMode.Anchors := [akLeft, akRight];

  { lblBackupMode (TLabel) }
  lblBackupMode := TLabel.Create(pageAutoBackup);
  lblBackupMode.Parent := pnlBackupMode;
  lblBackupMode.Enabled := True;
  lblBackupMode.Visible := True;
  lblBackupMode.Width := pnlBackupMode.Width;
  lblBackupMode.Caption := ExpandConstant('{cm:lblBackupMode}');

  { radBackupModeAuto (TNewRadioButton) }
  radBackupModeAuto := TNewRadioButton.Create(pageAutoBackup);
  radBackupModeAuto.Parent := pnlBackupMode;
  radBackupModeAuto.Enabled := True;
  radBackupModeAuto.Visible := True;
  radBackupModeAuto.Left := ScaleX(0);
  radBackupModeAuto.Top := lblBackupMode.Top + lblBackupMode.Height + ScaleY(2);
  radBackupModeAuto.Width := pnlBackupMode.Width;
  radBackupModeAuto.Height := ScaleY(radBackupModeAuto.Height);
  radBackupModeAuto.Checked := False;
  radBackupModeAuto.Caption := ExpandConstant('{cm:radBackupModeAuto}');

  { radBackupModeManual (TNewRadioButton) }
  radBackupModeManual := TNewRadioButton.Create(pageAutoBackup);
  radBackupModeManual.Parent := pnlBackupMode;
  radBackupModeManual.Enabled := True;
  radBackupModeManual.Visible := True;
  radBackupModeManual.Top := radBackupModeAuto.Top + radBackupModeAuto.Height + ScaleY(2);
  radBackupModeManual.Width := pnlBackupMode.Width;
  radBackupModeManual.Height := ScaleY(radBackupModeManual.Height);
  radBackupModeManual.Checked := False;
  radBackupModeManual.Caption := ExpandConstant('{cm:radBackupModeManual}');

  { lblPromptMode (TLabel) }
  lblPromptMode := TLabel.Create(pageAutoBackup);
  lblPromptMode.Parent := pnlBackupMode;
  lblPromptMode.Enabled := True;
  lblPromptMode.Visible := True;
  lblPromptMode.Top := radBackupModeManual.Top + radBackupModeManual.Height + ScaleY(10);
  lblPromptMode.Width := pnlBackupMode.Width;
  lblPromptMode.Caption := ExpandConstant('{cm:lblPromptMode}');

  { cmbPromptMode (TNewComboBox) }
  cmbPromptMode := TNewComboBox.Create(pageAutoBackup);
  cmbPromptMode.Parent := pnlBackupMode;
  cmbPromptMode.Style := csDropDownList;
  cmbPromptMode.Enabled := True;
  cmbPromptMode.Visible := True;
  cmbPromptMode.Top := lblPromptMode.Top + lblPromptMode.Height + ScaleY(5);
  cmbPromptMode.Width := pnlBackupMode.Width;
  cmbPromptMode.ItemIndex := 0;
  cmbPromptMode.Items.Add(ExpandConstant('{cm:cmbPromptModeItemNever}'));
  cmbPromptMode.Items.Add(ExpandConstant('{cm:cmbPromptModeItemDaily}'));
  cmbPromptMode.Items.Add(ExpandConstant('{cm:cmbPromptModeItemWeekly}'));
  cmbPromptMode.Items.Add(ExpandConstant('{cm:cmbPromptModeItemMonthly}'));
  cmbPromptMode.Anchors := [akLeft, akRight];

  { Now we can set the panel height! }
  pnlBackupMode.ClientHeight :=
          (cmbPromptMode.Top + cmbPromptMode.Height) + ScaleY(5);

  { lblBackupFolder (TLabel) }
  lblBackupFolder := TLabel.Create(pageAutoBackup);
  lblBackupFolder.Parent := pageAutoBackup.Surface;
  lblBackupFolder.Enabled := True;
  lblBackupFolder.Visible := True;
  lblBackupFolder.Top := pnlBackupMode.Top + pnlBackupMode.Height + ScaleY(2);
  lblBackupFolder.Width := pnlBackupMode.Width;
  lblBackupFolder.Caption := ExpandConstant('{cm:lblBackupFolder}');   
  lblBackupFolder.Anchors := [akLeft, akRight, akBottom];

  { txtBackupFolder (TNewEdit) }
  txtBackupFolder := TNewEdit.Create(pageAutoBackup);
  txtBackupFolder.Parent := pageAutoBackup.Surface;
  txtBackupFolder.Enabled := True;
  txtBackupFolder.ReadOnly := True;
  txtBackupFolder.Visible := True;
  txtBackupFolder.Top := lblBackupFolder.Top + lblBackupFolder.Height + ScaleY(5);
  txtBackupFolder.Anchors := [akLeft, akRight, akBottom];

  { btnSelectBackupFolder (TNewButton) }
  btnSelectBackupFolder := TNewButton.Create(pageAutoBackup);
  btnSelectBackupFolder.Parent := pageAutoBackup.Surface;
  btnSelectBackupFolder.Enabled := True;
  btnSelectBackupFolder.Visible := True;
  btnSelectBackupFolder.Left := pageAutoBackup.Surface.Width - WizardForm.CancelButton.Width;
  btnSelectBackupFolder.Top := txtBackupFolder.Top;
  btnSelectBackupFolder.Width := WizardForm.CancelButton.Width;
  btnSelectBackupFolder.Height := WizardForm.CancelButton.Height;
  btnSelectBackupFolder.Caption := SetupMessage(msgButtonBrowse);   
  btnSelectBackupFolder.Anchors := [akRight, akBottom];
  btnSelectBackupFolder.OnClick := @btnSelectBackupFolder_Click;
  
  { Now we can set the text box width!
    Use the gap between the Next and Cancel buttons for consistency.}
  iButtonGap := WizardForm.CancelButton.Left -
                      (WizardForm.NextButton.Left + WizardForm.NextButton.Width);
  txtBackupFolder.Width := 
          pageAutoBackup.Surface.Width - btnSelectBackupFolder.Width - iButtonGap;

  Result := pageAutoBackup.ID;

end;

function GetWhatToBackupMode(Param: string): string;
begin

  if(radBackupWhatComplete.Checked) then
  begin
    Log('What to backup: Complete backup mode selected.');
    Result := IntToStr(BackupWhat_Complete);
  end
  else if(radBackupWhatEssential.Checked) then
  begin
    Log('What to backup: Essential backup mode selected.');
    Result := IntToStr(BackupWhat_Essential);
  end
  else begin
    Log('What to backup: No backup mode selected.');
    Result := IntToStr(BackupWhat_None);
  end;
end;
  
function GetHowToBackupMode (Param: string): string;
begin

  if(radBackupModeManual.Checked) then
  begin
    Log('How to backup: Perform the backup manually.');
    Result := IntToStr(BackupMode_Manual);
  end
  else begin
    Log('How to backup: Perform the backup automatically.');
    Result := IntToStr(BackupMode_Automatic);
  end;
end;

function GetBackupPromptMode (Param: string): string;
begin
  Log('Where to backup: ' +  cmbPromptMode.Items[cmbPromptMode.ItemIndex]);
  Result := IntToStr(cmbPromptMode.ItemIndex);
end;

function GetBackupLocationPath (Param: string): string;
begin
  // If empty, use the app folder and create a backup folder (Param)
  Log(txtBackupFolder.Text);
  Result := txtBackupFolder.Text;
end;

procedure AutoBackupPage_InitializeWizard(AfterId: Integer);
var
  dwBackupAtShutdownWhat: Cardinal;
  dwBackupAtShutdownHow: Cardinal;
  dwBackupPromptMode: Cardinal;
  strBackupFolder: String;
begin
  pageAutoBackup_CreatePage(AfterId);

  { What to Backup }
  dwBackupAtShutdownWhat := BackupWhat_None;
  if (IsWin64) then
  begin
    RegQueryDWordValue(HKLM64,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupAtShutdownWhat', dwBackupAtShutdownWhat)
  end else
  begin
    RegQueryDWordValue(HKLM,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupAtShutdownWhat', dwBackupAtShutdownWhat);
  end;

  if (dwBackupAtShutdownWhat = BackupWhat_Complete) then
  begin
    radBackupWhatComplete.Checked := True;
  end
  else if (dwBackupAtShutdownWhat = BackupWhat_Essential) then
  begin
    radBackupWhatEssential.Checked := True;
  end
  else begin
    radBackupWhatNone.Checked := True;
  end;

  { How to Backup }
  dwBackupAtShutdownHow := BackupMode_Automatic;
  if (IsWin64) then
  begin
    RegQueryDWordValue(HKLM64,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupAtShutdownMode', dwBackupAtShutdownHow);
  end else
  begin
    RegQueryDWordValue(HKLM,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupAtShutdownMode', dwBackupAtShutdownHow);
  end;

  if (dwBackupAtShutdownHow = BackupMode_Manual) then
  begin
    radBackupModeManual.Checked := True;
  end
  else begin
    radBackupModeAuto.Checked := True;
  end;

  { Backup Prompt Mode }
  dwBackupPromptMode := BackupPrompt_Never;
  if (IsWin64) then
  begin
  RegQueryDWordValue(HKLM64,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupPromptMode', dwBackupPromptMode);
  end else
  begin
    RegQueryDWordValue(HKLM,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupPromptMode', dwBackupPromptMode);
  end;
  cmbPromptMode.ItemIndex  := dwBackupPromptMode;

  { Backup Local Path }
  strBackupFolder := '';
  if (IsWin64) then
  begin
    RegQueryStringValue(HKLM64,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupAtShutdownLocalPath', strBackupFolder);
  end else
  begin
    RegQueryStringValue(HKLM,
            'Software\MeetSchedAssist\Meeting Schedule Assistant\Options',
            'BackupAtShutdownLocalPath', strBackupFolder);
  end;
  
  { Do we need to reset the existing folder? }
  if(not DirExists(strBackupFolder)) then strBackupFolder :=  '';
  
  txtBackupFolder.Text  := strBackupFolder;
end;

procedure AutoBackupPage_CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = pageAutoBackup.ID then
  begin
    { Get the state of the Next button correct }
    if(radBackupWhatNone.Checked) then
      Wizardform.NextButton.Enabled := True
    else
      Wizardform.NextButton.Enabled := DirExists(txtBackupFolder.Text);
    WizardForm.Update;
  end;
end;

{ Build the Memo text for the Auto Backup Settings page }
function AutoBackupPage_MemoInfo(Space, NewLine: String): String;
begin
  Result := Result + ExpandConstant('{cm:pageAutoBackupTitle}') + NewLine;

  { What to Backup }
  Result := Result + Space + ExpandConstant('{cm:lblBackupWhat}') + NewLine;
  if(radBackupWhatNone.Checked) then
    Result := Result + Space + Space + ExpandConstant('{cm:radBackupWhatNone}') + NewLine;
  if(radBackupWhatComplete.Checked) then
    Result := Result + Space + Space + ExpandConstant('{cm:radBackupWhatComplete}') + NewLine;
  if(radBackupWhatEssential.Checked) then
    Result := Result + Space + Space + ExpandConstant('{cm:radBackupWhatEssential}') + NewLine;

  if(radBackupWhatNone.Checked = False) then
  begin
    { How to Backup }
    Result := Result + Space + ExpandConstant('{cm:lblBackupMode}') + NewLine;
    if(radBackupModeAuto.Checked) then
      Result := Result + Space + Space + ExpandConstant('{cm:radBackupModeAuto}') + NewLine;
    if(radBackupModeManual.Checked) then
      Result := Result + Space + Space + ExpandConstant('{cm:radBackupModeManual}') + NewLine;

    { Prompt Mode }
    Result := Result + Space + Space + ExpandConstant('{cm:lblPromptMode}') + NewLine;
    if(cmbPromptMode.ItemIndex = BackupPrompt_Never) then
      Result := Result + Space + Space + Space + ExpandConstant('{cm:cmbPromptModeItemNever}') + NewLine;
    if(cmbPromptMode.ItemIndex = BackupPrompt_Daily) then
      Result := Result + Space + Space + Space + ExpandConstant('{cm:cmbPromptModeItemDaily}') + NewLine;
    if(cmbPromptMode.ItemIndex = BackupPrompt_Weekly) then
      Result := Result + Space + Space + Space + ExpandConstant('{cm:cmbPromptModeItemWeekly}') + NewLine;
    if(cmbPromptMode.ItemIndex = BackupPrompt_Monthly) then
      Result := Result + Space + Space + Space + ExpandConstant('{cm:cmbPromptModeItemMonthly}') + NewLine;

    { Backup Folder }
    Result := Result + Space + ExpandConstant('{cm:lblBackupFolder}') + NewLine;
    Result := Result + Space + Space + txtBackupFolder.Text + NewLine;
  end;
  Result := Result + NewLine;

end;

I am using skinning as you can see (#define Skin "Amakrits.vsf").

I didn't anticipate this rendering issue.


Solution

  • Works fine for me on latest Win 10.

    1. Your picture shows you have selected "Don't perform..." option which disables the controls in next group, that is a reason why the controls have different colors.

    2. Did you make any changes in the skin file Amakrits.vsf? My skin looks different (I downloaded it from GitHub few moments ago) and it looks like some tweaks are missing in my case.

    Conclusion: this is not an Inno Setup issue, but problem in VCL skinning plugin (try to post your issue here: https://github.com/RRUZ/vcl-styles-plugins/issues), but it looks like it can be improved by tweaking the colors in used .vsf file.

    P.S. your script could not be compiled correctly as there were missing Custom Messages and skin / setup initialization functions.

    My setup