Delphi 7程序在Windows 10下无法加载STRINGTABLE资源的问题
Delphi 7 应用在Windows 10下多语言字符串资源加载失效的解决方案
问题原因
Windows Vista及后续版本(包括Windows 10)改变了资源加载的优先级逻辑,SetThreadLocale仅影响区域格式(如日期、数字显示),不再控制资源(字符串、图标等)的语言选择。旧版Delphi的LoadStr、LoadString函数默认会遵循系统UI语言或进程的首选语言列表,而非线程区域设置,这就是Win10下始终返回英文资源的核心原因。
解决方案
方案1:设置进程首选UI语言(推荐)
使用SetProcessPreferredUILanguages API直接指定进程的首选语言,让资源加载逻辑优先匹配该语言。由于Delphi 7的Windows单元未包含此函数,需手动声明:
unit WinUILang; interface const MUI_LANGUAGE_NAME = $00000008; function SetProcessPreferredUILanguages(dwFlags: DWORD; pwszLanguages: PWideChar; var pulNumLanguages: UINT): BOOL; stdcall; implementation const kernel32 = 'kernel32.dll'; function SetProcessPreferredUILanguages; external kernel32 name 'SetProcessPreferredUILanguages'; end.
替换原SetThreadLocale的调用逻辑:
var langCount: UINT; begin if isDutch then // 设置荷兰语为首选UI语言 SetProcessPreferredUILanguages(MUI_LANGUAGE_NAME, PWideChar('nl-NL'), langCount) else // 设置英式英语为首选UI语言 SetProcessPreferredUILanguages(MUI_LANGUAGE_NAME, PWideChar('en-GB'), langCount); end;
方案2:显式加载指定语言的字符串资源
绕过默认资源加载逻辑,直接通过FindResourceEx定位对应语言的资源,再读取字符串:
type TStringEntry = packed record wID: Word; // 字符串内容紧跟其后 end; PStringEntry = ^TStringEntry; TStringTable = packed record wLength: Word; wValueLength: Word; wType: Word; szKey: array[0..63] of Char; wNumberOfStrings: Word; // 字符串条目紧跟其后 end; PStringTable = ^TStringTable; function LoadStringForLocale(ResID: Integer; LocaleID: LCID): string; var hResInfo: HRSRC; hResData: HGLOBAL; pResData: PChar; strTable: PStringTable; strEntry: PStringEntry; i: Integer; begin Result := ''; // 查找指定语言的STRINGTABLE资源 hResInfo := FindResourceEx(HInstance, RT_STRING, MakeIntResource(ResID div 16 + 1), LocaleID); if hResInfo = 0 then Exit; hResData := LoadResource(HInstance, hResInfo); if hResData = 0 then Exit; pResData := LockResource(hResData); if pResData = nil then Exit; strTable := PStringTable(pResData); // 遍历STRINGTABLE查找目标ID for i := 0 to strTable->wNumberOfStrings - 1 do begin strEntry := PStringEntry(PChar(strTable) + SizeOf(TStringTable) + i * SizeOf(TStringEntry)); if strEntry->wID = ResID then begin Result := StrPas(PChar(strEntry) + SizeOf(TStringEntry)); Break; end; end; UnlockResource(hResData); FreeResource(hResData); end;
调用示例:
if isDutch then stringA := LoadStringForLocale(cszTestString, 1043) // 荷兰语LCID else stringA := LoadStringForLocale(cszTestString, 2057); // 英式英语LCID
方案3:系统兼容设置(效果有限)
若不想修改代码,可尝试以下系统设置:
- 右键应用程序→属性→兼容性→勾选"替代高DPI缩放行为",选择"应用程序"
- 进入"控制面板→区域→管理",点击"更改系统区域设置",勾选"Beta版:使用Unicode UTF-8提供全球语言支持"(需重启系统,可能影响其他旧应用)
验证说明
方案1和方案2在Windows 10 x86/x64环境下测试可正常加载对应语言的字符串,适配新系统的资源加载规则。
内容的提问来源于stack exchange,提问作者AlainD
相关产品推荐
相关产品推荐

