【发布时间】:2011-01-16 01:33:57
【问题描述】:
我需要在我的原生 C++ Win32 GUI 应用程序中绘制一列垂直文本(在日语中 - 它是从上到下而不是从左到右绘制的)。我浏览了 MSDN,只发现如何绘制从右到左的文本。
除了单独绘制每个字符之外,如何输出从上到下的文本?
【问题讨论】:
标签: user-interface winapi visual-c++ fonts
我需要在我的原生 C++ Win32 GUI 应用程序中绘制一列垂直文本(在日语中 - 它是从上到下而不是从左到右绘制的)。我浏览了 MSDN,只发现如何绘制从右到左的文本。
除了单独绘制每个字符之外,如何输出从上到下的文本?
【问题讨论】:
标签: user-interface winapi visual-c++ fonts
直接的 Win32 API 无法以这种方式绘制(未旋转的)垂直文本(使用任意字体),一次只能绘制 1 个字符。
您可以使用GDI+ 进行更复杂的文本输出 但这可能也不是您想要的,因为文本将是垂直的,但字符也会旋转。
同样,您可以使用 lfEscapement 值为 900 或 2700 的 CreateFont 来获取 rotated 文本,但这会旋转所有内容。所以这也无济于事。
要进行从上到下的日文绘图,您希望字符不旋转,但每个字符的放置在 Y 中而不是在 X 中前进。Windows 没有对所有字体执行此操作的 API。 (您可以从右到左和从左到右,但不能从上到下)。
理论上,创建一个方向为 900 且擒纵机构为 2700 的字体可以满足您的要求,但如果您设置了擒纵机构,那么大多数字体的方向都会被忽略。对于日文字体,这可能会有所不同。值得花一些时间来玩。 (有关这方面的更多信息,请参阅附录)
我认为您最好的选择可能是使用ExtTextOut 一次绘制一个角色的循环,这使您可以完全控制每个角色的位置。
如果您使用 ETO_OPAQUE 绘制列中的第一个字符,而不是绘制所有其他字符,那么您可以在需要时垂直调整字符间距。
Roygbiv 指出一篇有趣的文章说,当您使用 lfEscapement 值为 2700 的字体时,名称以 @ 开头的字体与其他字体的行为不同,这些特殊字体会在页面向下移动的同时产生直立字符。因此,虽然没有办法为任意字体做你想做的事,但你可以使用某些字体让它工作。
出于好奇,我编写了一个小型控制台应用程序来枚举字体并列出名称。我的 Windows Server 2003 机器没有名称以 @ 开头的字体。但是我的 Windows 7 机器有一些。虽然所有似乎都是中文字体,但我在默认的 Windows 7 Ultimate 安装中看不到日文字体。
【讨论】:
在 Win32 中,使用 LOGFONT 结构的 lfEscapement 成员来定义字体的旋转:
LOGFONT LogFont
LogFont.lfEscapement = 900; // 90 degreees rotated text
... // Many more initializations
HFONT newFont = CreateFontIndirect(LogFont);
SelectObject(hdc, newFont);
char tx[255];
strcpy(tx, "vertical text");
TextOut(hdc, x, y, tx, strlen(tx)); // draw a vertical font
有关更多信息,请参阅LOGFONT 结构和CreateFontIndirect 函数的在线帮助
【讨论】:
只是一个想法:
您是否尝试过使用 DrawText 或 DrawTextEx 使用非常窄的矩形,只适合最宽的字符?
【讨论】:
这个库使用的方法听起来很慢,但如果确实需要,似乎提供了源代码:
http://www.ucancode.net/faq/CDC-DrawText-Drawing-Vertical-Text.htm
您可能还会发现此讨论很有用 - http://www.eggheadcafe.com/forumarchives/win32programmergdi/Aug2005/post23542233.asp - 显然您需要一种垂直字体(以 @ 开头的字体),其余部分由 API 处理。
【讨论】:
作为一种快速破解类型的答案,如果您使用标准控件(例如 CEdit)并在每个键入的字符后插入一个换行符会发生什么?
【讨论】:
使用lfEscapement(如有必要,lfOrientation)在许多方面都优于使矩形宽度最小(例如:荷兰语单词“wij”将“i”和“j”相邻, 因为它们的组合宽度小于 'w'),或者在每个字符后插入换行符。
【讨论】:
HFONT gui_font = CreateFont( -MulDiv( 9, GetDeviceCaps( GetDC( hWnd ), LOGPIXELSY ), 72 ),
0,
900, // here
0,
FW_THIN, 0, 0, 0,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH,
L"Segoe UI" );
【讨论】: