How to jump to page on on button click? - windows

I need a simple thing: have advance and normal installation buttons. For normal case it is all simple - I used default next button with some logic on NextButtonClick to set a condition variable and skeep some pages using ShouldSkipPage . Yet for advanced setup I created a new button and all I need it to do on click is to open next installer page:
procedure CurPageChanged(CurPageID : Integer);
begin
if CurPageID = wpWelcome then begin
AdvancedButton := TButton.Create(WizardForm);
AdvancedButton.Caption := 'Advanced Install';
AdvancedButton.Left := WizardForm.InfoAfterPage.Left + 10;
AdvancedButton.Top := WizardForm.InfoAfterPage.Height + 88;
AdvancedButton.Parent := WizardForm.NextButton.Parent;
# AdvancedButton.OnClick := What shall I call to open say next page (or some page by given PageID value)
end
else begin
AdvancedButton.Visible := False;
end;
end;
So What shall I call to open say next page (or some page by given PageID value) on my button click (could not find any NextPage or some SetPage function in Inno API)?

There is no such thing as "Direct jump to page" in Inno Setup.
All you need is to quietly skip certain pages in 'Advanced mode'.
Simply do the same as in regular installer. Set one variable for holding 'Advanced mode'. After clicking the Advance button:
[Code]
var
IsAdvanced: Boolean;
procedure AdvancedButtonClick(Sender: TObject);
begin
IsAdvanced := True;
WizardForm.NextButton.OnClick(nil);
end;
procedure InitializeWizard;
var
AdvancedButton: TNewButton;
begin
// not necessary; just for sure
IsAdvanced := False;
// create the button
AdvancedButton := TNewButton.Create(WizardForm);
AdvancedButton.Caption := 'Advanced Install';
AdvancedButton.Left := WizardForm.InfoAfterPage.Left + 10;
AdvancedButton.Top := WizardForm.InfoAfterPage.Height + 88;
AdvancedButton.Parent := WizardForm.NextButton.Parent;
AdvancedButton.OnClick := #AdvancedButtonClick;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
// the <page where you want to end up> fill with the wizard page constant
// of the page where you want to end up, e.g. wpReady
Result := IsAdvanced and (PageID <> <page where you want to end up>);
end;
With this logic you can simulate quiet 'jump' to certain page.

Related

How to make Inno Setup RunList checklist box transparent?

My installer has a custom finish page with an image on it. I referred this Custom Welcome and Finished page with stretched image in Inno Setup solution for it. But the issue is with the check box at finish page, it is coming on top of the finish page image with a white background. If I removed postinstall flag, then it will automatically launch my app. But I want the user to be able to choose like how checkbox does. So is there any way to transparent the check box launch message on top of my image? Would TNewCheckBox help here?
[Run]
Filename: "app\My program.exe"; Description: "{cm:LaunchProgram}"; #
Flags: nowait postinstall skipifsilent
In standard Inno Setup, I do not think you can make WizardForm.RunList (TNewCheckListBox) transparent. But as the simple TNewCheckListBox is transparent, you can replace the WizardForm.RunList with TNewCheckListBox.
[Code]
procedure RunCheckBoxClick(Sender: TObject);
begin
WizardForm.RunList.Checked[0] := TNewCheckBox(Sender).Checked;
end;
procedure CurPageChanged(CurPageID: Integer);
var
RunCheckBox: TNewCheckBox;
begin
if CurPageID = wpFinished then
begin
if (not WizardForm.RunList.Visible) or
(WizardForm.RunList.Items.Count < 1) then
begin
Log('No items to run');
end
else
if WizardForm.RunList.Items.Count > 1 then
begin
Log('More than one item to run, keeping the standard non-transparent run list');
end
else
begin
Log('Replacing the one item in the run list with a simple transparent checkbox');
RunCheckBox := TNewCheckBox.Create(WizardForm);
RunCheckBox.Parent := WizardForm.RunList.Parent;
RunCheckBox.Left := WizardForm.RunList.Left + ScaleX(4);
RunCheckBox.Top := WizardForm.RunList.Top + ScaleY(4);
RunCheckBox.Width := WizardForm.RunList.Width;
RunCheckBox.Height := ScaleY(RunCheckBox.Height);
RunCheckBox.Checked := WizardForm.RunList.Checked[0];
RunCheckBox.Caption := WizardForm.RunList.ItemCaption[0];
RunCheckBox.OnClick := #RunCheckBoxClick;
WizardForm.RunList.Visible := False;
end
end;
end;

Why doesn't the radio button on custom page checked in Inno Setup?

