I have an Inno Setup program with a custom WelcomeLabel2 message.
[Messages]
WelcomeLabel2=Lorem ipsum dolor sit amet CLICK_HERE consectetur adipiscing elit.
I am trying to make the CLICK_HERE a clickable link to a website.
Another thing I am wondering is how to make this CLICK_HERE text bold.
How can I achieve this?
It's not easy.
To create a label that is clickable whole, you can use a code like:
procedure OpenBrowser(Url: string);
var
ErrorCode: Integer;
begin
ShellExec('open', Url, '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end;
procedure LinkClick(Sender: TObject);
begin
OpenBrowser('https://www.example.com/');
end;
procedure InitializeWizard;
var
Link: TLabel;
begin
Link := TLabel.Create(WizardForm);
Link.Left := ???;
Link.Top := ???;
Link.Parent := WizardForm.WelcomePage;
Link.Caption := 'CLICK_HERE';
Link.OnClick := #LinkClick;
Link.ParentFont := True;
Link.Font.Style := Link.Font.Style + [fsUnderline, fsBold];
Link.Font.Color := clBlue;
Link.Cursor := crHand;
end;
See also Show License Agreement link in Inno Setup while installation.
Though to create a label that have just parts of its text clickable is a way more difficult. If the text fits on one line, it's doable by stacking three labels next to each other (first the leading static text, then link, followed by the trailing static text). But if the text does not fit on one line, it's not doable, as the labels would overlap each other.
Alternatively, you can create an RTF document with the link and present it using a read-only TRichEditViewer:
procedure InitializeWizard;
var
RichViewer: TRichEditViewer;
begin
RichViewer := TRichEditViewer.Create(WizardForm);
RichViewer.Left := WizardForm.WelcomeLabel2.Left;
RichViewer.Top := WizardForm.WelcomeLabel2.Top;
RichViewer.Width := WizardForm.WelcomeLabel2.Width;
RichViewer.Height := WizardForm.WelcomeLabel2.Height;
RichViewer.Parent := WizardForm.WelcomeLabel2.Parent;
RichViewer.BorderStyle := bsNone;
RichViewer.TabStop := False;
RichViewer.ReadOnly := True;
WizardForm.WelcomeLabel2.Visible := False;
RichViewer.RTFText :=
'{\rtf1 Lorem ipsum dolor sit amet ' +
'{\b {\field{\*\fldinst{HYPERLINK "https://www.example.com/" }}' +
'{\fldrslt{CLICK_HERE}}}} ' +
'consectetur adipiscing elit.}';
end;
You need Unicode version (the only version as of Inno Setup 6) for this, see How to add clickable links to custom page in Inno Setup using RichEditViewer?
To change the link color, see Inno Setup - How to change the color of the hyperlink in RTF text?
As #Bill_Stewart commented, you should avoid starting the browser with elevated privileges. For a solution, see How to open a web site after uninstallation in non-elevated mode?
Related
I'm trying to create a custom message box saying something like "Loading" or "Extracting" during the Extraction of temporary files in InnoSetup. Is this possible? If not, please come up with suggestions on how I can proceed.
I'm extracting the files temporarily because the files are installers. Otherwise, I would have to extract them into for example documents, run them, and then remove them after my installer is finished.
After extraction, I'm using a batch file to run the different installers from tmp.
Anyway, what I'm struggling with is that After I've created a Form and a label for that form, the label is displayed first when the "ExtractTemporaryFiles" is finished.
This is my code:
`[Code]
var
ResultCode: Integer;
Form: TSetupForm;
Label1: TLabel;
function InitializeSetup: Boolean;
begin
Form := CreateCustomForm;
Form.ClientWidth := ScaleX(500);
Form.ClientHeight := ScaleY(500);
Form.Caption := 'Loading.. ';
Label1 := TLabel.Create(Form);
Label1.Parent := Form;
Label1.Caption := 'Extracting.. ';
Label1.Left := ScaleX(16);
Label1.Top := ScaleY(16);
Label1.Width := ScaleX(224);
Label1.Height := ScaleY(32);
Form.show()
end;
end;
procedure DeinitializeSetup;
begin
Form.showModal()
ExtractTemporaryFiles('{app}\*');
if Exec(ExpandConstant('{tmp}\')+'{app}\runAll2.bat', 'runascurrentuser', '',SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then begin
MsgBox('Finished! Press ok', mbError, MB_OK)
end
else begin
MsgBox('Something went wrong! Press ok', mbError, MB_OK)
end;
end;`
Can you please help me out guys?
//InnoSetup noob :)
Can you create a custom page that looks like the Finish page?
This is the code for custom page,
UserPage2 := CreateCustomPage(
UserPage1.ID,
'Title',
'Details'
);
This custom page,
Needs to look like this,
The reason for this is because, sometimes when the user runs the installer again they will be able to select few options. Based on the options the installer needs to make few changes to the settings used by the installed program without overwriting the files by reinstalling. So the user should get the Finish dialog after the changes.
Recreate the FinishedPage controls on your custom page.
When entering the page, you need to resize WizardForm.InnerNotebook to cover whole wizard window (except for the bottom button area) and hide the page header controls.
var
FakeFinishedPage: TWizardPage;
FakeFinishedBitmapImage: TBitmapImage;
FakeFinishedLabel: TNewStaticText;
FakeFinishedHeadingLabel: TNewStaticText;
procedure CopyBounds(Dest, Source: TControl);
begin
Dest.Left := Source.Left;
Dest.Top := Source.Top;
Dest.Width := Source.Width;
Dest.Height := Source.Height;
end;
procedure FakeFinishedPageActivate(Sender: TWizardPage);
begin
WizardForm.Bevel1.Visible := False;
WizardForm.MainPanel.Visible := False;
WizardForm.InnerNotebook.Left := 0;
WizardForm.InnerNotebook.Top := 0;
WizardForm.InnerNotebook.Width := WizardForm.OuterNotebook.ClientWidth;
WizardForm.InnerNotebook.Height := WizardForm.OuterNotebook.ClientHeight;
// With WizardStyle=modern and/or WizardResizable=yes,
// we cannot copy the sizes in InitializeWizard as they are not final yet.
CopyBounds(FakeFinishedBitmapImage, WizardForm.WizardBitmapImage2);
FakeFinishedBitmapImage.Anchors := WizardForm.WizardBitmapImage2.Anchors;
CopyBounds(FakeFinishedLabel, WizardForm.FinishedLabel);
FakeFinishedLabel.Anchors := WizardForm.FinishedLabel.Anchors;
CopyBounds(FakeFinishedHeadingLabel, WizardForm.FinishedHeadingLabel);
FakeFinishedHeadingLabel.Anchors := WizardForm.FinishedHeadingLabel.Anchors;
WizardForm.BackButton.Visible := False;
WizardForm.NextButton.Caption := SetupMessage(msgButtonFinish);
end;
procedure CopyLabel(Dest, Source: TNewStaticText);
begin
Dest.AutoSize := Source.AutoSize;
Dest.Font := Source.Font;
Dest.ShowAccelChar := Source.ShowAccelChar;
Dest.WordWrap := Source.WordWrap;
end;
procedure InitializeWizard();
var
S: string;
begin
// ...
FakeFinishedPage := CreateCustomPage(UserPage1.ID, '', '');
FakeFinishedPage.OnActivate := #FakeFinishedPageActivate;
FakeFinishedBitmapImage := TBitmapImage.Create(WizardForm);
FakeFinishedBitmapImage.Parent := FakeFinishedPage.Surface;
FakeFinishedBitmapImage.BackColor := WizardForm.WizardBitmapImage2.BackColor;
FakeFinishedBitmapImage.Bitmap := WizardForm.WizardBitmapImage2.Bitmap;
FakeFinishedBitmapImage.Stretch := WizardForm.WizardBitmapImage2.Stretch;
FakeFinishedLabel := TNewStaticText.Create(WizardForm);
FakeFinishedLabel.Parent := FakeFinishedPage.Surface;
CopyLabel(FakeFinishedLabel, WizardForm.FinishedLabel);
S := SetupMessage(msgFinishedLabelNoIcons) + #13#13 + SetupMessage(msgClickFinish);
StringChangeEx(S, '[name]', 'My Program', True);
FakeFinishedLabel.Caption := S;
FakeFinishedHeadingLabel := TNewStaticText.Create(WizardForm);
FakeFinishedHeadingLabel.Parent := FakeFinishedPage.Surface;
CopyLabel(FakeFinishedHeadingLabel, WizardForm.FinishedHeadingLabel);
S := SetupMessage(msgFinishedHeadingLabel);
StringChangeEx(S, '[name]', 'My Program', True);
FakeFinishedHeadingLabel.Caption := S;
end;
There are some limitations:
The code does not handle correctly image resizes, when the wizard resizes (with WizardResizable=yes) – it's easy to fix though.
The solution does not expect that any page will be shown after this fake finish pages shows. I.e. there's no Back button and it's expected that the Finish button is implement to kill the intallater. After all, this is a follow up question to Conditionally skip to a custom page at the end of the Inno Setup installation wizard without installing?
Though to avoid all these hacks, consider allowing the installation to proceed normally, but without changing anything. It might be easier to implement in the end.
Related questions:
Image covering whole page in Inno Setup – An alternative implementation that solves the problem by overlaying a control over whole upper part of the wizard window, hiding/showing it as needed.
Custom Welcome and Finished page with stretched image in Inno Setup
How to hide the main panel and show an image over the whole page?
I want make transparency under text here:
As you can see, I have black background what i don't want to have.
Greetings.
The PageNameLabel and PageDescriptionLabel are TNewStaticText components. This component does not support transparency. Though TLabel component, which has similar functionality otherwise, does support transparency (in Unicode version of Inno Setup and with themed Windows only).
So, you can replace those two components with TLabel equivalent. And then you need to make sure, that captions of your new custom components get updated, whenever Inno Setup does update the original components. For these two components, this is quite easy, as they get updated only, when a page changes. So you can update your custom components from CurPageChanged event function.
function CloneStaticTextToLabel(StaticText: TNewStaticText): TLabel;
begin
Result := TLabel.Create(WizardForm);
Result.Parent := StaticText.Parent;
Result.Left := StaticText.Left;
Result.Top := StaticText.Top;
Result.Width := StaticText.Width;
Result.Height := StaticText.Height;
Result.AutoSize := StaticText.AutoSize;
Result.ShowAccelChar := StaticText.ShowAccelChar;
Result.WordWrap := StaticText.WordWrap;
Result.Font := StaticText.Font;
StaticText.Visible := False;
end;
var
PageDescriptionLabel: TLabel;
PageNameLabel: TLabel;
procedure InitializeWizard();
begin
{ ... }
{ Create TLabel equivalent of standard TNewStaticText components }
PageNameLabel := CloneStaticTextToLabel(WizardForm.PageNameLabel);
PageDescriptionLabel := CloneStaticTextToLabel(WizardForm.PageDescriptionLabel);
end;
procedure CurPageChanged(CurPageID: Integer);
begin
{ Update the custom TLabel components from the standard hidden components }
PageDescriptionLabel.Caption := WizardForm.PageDescriptionLabel.Caption;
PageNameLabel.Caption := WizardForm.PageNameLabel.Caption;
end;
Way easier is to change original labels background color:
Inno Setup - Change size of page name and description labels
How to hide X button at message box?
I want to see this, if is possible:
I do not think this is possible.
One possible workaround is to implement the message box from the scratch.
And remove the biSystemMenu from the TForm.BorderIcons (or actually setting it empty).
procedure MyMessageBoxWithoutCloseButton;
var
Form: TSetupForm;
Button: TNewButton;
MesssageLabel: TLabel;
begin
Form := CreateCustomForm;
Form.BorderStyle := bsDialog;
Form.Position := poOwnerFormCenter;
Form.ClientWidth := ScaleX(400);
Form.ClientHeight := ScaleY(130);
Form.BorderIcons := []; { No close button }
Form.Caption := 'Caption';
MesssageLabel := TLabel.Create(Form);
MesssageLabel.Parent := Form;
MesssageLabel.Left := ScaleX(16);
MesssageLabel.Top := ScaleX(16);
MesssageLabel.Width := Form.ClientWidth - 2*ScaleX(16);
MesssageLabel.Height := ScaleY(32);
MesssageLabel.AutoSize := False;
MesssageLabel.WordWrap := True;
MesssageLabel.Caption := 'Lorem ipsum dolor sit amet, ...';
Button := TNewButton.Create(Form);
Button.Parent := Form;
Button.Width := ScaleX(80);
Button.Height := ScaleY(24);
Button.Left := Form.ClientWidth - Button.Width - ScaleX(8);
Button.Top := Form.ClientHeight - Button.Height - ScaleY(8);
Button.Caption := 'Accept';
Button.ModalResult := mrOK;
Form.ShowModal;
end;
Note that it's still possible to close the message box using Alt-F4.
To prevent that handle OnCloseQuery. For an example, see How to Delete / Hide / Disable [OK] button on message box.
I made a custom wizard page, and I want it to show a sort of installation checklist at the end of the install, showing what installed successfully or not.
Something like
Crucial Step......................SUCCESS
Optional Step.....................FAILURE
So I have this code in my initializeWizard()
Page := CreateCustomPage(wpInstalling, 'Installation Checklist', 'Status of all installation components');
RichEditViewer := TRichEditViewer.Create(Page);
RichEditViewer.Width := Page.SurfaceWidth;
RichEditViewer.Height := Page.SurfaceHeight;
RichEditViewer.Parent := Page.Surface;
RichEditViewer.ScrollBars := ssVertical;
RichEditViewer.UseRichEdit := True;
RichEditViewer.RTFText := ''// I want this attribute to be set in CurStepChanged()
Is there a way to add or edit RichEditViewer.RTFText at a later point in time? Page is a global variable but trying to access any attributes gives me an error. I'd like to do edit the text after wpInstalling, so I can tell whether or not install steps were successful.
I'm not a huge fan of this method, but you Can set your RichEditViewer as a global, and then editing it at any point, in any function, is trivial.
var
RichEditViewer: TRichEditViewer;
procedure InitializeWizard();
var
Page: TWizardPage;
begin
Page := CreateCustomPage(wpInstalling, 'Installation Checklist', '');
RichEditViewer := TRichEditViewer.Create(Page);
RichEditViewer.Width := Page.SurfaceWidth;
RichEditViewer.Height := Page.SurfaceHeight;
RichEditViewer.Parent := Page.Surface;
RichEditViewer.ScrollBars := ssVertical;
RichEditViewer.UseRichEdit := True;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep=ssPostInstall then RichEditViewer.RTFText := 'STUFF';
end;
Worthwhile to note, the page itself doesn't even need to be global.