【问题标题】:Finding out Inno Setup WizardForm Caption Font Size, Font Name and Font Color and Center the WizardForm Caption找出 Inno Setup WizardForm Caption 字体大小、字体名称和字体颜色并将 WizardForm Caption 居中
【发布时间】:2016-10-03 12:12:23
【问题描述】:

我需要使用 GetTextExtentPoint32 找到 Inno Setup WizardForm.CaptionFont.ColorFont.SizeFont.Name 以获取其(它是一个字符串)范围点。

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

而且我还想知道在知道这些字体信息后如何使用 Pascal 脚本将向导窗口标题居中。

提前致谢。

【问题讨论】:

  • 我不明白你需要这个做什么。你能解释一下吗?
  • 由于 Windows 不支持居中字幕,我想根据当前字体名称和大小计算 WizardForm.Caption 中空格的宽度,并在我想要的字幕前面自动添加空格以使其居中. :-(

标签: inno-setup caption pascalscript


【解决方案1】:

我认为这是不可能的。

窗口标题由 ISSkin DLL 自定义绘制。所以 Windows 不知道字体大小,因此你不能使用 Windows API。

而且 ISSkin 不会导出任何函数来检索这些信息。

【讨论】:

  • 好的,我什至不能在没有皮肤的情况下获取 WizardForm.Caption 字体信息吗?
  • @Martin 如何在设置中获取字体(默认为 Tahoma)+ GetWindowsText() 并使用 WinAPI 函数计算宽度?
  • @Slappy 你的意思是计算没有皮肤的标题范围?
  • 或者这样的事情可以使用 Resource Tuner 之类的资源编辑器完成吗?
  • 也许吧。无论如何,这会给你一个静态信息。你已经知道了,不是吗?你知道你的风格有什么字体大小,对吧?
【解决方案2】:

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

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

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

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

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


但是,您可以使用两个不同的选项将 WizardForm Caption 居中。

使用资源黑客:

使用 Resource Hacker,可以很容易地将皮肤的窗口标题(标题)对齐设置为居中。

1.使用 Resource Hacker 打开您的 Visual Styles Skin(.cjstyles 或 .msstyles)文件并查找名为 TEXTFILE 的资源组。

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

例如,如果您的皮肤文件名称是 Elegance.cjstyles,则具有 Normal 配色方案的 .INI 文件应类似于 NORMALELEGANCE_INI 或包含单词 NORMAL 的内容。

3.在Resource Hacker自带的内部文本编辑器中打开这个.INI文件,找到Window.Caption这一行,如下图:

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

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

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


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

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

这样的代码可以满足您的需要。

[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 参数应该是您想要使字符串居中的宽度。宽度大于您在此处指定的字符串无法正确居中。并且不需要视觉样式皮肤使用上述功能将向导窗口标题居中。

用法:

如果您想使用此功能使向导窗口标题居中,请按如下方式使用:

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

[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;

居中的向导窗口标题:

但是,使用上述功能将向导窗口标题居中(通过添加空格来破解它)会在 Windows 任务栏工具提示中产生以下不良影响:

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

【讨论】:

  • 效果很好!谢谢!但我仍然不知道如何以编程方式获取向导标题字体大小和名称。 :-(
  • 现在,您可以如上所述将 WizardForm 的窗口标题居中。然后您应该尝试通过 Pascal 脚本使用Resource Hacker commandline 获取视觉样式皮肤信息,例如窗口标题字体信息。再试试! ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多