Why don't rbStandardInstallType and rbCustomInstallType radio buttons get checked even though I set the Checked property of one of those to True? On the other hand, rbDefaultMSSQLInstance and rbNamedMSSQLInstance radio buttons do get checked.
I create radio buttons like this:
function CreateRadioButton(
AParent: TNewNotebookPage; AChecked: Boolean; AWidth, ALeft, ATop, AFontSize: Integer;
AFontStyle: TFontStyles; const ACaption: String): TNewRadioButton;
begin
Result := TNewRadioButton.Create(WizardForm);
with Result do
begin
Parent := AParent;
Checked := AChecked;
Width := AWidth;
Left := ALeft;
Top := ATop;
Font.Size := AFontSize;
Font.Style := AFontStyle;
Caption := ACaption;
end;
end;
I have 2 custom pages where I must show my image on the left and some text and radio buttons on the right (2 radio buttons per page).
So, in my InitializeWizard procedure I've written this:
wpSelectInstallTypePage := CreateCustomPage(wpSelectDir, 'Caption', 'Description');
rbStandardInstallType := CreateRadioButton(WizardForm.InnerPage, True, WizardForm.InnerPage.Width, ScaleX(15), WizardForm.MainPanel.Top + ScaleY(30), 9, [fsBold], 'Standard');
rbCustomInstallType := CreateRadioButton(WizardForm.InnerPage, False, rbStandardInstallType.Width, rbStandardInstallType.Left, rbStandardInstallType.Top + rbStandardInstallType .Height + ScaleY(16), 9, [fsBold], 'Custom');
wpMSSQLInstallTypePage := CreateCustomPage(wpSelectInstallTypePage.ID, 'Caption2', 'Description2');
rbDefaultMSSQLInstance := CreateRadioButton(WizardForm.InnerPage, True, WizardForm.InnerPage.Width, ScaleX(15), WizardForm.MainPanel.Top + ScaleY(30), 9, [fsBold], 'DefaultInstance');
rbNamedMSSQLInstance := CreateRadioButton(WizardForm.InnerPage, False, rbDefaultMSSQLInstance.Width, rbDefaultMSSQLInstance.Left, rbDefaultMSSQLInstance.Top + rbDefaultMSSQLInstance.Height + ScaleY(10), 9, [fsBold], 'NamedInstance');
And finally, here's my CurPageChanged code in order to display all the controls properly:
procedure CurPageChanged(CurPageID: Integer);
begin
case CurPageID of
wpSelectInstallTypePage.ID, wpMSSQLInstallTypePage.ID:
WizardForm.InnerNotebook.Visible := False;
else
WizardForm.InnerNotebook.Visible := True;
end;
rbDefaultMSSQLInstance.Visible := CurPageID = wpMSSQLInstallTypePage.ID;
rbNamedMSSQLInstance.Visible := CurPageID = wpMSSQLInstallTypePage.ID;
rbStandardInstallType.Visible := CurPageID = wpSelectInstallTypePage.ID;
rbCustomInstallType.Visible := CurPageID = wpSelectInstallTypePage.ID;
end
You are adding the radio buttons to a wrong parent control (WizardForm.InnerPage). Not to the custom pages you are creating. And you then workaround that flaw by explicitly hiding/showing the radio buttons in CurPageChanged.
As all four radio buttons have the same parent (WizardForm.InnerPage), only one of them can be checked. So when you check the rbDefaultMSSQLInstance, the rbStandardInstallType is implicitly unchecked.
For the correct code, see:
Inno Setup Placing image/control on custom page
(make sure you remove your redundant CurPageChanged code)
You should also consider using CreateInputOptionPage instead of manually adding the radio buttons to a generic custom page.

How to change picture delphi timage in run time

I use a timage in a form which load a background image.
The problem is when i choose another picture in run time and change it by
Img_Bk.Picture.LoadFromFile( SaveFileName );
It doesnt work (Picture did n't change ). I mean it shows previous picture and doesn't show the new image during run time. Id like to change application background image during run time in my company by users which main form is a mdi form .
I use delphi 7 .
try
Img_Bk.Picture := nil ;
if FileSize > 100 then
begin
Img_Bk.Picture.LoadFromFile( SaveFileName );
end;
Img_Bk.Stretch := True ;
except
end;
LoadFromFile is known to work. So there must be a more prosaic explanation.
The first possible explanation is that FileSize is not greater than 100 and the if condition evaluates false.
Another possible explanation is that the image in the file that you specify is not the one you are expecting.
Otherwise, your code has a swallow all exception handler. And so when the call to LoadFromFile fails and raises an exception, your code ignores that and carries on as if nothing un-toward had happened. Remove the try/except, and deal with the error that will be revealed.
The real lesson for you to learn is never to write such an exception handler again.
This program should prove to you that LoadFromFile is just fine:
program ImageDemo;
uses
Types, Math, IOUtils, SHFolder, Forms, Controls, StdCtrls, ExtCtrls, jpeg;
var
Form: TForm;
Image: TImage;
Timer: TTimer;
ImageIndex: Integer = -1;
MyPictures: string;
Images: TStringDynArray;
type
THelper = class
class procedure Timer(Sender: TObject);
end;
class procedure THelper.Timer(Sender: TObject);
begin
inc(ImageIndex);
if ImageIndex>high(Images) then
ImageIndex := 0;
if ImageIndex>high(Images) then
exit;
Image.Picture.LoadFromFile(Images[ImageIndex]);
end;
function GetMyPictures: string;
var
Str: array[0..260] of Char;
begin
if SHGetFolderPath(0, CSIDL_MYPICTURES, 0, 0, Str) = S_OK then
Result := Str;
end;
procedure BuildForm;
begin
Form.ClientWidth := 700;
Form.ClientHeight := 500;
Image := TImage.Create(Form);
Image.Parent := Form;
Image.Align := alClient;
Image.Stretch := True;
Timer := TTimer.Create(Form);
Timer.OnTimer := THelper.Timer;
Timer.Interval := 100;
end;
begin
MyPictures := GetMyPictures;
Images := TDirectory.GetFiles(MyPictures, '*.jpg', TSearchOption.soAllDirectories);
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, Form);
BuildForm;
Application.Run;
end.
I had the same problem today. After the call of LoadFromFile() the image does not change. I have tried Refresh, Repaint, Invalidate and Update -> nothing helped. Then I found that resizing the from immediately updated the image.
Finally I found that setting property Visible to false and back to true updates the image, too.
FormMain.Image1.Visible := false;
FormMain.Image1.Picture.LoadFromFile(newImageFileName);
FormMain.Image1.Visible := true;
Perhaps not the best but it works for me.

