Inno Setup: change the setup language while setup is running - inno-setup

In my Setup I don't want use the standard Language Dialog form.
Instead, I want to add a combobox to the Welcome page of my Inno Setup to do the same job made by the Language Dialog, so that it's able to :
show all the languages included in the [Languages] section in the drop down list. So the user can select a language from this custom combobox.
apply the chosen language to the whole setup.
I know that this is not possible using the "normal way", because there are no functions available in Inno Setup to perform this job (!!!).
So that, I added a couple of functions to the Inno Setup compiler and I call them from my script:
function GetAvailableLanguages: TStringList: it is able to return the list of all the active languages (complete data), and it works fine.
procedure SetChosenLanguage(const I:integer): it should set the chosen language, and it does but up now only "partially". The language is changed for everything BUT the labels in all the Setup pages. So, button captions, message boxes, dialog boxes,... everything has the language set to the chosen one, but all the labels are still in the default (OS) language.
I tried to resolve using Refresh, Invalidate, Update, sending messages without any success. The label captions are still in the original default language.
The link below is a video showing my Test setup with the combobox and language changing. My default (OS) language is Italian. The video shows that even if I change the language, for example, to Deutsch, everything will change the language to Deustch BUT the labels.
http://screencast.com/t/SDI5VN67LFL
If someone has already resolved the problem please help me!

You would have to re-set all the labels one by one the same way the TWizardForm code initializes them to the initial language.
For example:
SelectTasksLabel.Caption := ExpandSetupMessage(msgSelectTasksLabel2);
See TWizardForm.Create code for more.
There's no easier way. The strings are copied to the Windows (Win32) controls, they won't magically learn that you have changed the language. You have to overwrite the strings with the new values.
For example the labels of the "Next" and "Back" buttons are updated with the language change, because they are always re-set, when a page is changed, from TWizardForm.SetCurPage:
procedure TWizardForm.SetCurPage(const NewPageID: Integer);
...
begin
...
BackButton.Caption := SetupMessages[msgButtonBack];
if CurPageID = wpReady then begin
NextButton.Caption := SetupMessages[msgButtonInstall];
CancelButton.Caption := SetupMessages[msgButtonCancel];
end else if ((CurPageID = wpPreparing) and PrepareToInstallNeedsRestart) or (CurPageID = wpFinished) then begin
NextButton.Caption := SetupMessages[msgButtonFinish];
CancelButton.Caption := SetupMessages[msgButtonCancel];
end else begin
NextButton.Caption := SetupMessages[msgButtonNext];
CancelButton.Caption := SetupMessages[msgButtonCancel];
end;
...
end;
But most other labels are static and are never updated, so they stay to the original language.

Related

Create an excel workbook/worksheet in Altium DelphiScript without installing plugins

I am currently extracting the Pin List - Pin Names in Altium Designer that uses DelphiScript (not Delphi). DelphiScript and Delphi has differences and I believe one of them is the file I/O component. According to the Altium Docs for DelphiScript, only text files and csv files can be produced. In producing an output file .csv, saving is as easy as throwing text that are comma delimited and then saving with an extension '.csv'. My problem now is how to create a .xls file without importing and/or downloading plugins/extensions like eDocEngine VCL, LibXL, TQExport4Xlsx.
Tried declaring TBook, TSheet, TgtXLSEngine or other ways to create the spreadsheet but error says it is an undeclared identifier.
Do you guys have any idea?
Report Writer Code Snippet:
Procedure BeginReportPinList(AFilename: String);
Begin
gv_FileName := AFilename + '.csv';
AssignFile(gv_FileReport, gv_FileName);
Rewrite(gv_FileReport);
End;
Procedure WriteReportDUT(AReport : String);
Begin
WriteLn(gv_FileReport, Format('%s', [AReport]));
End;
Procedure EndReport(Dummy : Boolean);
Begin
CloseFile(gv_FileReport);
End;
String Parser Code Snippet that calls above procedures:
if dutlistX.Count = 1 then
Begin
PinFilename := copy(gv_Board.FileName, 1, Pos('-05', gv_Board.FileName)-1) + '-14';
BeginReportPinList(PinFilename);
For I := 0 To finalreport.Count - 1 Do
Begin
WriteReportDUT(finalreport[I]);
End;
EndReport(0);
End;
As was mentioned in comments by #Ken White, it is very difficult to do this without third-party components.
As far as I know, XSL file has a structure of Compound File Binary Format. This type of files consisting of blocks and streams that You can manipulate. I have used this third-party software to parse such file type (actually SchDoc, but not XLS), check this question. OpenMCDF can do a trick if You have Altium running with .NET platform, like 16 version do, for example. In addition, You may use the specification of this file format based on CFB.
It is very noticeable, that some other filetypes of Altium is using that CFB file format, so it might be useful to know about OpenMCDF. I believe that XLS can be created in much handy way, than this one, but it is useful to know, how to deal with such data containers, as XLS, or SchDoc, et cetera.

