找出 Inno Setup WizardForm 标题字体大小、字体名称和字体颜色并将 WizardForm 标题居中

Finding out Inno Setup WizardForm Caption Font Size, Font Name and Font Color and Center the WizardForm Caption

我需要找到 Inno Setup WizardForm.CaptionFont.ColorFont.SizeFont.Name 是什么,以便使用 GetTextExtentPoint32

请告诉我如何找到 WizardForm 的上述属性。 (不是系统字体属性)。我想根据我正在使用的 .cjstyles 皮肤获取 WizardForm 的当前字体信息。

而且我还想知道如何在了解这些字体信息后使用 Pascal Script 将向导 Window 标题居中。

提前致谢。

我认为这是不可能的。

ISSkin DLL window 的标题是 custom-drawn。所以 Windows 不知道字体大小,因此你不能使用 Windows API.

并且ISSkin没有导出任何函数来检索这些信息。

WizardForm 的 Window 标题属性由 ISSkin.DLL 根据您的视觉样式外观内部加载。因此,如果 Window 标题用户在控​​制面板的高级外观设置中配置了任何系统指标,例如:

Window 标题 - 字体名称 Segoe UI 和字体大小 10

加载指定的视觉样式时,所有这些都将被 ISSKin.DLL 覆盖,因为它在其 .INI 文件中具有不同的字体和字体大小配置,其由函数 LoadSkin 加载,如下所示.

procedure LoadSkin(lpszPath: String; lpszIniFileName: String);

您在此处提供的 .INI 文件几乎包含有关如何从存储在皮肤文件中的 Bitmpas 等资源加载皮肤的所有信息。


不过,您可以使用两种不同的选项将 WizardForm 标题居中。

使用 Resource Hacker:

使用 Resource Hacker,可以非常轻松地将皮肤的 Window 标题(标题)对齐设置为中心。

1.Open 使用 Resource Hacker 的视觉样式皮肤(.cjstyles 或 .msstyles)文件并查找名为 TEXTFILE.[= 的资源组29=]

2.Expand 并根据ISSkin.dll默认加载的配色方案找到.INI文件。在大多数情况下,如果您的系统字体大小为 100%(默认),它应该是正常配色方案。因此,单击名称中包含 NORMAL 一词的 .INI 文件,如下所示:

例如,如果您的皮肤文件名称是 Elegance.cjstyles,那么具有正常配色方案的 .INI 文件应该是 NORMALELEGANCE_INI 或包含单词 NORMAL.[=29 的内容=]

3.Open 内部文本编辑器中的这个 .INI 文件带有 Resource Hacker 并找到行 Window.Caption,如下所示:

4.And 确保其 ContentAlignment 设置为 Center。如果不是默认设置,请将其更改为 Center.

现在,Window 向导的标题应该在 ISSkin.DLL 加载皮肤后居中。

注意:此居中不准确,因为居中是在标题左侧和最小化按钮之间完成的,因此即使以这种方式居中后,标题可能仍靠近左侧。


使用 Pascal 脚本 [代码] 部分:

您可以通过在其前面添加空格来使 WizardForm 标题居中。(但不推荐。)

像这样的代码将满足您的需要。

[Code]
Type
  TSize = Record
    cx, cy: Integer;
end;

function GetTextExtentPoint32(hdc: THandle; s: string; c: Integer; var Size: TSize): Boolean;
    external 'GetTextExtentPoint32W@Gdi32.dll stdcall';
function GetDC(hWnd: THandle): THandle;
    external 'GetDC@User32.dll stdcall';
function SelectObject(hdc: THandle; hgdiobj: THandle): THandle;
    external 'SelectObject@Gdi32.dll stdcall';

function AlignStringToCenter(S: String; const FontName: String; const MaxWidth, FontSize: Integer): String;
var
  SWidth, SX, NSWidth: Integer;
  SFont, SHandle: THandle;
  StringModifier: TNewStaticText;
  StringDimensions: TSize;
  SHandleEx: TForm;
begin
  if S = '' then
    RaiseException('The specified Caption is an empty String')
  else begin
    Try
      SHandleEx := TForm.Create(nil);
      StringModifier := TNewStaticText.Create(SHandleEx);
      StringModifier.Font.Name := FontName;
      StringModifier.Font.Size := FontSize;
      StringModifier.Parent := SHandleEx;
      SX := 0;
      StringModifier.Caption := S;
      SHandle := GetDC(StringModifier.Handle);
      SFont := SelectObject(SHandle, StringModifier.Font.Handle);
      GetTextExtentPoint32(SHandle, StringModifier.Caption, Length(StringModifier.Caption), StringDimensions);
      SelectObject(SHandle, SFont);
      SWidth := StringDimensions.cx;
      Repeat
        Insert(' ', S, SX);
        StringModifier.Caption := S;
        Result := S;
        SHandle := GetDC(StringModifier.Handle);
        SFont := SelectObject(SHandle, StringModifier.Font.Handle);
        GetTextExtentPoint32(SHandle, StringModifier.Caption, Length(StringModifier.Caption), StringDimensions);
        SelectObject(SHandle, SFont);
        NSWidth := StringDimensions.cx;
        SX := SX + 1;
      Until (NSWidth - SWidth) >= (MaxWidth - NSWidth);
    Finally
      StringModifier.Caption := '';
      StringModifier.Free;
      SHandleEx.Free;
      SHandleEx.Close;
    end;
  end;
end;

上面的代码不断在你想要居中的字符串前面添加空格,直到它在你给定的最大字符串宽度中正确居中,并输出添加了空格的修改后的字符串。

注意:此处的 MaxWidth 参数应该是您希望字符串居中的宽度。宽度高于您在此处指定的宽度的字符串无法正确居中。使用上述功能,无需视觉样式皮肤即可使向导 Window 标题居中。

用法:

如果你想使用此功能将向导 Window 标题居中,请像这样使用:

如果您不使用视觉样式外观:

[Code]
Const
  SM_CYSIZEFRAME = 33;
  SM_CXSMICON = 49;

function GetSystemMetrics(nIndex : Integer): Integer;  
  external 'GetSystemMetrics@User32 stdcall';

procedure InitializeWizard;
begin
  { MaxWidth = WizardForm.Width - 2 * (WizardForm.FrameWidth + WizardForm.SmallIconWidth + WizardForm.CaptionLeft + WizardForm.CaptionRight) }
  WizardForm.Caption := AlignStringToCenter(WizardForm.Caption, 'Segoe UI', WizardForm.Width - (2 * (GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXSMICON) + 10 + 10)), 9);
end;

如果您使用视觉样式皮肤:

[Code]
Const
  SM_CYSIZEFRAME = 33;
  SM_CXSMICON = 49;

function GetSystemMetrics(nIndex : Integer): Integer;  
  external 'GetSystemMetrics@User32 stdcall';

procedure InitializeWizard;
begin
  { MaxWidth = WizardForm.Width - 2 * (WizardForm.FrameWidth + WizardForm.SmallIconWidth + WizardForm.CaptionLeft + WizardForm.CaptionRight) }
  WizardForm.Caption := AlignStringToCenter('Setup - {#MyAppName}', 'Window Title Font Name of your Visual Styles Skin', WizardForm.Width - (2 * (GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXSMICON) + 10 + 10)), Window Title Font Size of your Visual Styles Skin);
end;

居中向导Window标题:

然而,居中向导 Window 使用上述功能的标题(通过添加空格破解它)会在 Windows 任务栏工具提示中造成以下不良影响:

注意:如果您使用视觉样式皮肤,WizardForm.CaptionLeft 和 CaptionRight 应随视觉样式皮肤的左字幕边距的大小而变化。