Delphi return custom result for showmodal

I have a form with 2 buttons (1 is mrOK - 1 is mrCancel).
As soon as I click one of the buttons the form closes (OnClose gets called), no matter what.
I would like to return a custom value. like this:
procedure OpenForm;
var
MyForm : TMyForm;
begin
MyForm := TMyForm.Create (NIL);
try
if MyForm.ShowModal = 1337 then begin
// [...]
end;
finally
MyForm.Free
end;
end;
The Modal Form:
procedure TMyForm.Button1Click(Sender: TObject); // mrOK
begin
if Edit1.Text = '' then abort; // Don't close here?!
end;
procedure TExecutePrompt.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
if Edit1.Text = '' then abort; // Works but if the user clicks the X it should return mrCancel
end;
Hope you understand what I want to do.
it's a prompt window with a edit control. if theres no text in the control the form should stay until text is entered (unless the X is clicked).
Thanks for your help.
To close a modal window with some particular modal result value, simply assign
ModalResult := MyVal; // This will close this modal window
// and the modal result will be MyVal
That is, make sure that Button1 has ModalResult = mrNone, and then you can do things like
procedure TMyForm.Button1Click(Sender: TObject); // mrOK
begin
if Edit1.Text <> '' then ModalResult := 1337;
end;
This will close the form if the edit box isn't empty, and the modal result will be 1337.

Add function execution into installer progress of inno setup

I'm making a patch for an old game (Command & Conquer 1, Win95 edition), and in some cases, executing the patch requires going through a function written in the Pascal script that could take quite a while.
At the moment, I execute this at the moment the page is changed to the "installing" page, so, after the user has selected all options and confirmed to install, right before the installer starts actually adding (and deleting) files.
procedure CurPageChanged(CurPageID: Integer);
begin
if (CurPageID = wpInstalling) then
begin
// Rename all saveg_hi.### files to savegame.###
renameSaveGames();
// clean up the ginormous files mess left behind if the game was installed from the 'First Decade' compilation pack
cleanupTFD();
end;
end;
But since the process could be rather long, I'd prefer to somehow add it to the actual install progress bar. Is there any way to accomplish this?
You can control the ProgressGauge from the install page of the WizardForm. In the following script is shown how to update the progress bar from a loop (which you'll just replace with your actions). For safety are progress bar values like min, max and position saved before the custom actions are performed and restored when they're done.
[Code]
procedure CurPageChanged(CurPageID: Integer);
var
I: Integer;
ProgressMin: Longint;
ProgressMax: Longint;
ProgressPos: Longint;
begin
if CurPageID = wpInstalling then
begin
// save the original "configuration" of the progress bar
ProgressMin := WizardForm.ProgressGauge.Min;
ProgressMax := WizardForm.ProgressGauge.Max;
ProgressPos := WizardForm.ProgressGauge.Position;
// output some status and setup the min and max progress values
WizardForm.StatusLabel.Caption := 'Doing my own pre-install...';
WizardForm.ProgressGauge.Min := 0;
WizardForm.ProgressGauge.Max := 100;
// here will be your time consuming actions with the progress update
for I := 0 to 100 do
begin
WizardForm.FilenameLabel.Caption := 'I''m on ' + IntToStr(I) + '%';
WizardForm.ProgressGauge.Position := I;
Sleep(50);
end;
// restore the original "configuration" of the progress bar
WizardForm.ProgressGauge.Min := ProgressMin;
WizardForm.ProgressGauge.Max := ProgressMax;
WizardForm.ProgressGauge.Position := ProgressPos;
end;
end;

Resources