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

Windows 64位平台调用EnumFontFamiliesEx枚举字体出现访问冲突如何解决

问题原因

报错是64位环境下回调函数签名不匹配导致的,32位下可以正常运行属于巧合兼容:

  • EnumFontFamiliesEx要求的回调函数前两个参数是结构体指针,你代码里用var引用传递,32位下引用的底层实现和指针刚好兼容,64位下调用约定导致参数地址错位
  • 回调函数第四个参数是LPARAM类型,你定义成Pointer在部分场景下也会触发长度不匹配
  • 你把ListBox1.Items(实际为TStrings子类)强制转换为TStringList存在类型不匹配风险

修复代码

只需要修改回调函数的定义即可:

procedure TForm1.Button1Click(Sender: TObject);

  // 修正回调函数签名:参数用指针、返回值用BOOL、第四个参数类型为LPARAM
  function EnumFontFamExProc(LogFont: PEnumLogFontEx; TextMetric: PNewTextMetric; FontType: Integer; Data: LPARAM): BOOL; stdcall;
  var
    Strings: TStrings;
    TempFaceName: String;
    FontTypeObject: TFontTypeObject;
  begin
    Strings := TStrings(Data);
    TempFaceName := LogFont.elfLogFont.lfFaceName;

    if (Strings.IndexOf(TempFaceName) = -1) then
    begin
      FontTypeObject:= TFontTypeObject.Create;
      FontTypeObject.FtoFontType:= FontType;
      FontTypeObject.FtoFlags:= TextMetric.ntmFlags;
      Strings.AddObject(TempFaceName, FontTypeObject);
    end;
    Result := True;
  end;

var
  DC: HDC;
  LogFont: TLogFont;
begin
  DC:= GetDC(0);
  try
    FillChar(LogFont, SizeOf(LogFont), 0);
    LogFont.lfCharSet:= DEFAULT_CHARSET;
    LogFont.lfFaceName:= '';
    LogFont.lfPitchAndFamily:= 0;
    EnumFontFamiliesEx(DC, LogFont, @EnumFontFamExProc, LPARAM(ListBox1.Items), 0);
    ListBox1.Sorted:= TRUE;
  finally
    ReleaseDC(0, DC);
  end;
end;

补充说明

32位下没有触发报错是因为32位stdcall约定的参数传递规则、栈对齐逻辑刚好掩盖了签名不匹配的问题,64位下微软x64调用约定对参数长度、传递方式的校验更严格,不匹配的签名会直接触发访问冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:18:00