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

Win64下DrawText函数异常行为:为何需临时变量?

Win64环境下DrawText调用需临时变量的原因

我有一个包含单个项目'ABC'的ListBox,以下代码在Win32环境下运行正常:

h := DrawText(ListBox1.Canvas.Handle, PChar(ListBox1.Items[0]), -1, R, DT_CALCRECT);

执行该行代码后,h = 19,结果正确。但在Win64环境下运行相同代码时返回h = 0,调用SysErrorMessage(GetLastError)返回“操作已成功完成”。

若将代码修改为以下形式,则在Win32和Win64环境下均可正常运行,修改后Win32和Win64环境下h = 19:

s := ListBox1.Items[0];
h := DrawText(ListBox1.Canvas.Handle, PChar(s), -1, R, DT_CALCRECT);

原因分析

核心差异来自64位Delphi的字符串生命周期管理机制:

  • 在32位Delphi中,ListBox1.Items[0]返回的是字符串的直接引用,PChar()强制转换后能拿到有效内存指针,DrawText可以正常读取文本内容完成计算。
  • 但在64位Delphi里,ListBox1.Items[0]返回的是临时字符串实例,它的生命周期仅局限于当前表达式内部。当直接把PChar(ListBox1.Items[0])作为参数传给DrawText时,由于表达式求值顺序的问题,这个临时字符串可能在DrawText开始执行前就被销毁了——导致传入的指针指向无效内存,DrawText无法正确读取文本,最终返回0。
  • 用临时变量s接收ListBox1.Items[0]后,字符串的生命周期被延长到变量s的作用域内,PChar(s)指向的内存在DrawText执行期间始终有效,因此能正确计算出文本高度。

至于GetLastError返回“操作已成功完成”,是因为DrawText检测到指针无效时,并未触发系统级别的错误,只是返回0表示计算失败,此时系统错误码仍保留着之前操作的成功状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:10:31