You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过编程方式设置Inno Setup向导字体及DialogFontName?

解决方案:通过脚本动态设置对话框字体

由于Inno Setup 5.6.1中[LangOptions]的DialogFontName和[Setup]的DefaultDialogFontName确实不支持运行时常量展开,无法直接通过配置节动态切换字体。要实现非XP系统使用Segoe UI字体的需求,需要通过Windows API在脚本中动态替换对话框及控件的字体。

实现步骤

  • 判断系统版本:通过GetWindowsVersion函数识别是否为XP系统(版本号5.1)。
  • 创建目标字体:在非XP系统中创建Segoe UI字体对象。
  • 替换现有窗口字体:枚举主窗口及所有子控件,发送WM_SETFONT消息设置新字体。
  • 处理后续窗口:通过窗口钩子捕获新创建的对话框,自动应用字体设置。

完整脚本代码

const
  WM_SETFONT = $0030;
  GWL_WNDPROC = -4;
  LOGPIXELSX = 88;

type
  TFNWndProc = function(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

var
  OldWndProc: TFNWndProc;
  SegoeUIFont: HFONT;

function EnumChildProc(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
begin
  SendMessage(hWnd, WM_SETFONT, lParam, 1);
  Result := True;
end;

procedure SetFontToWindow(hWnd: HWND; Font: HFONT);
begin
  SendMessage(hWnd, WM_SETFONT, Font, 1);
  EnumChildWindows(hWnd, @EnumChildProc, Font);
end;

function NewWndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  if Msg = WM_INITDIALOG then
  begin
    SetFontToWindow(hWnd, SegoeUIFont);
  end;
  Result := OldWndProc(hWnd, Msg, wParam, lParam);
end;

function InitializeSetup(): Boolean;
var
  WinVer: TWindowsVersion;
  DC: HDC;
  LogPixelsX: Integer;
  FontHeight: Integer;
begin
  Result := True;
  GetWindowsVersion(WinVer);
  // 仅在非XP系统(版本号≠5)启用Segoe UI
  if WinVer.Major <> 5 then
  begin
    DC := GetDC(0);
    LogPixelsX := GetDeviceCaps(DC, LOGPIXELSX);
    ReleaseDC(0, DC);
    // 计算与Inno默认8pt字体匹配的高度
    FontHeight := -MulDiv(8, LogPixelsX, 72);
    // 创建Segoe UI字体
    SegoeUIFont := CreateFont(FontHeight, 0, 0, 0, FW_NORMAL, False, False, False, DEFAULT_CHARSET,
      OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH or FF_DONTCARE, 'Segoe UI');
    if SegoeUIFont <> 0 then
    begin
      // 应用字体到向导主窗口
      SetFontToWindow(WizardForm.Handle, SegoeUIFont);
      // 安装窗口过程钩子,处理后续弹出的对话框
      OldWndProc := TFNWndProc(GetWindowLongPtr(WizardForm.Handle, GWL_WNDPROC));
      SetWindowLongPtr(WizardForm.Handle, GWL_WNDPROC, NativeInt(@NewWndProc));
    end;
  end;
end;

procedure DeinitializeSetup();
begin
  // 释放字体资源,避免内存泄漏
  if SegoeUIFont <> 0 then
  begin
    DeleteObject(SegoeUIFont);
  end;
end;

注意事项

  • 该方法会替换向导窗口、自定义页面及大部分标准对话框的字体,但极少数系统原生控件可能不响应WM_SETFONT消息。
  • 字体高度计算确保与Inno Setup默认的8pt字体大小一致,避免界面布局错乱。
  • 必须在DeinitializeSetup中释放字体对象,防止内存泄漏。

内容的提问来源于stack exchange,提问作者catnip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:37:08