带 VCL 样式的 Inno Setup 语言选择器

2023-12-31

有没有办法将语言选择器(Inno Setup)与VCL样式一起使用?如何?


出现“选择安装语言”对话框之前叫做。因此您无法加载对话框的皮肤。


作为解决方法,您可以实现自己的“语言”对话框,并从InitializeSetup。这样自定义对话框就会被换肤。用户选择语言后,您可以使用以下命令重新启动安装程序加载所选语言。

确保通过设置禁用标准语言对话框ShowLanguageDialog https://jrsoftware.org/ishelp/index.php?topic=setup_showlanguagedialog to no.

[Setup]
ShowLanguageDialog=no

[Files]
Source: "skin.vsf"; Flags: dontcopy
Source: "VclStylesInno.dll"; Flags: dontcopy

[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"
Name: "cs"; MessagesFile: "compiler:Languages\Czech.isl"
[Code]

procedure LoadVCLStyle(VClStyleFile: String);
  external 'LoadVCLStyleW@files:VclStylesInno.dll stdcall setuponly';
procedure UnLoadVCLStyles;
  external 'UnLoadVCLStyles@files:VclStylesInno.dll stdcall setuponly';

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
  external '[email protected] /cdn-cgi/l/email-protection stdcall';
  
procedure SelectLanguage();
var
  LanguageForm: TSetupForm;
  CancelButton: TNewButton;
  OKButton: TNewButton;
  LangCombo: TNewComboBox;
  SelectLabel: TNewStaticText;
  Languages: TStrings;
  Params: string;
  Instance: THandle;
  P, I: Integer;
  S, L: string;
begin
  Languages := TStringList.Create();

  Languages.Add('en=English');
  Languages.Add('cs='+#$010C+'e'+#$0161+'tina');

  LanguageForm := CreateCustomForm;

  LanguageForm.Caption := SetupMessage(msgSelectLanguageTitle);
  LanguageForm.ClientWidth := ScaleX(297);
  LanguageForm.ClientHeight := ScaleY(125);
  LanguageForm.BorderStyle := bsDialog;
#if Ver < 0x06000000
  LanguageForm.Center;
#endif

  CancelButton := TNewButton.Create(LanguageForm);
  CancelButton.Parent := LanguageForm;
  CancelButton.Top := ScaleY(93);
  CancelButton.Width := ScaleY(75);
  CancelButton.Left := LanguageForm.ClientWidth - CancelButton.Width - ScaleX(16);
  CancelButton.Height := ScaleY(23);
  CancelButton.TabOrder := 3;
  CancelButton.ModalResult := mrCancel;
  CancelButton.Caption := SetupMessage(msgButtonCancel);

  OKButton := TNewButton.Create(LanguageForm);
  OKButton.Parent := LanguageForm;
  OKButton.Top := CancelButton.Top;
  OKButton.Width := CancelButton.Width;
  OKButton.Left := CancelButton.Left - OKButton.Width - ScaleX(8);
  OKButton.Height := CancelButton.Height;
  OKButton.Caption := SetupMessage(msgButtonOK);
  OKButton.Default := True
  OKButton.ModalResult := mrOK;
  OKButton.TabOrder := 2;

  LangCombo := TNewComboBox.Create(LanguageForm);
  LangCombo.Parent := LanguageForm;
  LangCombo.Left := ScaleX(16);
  LangCombo.Top := ScaleY(56);
  LangCombo.Width := LanguageForm.ClientWidth - ScaleX(16) * 2;
  LangCombo.Height := ScaleY(21);
  LangCombo.Style := csDropDownList;
  LangCombo.DropDownCount := 16;
  LangCombo.TabOrder := 1;

  SelectLabel := TNewStaticText.Create(LanguageForm);
  SelectLabel.Parent := LanguageForm;
  SelectLabel.Left := LangCombo.Left;
  SelectLabel.Top := ScaleY(8);
  SelectLabel.Width := LangCombo.Width;
  SelectLabel.Height := ScaleY(39);
  SelectLabel.AutoSize := False
  SelectLabel.Caption := SetupMessage(msgSelectLanguageLabel);
  SelectLabel.TabOrder := 0;
  SelectLabel.WordWrap := True;

  for I := 0 to Languages.Count - 1 do
  begin
    P := Pos('=', Languages.Strings[I]);
    L := Copy(Languages.Strings[I], 0, P - 1);
    S := Copy(Languages.Strings[I], P + 1, Length(Languages.Strings[I]) - P);
    LangCombo.Items.Add(S);
    if L = ActiveLanguage then
      LangCombo.ItemIndex := I;
  end;

  // Restart the installer with the selected language
  if LanguageForm.ShowModal = mrOK then
  begin
    // Collect current instance parameters
    for I := 1 to ParamCount do
    begin
      S := ParamStr(I);
      // Unique log file name for the elevated instance
      if CompareText(Copy(S, 1, 5), '/LOG=') = 0 then
      begin
        S := S + '-localized';
      end;
      // /SL5 switch is an internal switch used to pass data
      // from the master Inno Setup process to the child process.
      // As we are starting a new master process, we have to remove it.
      // This should not be needed since Inno Setup 6.2,
      // see https://groups.google.com/g/innosetup/c/pDSbgD8nbxI
      if CompareText(Copy(S, 1, 5), '/SL5=') <> 0 then
      begin
        Params := Params + AddQuotes(S) + ' ';
      end;
    end;

    L := Languages.Strings[LangCombo.ItemIndex];
    P := Pos('=', L);
    L := Copy(L, 0, P-1);

    // ... and add selected language
    Params := Params + '/LANG=' + L;

    Instance :=
      ShellExecute(0, '', ExpandConstant('{srcexe}'), Params, '', SW_SHOW);
    if Instance <= 32 then
    begin
      S := 'Running installer with the selected language failed. Code: %d';
      MsgBox(Format(S, [Instance]), mbError, MB_OK);
    end;
  end;
end;

function InitializeSetup(): Boolean;
var
  Language: string;
begin
  ExtractTemporaryFile('skin.vsf');
  LoadVCLStyle(ExpandConstant('{tmp}\skin.vsf'));

  Result := True;

  if WizardSilent then
  begin
    Log('Silent installation, keeping the default language');
  end
    else
  begin
    Language := ExpandConstant('{param:LANG}');
    if Language = '' then
    begin
      Log('No language specified, showing language dialog');
      SelectLanguage();
      Result := False;
      Exit;
    end
      else
    begin
      Log('Language specified, proceeding with installation');
    end;
  end;
end;

procedure DeinitializeSetup();
begin
  UnLoadVCLStyles;
end;

安装程序重新启动代码基于让 Inno Setup 安装程序仅在需要时请求权限提升 https://stackoverflow.com/q/21556853/850848.


请注意,如果您想允许父进程等待安装完成,则可能需要调整代码。尽管在这种情况下您可能会使用静默安装,但代码可以正确处理。


这种黑客解决方案会导致调试器出现问题:调试自行重生的 Inno Setup 安装程序 https://stackoverflow.com/q/65389216/850848.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带 VCL 样式的 Inno Setup 语言选择器 的相关文章

随机推荐

  • Angular 2 动态页眉和页脚

    以下是我的 app component html 中包含的内容
  • 该语句没有返回结果集。 Java错误

    我正在尝试使用 JDBC 从 java 表中删除数据 首先 我计算行数并确保表不为空 然后截断数据 这是我正在使用的代码 Class forName com microsoft sqlserver jdbc SQLServerDriver
  • jdbc 驱动程序“org.gjt.mm.mysql.Driver”的用途是什么?

    在接手一位同事的项目后 我注意到他使用 org gjt mm mysql Driver 作为 MySQL 5 的 jdbc 驱动程序 而不是更常见的 com mysql jdbc Driver 它们都包含在我在 Maven 中心找到的驱动程
  • 员工 ID 的标准正则表达式

    我需要员工的标准正则表达式就像 EMP015 015EMP EMP 015 E 015 EMP 015 EMP VIS EMP 056 基本上应该允许 or or or 字母数字字符之间 状况 第一个字符不应该是 or or or 员工 I
  • 如何按单元格中的第一个字符过滤范围?

    如果 cell Text 以 A 开头 我想按 column1 过滤 multipleColumnRange rng01 Columns 1 AutoFilter Field 1 Criteria1 firstCharacter A Vis
  • 与正常模式下正确设置的回车符相比,为什么 fprintf 在文本模式下的行为不同?

    下面的问题与其说是一个问题 不如说是一个好奇心 我绊倒了这个问题 https stackoverflow com q 6536599 2605073 提供了两个似乎相同的不同答案 但他们不是 这让我思考 想象一个system调用会回显两行
  • 在 Windows 机器上运行 python 与在 Linux 上运行 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对学习 python 很感兴趣 但我的 Linux 技能很糟糕 我想使用 python 和 django 开发一个中型到大型 Web
  • 获取 R 中向量每 10 步的平均值[重复]

    这个问题在这里已经有答案了 我有一个值向量 1 0 0 4 1 0 0 1 1 1 0 1 0 0 2 0 0 17 1 2 0 2 0 1 1 1 0 1 1 0 0 0 0 0 33 0 2 0 4 2 0 0 1 1 0 0 0 1
  • Graphite只会显示过去24小时的数据

    以下是过去 24 小时的统计数据显示 在 Graphite Composer 中 以下是 过去 14 天 的统计数据显示 那里没有太大区别 我无法说服 Graphite 显示过去 24 小时内任何时间段的任何数据 以下是来自的相关条目sto
  • Google API Gateway:在标头中提供 API 密钥

    我正在尝试设置 Google API Gateway 以使用调用者在标头中发送的 API 密钥 我的 api 配置 yaml 如下所示 securityDefinitions api key header type apiKey name
  • PyLint 无法识别 cv2 成员

    我正在 opencv 项目上运行 pylint 并且在 VS 代码中收到许多有关成员不存在的 pylint 错误 示例代码 import cv2 cv2 imshow 得到的错误 不过 代码运行正确 没有任何错误 版本 pylint 1 8
  • GIT Xcode - 更改原点

    如何更改 GIT 存储库中的原始 url 我不想添加新的存储库 我想换旧的 请帮帮我 我找到了添加新选项但不更改现有选项的选项 Thanks 我认为你不能从 XCode4 中做到这一点 就像许多其他事情一样 Do git remote se
  • 使用下拉菜单创建虚线图

    您好 我有一个 excel 文件 如下所示 其中有三个不同的服务器 A B C 我正在尝试构建一个带有下拉菜单的仪表板应用程序 可以选择所需的服务器并显示每个服务器的 CPU 使用情况和内存使用情况的图表 我尝试从 Dash 官方网站修改以
  • 使用按钮清除多选(角primeng涡轮表)

    是否可以通过按钮远程清除多选 或多个多选 我正在使用 primeng multiselect 和 Turbo table 我已经多次看到这个问题 但没有选择答案 以下是我的多选 span span
  • 如何在yii2中进行ajax调用?

    在 yii 1 14 版本中我们使用 CHtml ajax链接 对于 ajax 调用 在 yii2 中怎么样 你可以像这样创建一个ajax链接 Html a Your Link name controller action title gt
  • 缺少带有 .otf 的内容类型标头字体

    我使用 Laravel 框架 但是在 chrome 控制台中发生了这个错误并且font family不工作 无法加载资源 服务器响应状态为 500 缺少 Content Type 标头 In css font face font famil
  • 使用 PyDrive 上传 XLSX 并将其转换为 Google Sheets

    我正在尝试将 xlsx 文件上传到 Google 云端硬盘 我可以上传它 但是 当我们尝试在云端硬盘中打开同一文件时 必须使用 Google 表格打开它 因此 它会创建一个同名的新文件并消耗驱动器空间 我想我需要在上传时更改 MimeTyp
  • 不同IPC机制的使用

    我是一名 C 程序员 我想知道一个实时场景 我们可以使用不同的 IPC 机制 例如 PIPE 命名 共享内存 我大致知道在哪里可以使用套接字和消息队列 但对于 PIPE Named PIPE 和共享内存我没有任何想法 这只是为了了解不同的
  • 如何将elasticquery转换为kibana URL

    我正在使用 kibana 6 仪表板来显示可视化 我有一个如下所示的弹性查询 它需要传入 kibana 仪表板 URL query bool minimum should match 1 should match phrase jt tax
  • 带 VCL 样式的 Inno Setup 语言选择器

    有没有办法将语言选择器 Inno Setup 与VCL样式一起使用 如何 出现 选择安装语言 对话框之前叫做 因此您无法加载对话框的皮肤 作为解决方法 您可以实现自己的 语言 对话框 并从InitializeSetup 这样自定义对话框就会