Inno Setup Wizard Page onscreen placement (off-centre position)

I would like to specify that the Wizard Pages do not open in the middle of the screen by default i.e. to position them slightly off-centre using x,y coordinates (or a similar offset). This is because I call another program that also opens in the middle of the screen, obscuring the progress page. If I could open all Wizard pages offset to the left or top, for example, it would mean both windows would be visible at the same time, without having to reposition them. Is this possible and, if so, how could it be done?
Just offset the WizardForm.Left and WizardForm.Top as needed:
procedure InitializeWizard();
begin
WizardForm.Left := WizardForm.Left - ScaleX(320);
WizardForm.Top := WizardForm.Top - ScaleY(160);
end;
Or maybe:
procedure InitializeWizard();
begin
WizardForm.Left := WizardForm.Left div 2;
WizardForm.Top := WizardForm.Top div 2;
end;
It's been a while since I've used INNO, but I believe you can do this with some custom code in the [CODE] section. You'd have to create a overload to modify WizardForm..Left and WizardForm..Top as appropriate in InitializeWizard().
Check CodeDlg.iss and CodeClassess.iss in the Examples folder, and possibly the rest in there, for examples (sic) and details on how to properly set up the [CODE] section.
Useful docs: http://www.jrsoftware.org/ishelp/index.php?topic=scriptclasses

Inno Setup: WizardForm.StatusLabel color

How to change StatusLabel color for Inno Setup correctly? I've tried next options:
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpInstalling then
begin
WizardForm.StatusLabel.Font.Color := $8D7C72;
end;
end;
and
procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);
begin
WizardForm.StatusLabel.Caption := 'Installing, please wait...';
WizardForm.StatusLabel.Font.Color := $8D7C72;
end;
But it didn't help.
On the screen below, I've set color for WizardForm.StatusLabel and custom percent label. But it works only for the second one.
Also I use VclStyleInno to style my installer.
Your code (the CurPageChanged) works for me for a plain un-styled installer.
So it's probably the styling that breaks it.
Note that the StatusLabel is TNewStaticText, not TLabel. So if the TLabel works correctly, just hide the StatusLabel and create another custom TLabel instead.
Do you use TLabel or TNewStaticText?
Some time ago you mentioned you use Graphical Installer for styling (with VCL Styles). In GI you can use new TextColor property for TNewStatictext which overrides Font.Color and Color properties.
Example:
URLLabel.TextColor := clRed
TLabel has no changes so it accepts Font.Color and Color.
As turned out, all I needed to do - is re-install Inno Setuup.

Inno setup window title is corrupted (botva2.dll)

I created multi-language setup + VCL-styles, and I had a problem with standard progressbar(progressgauge) - it flickers and looks ugly overall. So I used botva2.dll with 2 png's and now it looks perfect - but the problem now is: after ImgLoad call
function ImgLoad(Wnd :HWND; FileName :PAnsiChar; Left, Top, Width, Height :integer; Stretch, IsBkg :boolean) :Longint; external 'ImgLoad#{tmp}\botva2.dll stdcall delayload';
wizardform title is corruprted, and as far as I understand its because botva2 is not unicode and it subclasses a wnd (Wizardform in my case), and as a result window title is corrupted in current language isnt a system language.
I tried creating TPanel and feeding botva a panel handle - its not working, unfortunately.
I tried adding doublebuffer to original progressgauge and making somehow look good - with no result.
Any ideas or workarounds?
PS. Summoning #TLama...

How to access texts from language files from the code section?

In Inno Setup one can access texts from the language files e.g. the following way (where CreateDesktopIcon is the text entry to look for):
[Tasks]
Name: "TaskDesktopIcon"; Description: "{cm:CreateDesktopIcon}"; Flags:
My question is how to access texts from the language files from the code section of the Inno Setup script?
I have tried the following, but the compiler will not accept the syntax:
[code]
var
pageAutoLogon: TWizardPage;
procedure CreateAutoLogonPage;
begin
pageAutoLogon := CreateCustomPage(wpSelectTasks, "{cm:AutoLogonCredentialsTitle}", "{cm:AutoLogonCredentialsDescription}");
...
Any help is appreciated!
You need to call ExpandConstant (or ExpandConstantEx) function to evaluate a constant in script code. Like this way for instance:
procedure CreateAutoLogonPage;
begin
pageAutoLogon := CreateCustomPage(wpSelectTasks, ExpandConstant('{cm:AutoLogonCredentialsTitle}'), ExpandConstant('{cm:AutoLogonCredentialsDescription}'));
...
end;
You can use the CustomMessage() function to retrieve the values from the [CustomMessages] section.
pageAutoLogon := CreateCustomPage(wpSelectTasks, CustomMessage('AutoLogonCredentialsTitle'), CustomMessage('AutoLogonCredentialsDescription'));
For normal [Messages], you can use the SetupMessage() with one of the enum values.

Resources