CreateFont的charset参数到底设置了什么?
我的 Windows 上的代码页设置为 ANSI(Latin1、Windows-1252)。
我使用 CreateFont 创建字体并在 fdwCharSet 中传递 RUSSIAN_CHARSET
这就是我的经历:
- 使用此字体的 Windows 控件(例如 Static)忽略字体的字符集:传递给 SetWindowTextA 的字符串以拉丁字符显示
- 在选择此字体后DC、GDI 文本函数 (Ext)TextOutA 和 DrawTextA 使用字体的字符集。传递给它们的字符串以西里尔字母显示。
为什么?何时考虑字体的字符集参数,何时忽略它?我可以强制 Windows 控件使用字体的字符集吗?
The code page on my Windows is set to ANSI (Latin1, Windows-1252).
I create a font with CreateFont and pass RUSSIAN_CHARSET in fdwCharSet
This is what I experience:
- Windows controls (like a Static for example) using this font ignore the font's character set: the string passed to SetWindowTextA is displayed with Latin characters
- After selecting this font on the DC, GDI text functions (Ext)TextOutA and DrawTextA use the character set of the font. Strings passed to them are displayed with cyrillic letters.
Why? When is the charset parameter of the font taken into account and when is it ignored? Can I force windows controls to use the font's character set?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您必须将文本转换为 Unicode 并调用
SetWindowTextW()
而不是SetWindowTextA()
。确保窗口的类是通过
RegisterClassW()
而不是RegisterClassA()
注册的。这才是真正决定窗口是否为 Unicode 的因素。您可以使用IsWindowUnicode()
来验证窗口是否确实是 Unicode。确保将未处理的消息传递给
DefWindowProcW()
而不是DefWindowProcA()
。或者,如果窗口是一个对话框,只需确保它是使用
CreateDialogW()
或DialogBoxParamW()
创建的。You will have to convert the text to Unicode and call
SetWindowTextW()
instead ofSetWindowTextA()
.Make sure the window's class is registered with
RegisterClassW()
and notRegisterClassA()
. This is what really determines if a window is Unicode. You can useIsWindowUnicode()
to verify that the window is really Unicode.Make sure you pass unhandled messages to
DefWindowProcW()
and notDefWindowProcA()
.Or, if the window is a dialog, just make sure it is created with
CreateDialogW()
orDialogBoxParamW()
.正在发生的事情是这样的:
"\xC4\xEE\xE1\xF0\xEE\xE5 xF3\xF2\xF0\xEE"
之类的内容调用 SetWindowText。我尝试想出一个最小的方法来完成你需要的事情,但我失败了。我的第一个想法是自己进行转换并直接调用 SetWindowTextW:
但这不起作用。我怀疑,由于该窗口是作为 ANSI 窗口创建的,因此 Unicode 字符串会转换回 ANSI(再次假设代码页错误),然后您会得到问号而不是拉丁语废话。
我认为您必须转换为 Unicode 应用程序,或者仅使用设置为 1251 的默认代码页运行。
更新:如果您控制窗口的创建(例如,您调用 CreateWindow直接而不是让对话框实例化控件),那么您可以通过直接调用 CreateWindowW 并为重要的控件创建一个 Unicode 窗口来完成上述工作。
Here is what is happening:
"\xC4\xEE\xE1\xF0\xEE\xE5 xF3\xF2\xF0\xEE"
.I tried coming up with a minimal way to do what you need, but I failed. My first idea was to do the conversion yourself and call SetWindowTextW directly:
But this doesn't work. I suspect that since the window was created as an ANSI window, the Unicode string is converted back to ANSI (assuming the wrong code page again), and then you get question marks instead of Latin nonsense.
I think you're going to have to convert to a Unicode app, or only run with the default code page set to 1251.
Update: If you control the creation of the window (e.g., you call CreateWindow directly rather than having a dialog box instantiate the controls), then you can probably make the above work by calling CreateWindowW directly and creating a Unicode window for the controls that matter.
>我可以强制 Windows 控件使用字体的字符集吗?
据我所知不,你不能。
SetWindowTextA 只是将参数转换为 Unicode,然后调用 SetWindowTextW:Windows 内核、shell 和 GDI 都是 unicode。
要将参数转换为 Unicode,SetWindowTextA 使用 Window 区域选项中的设置(“非 Unicode 程序的语言”)。
>Can I force windows controls to use the font's character set?
AFAIK no, you can't.
SetWindowTextA just converts the argument to Unicode, then calls SetWindowTextW: both windows kernel, shell, and GDI are unicode.
To convert the argument to Unicode, SetWindowTextA uses the setting from Window's regional options ("Language for non-Unicode programs").
考虑挂钩 gdi32full.dll GetCodePage 以选择您需要的代码页。例如 CP_UTF8。它具有单指针参数,返回单个 DWORD(代码页)和 stdcall 调用约定。
Consider hooking gdi32full.dll GetCodePage to select the code page that you need. CP_UTF8 for example. It has single pointer param, returns single DWORD (the code page) and stdcall calling convention.