【问题标题】:How to draw vertical text in Windows GUI?如何在 Windows GUI 中绘制垂直文本?
【发布时间】:2011-01-16 01:33:57
【问题描述】:

我需要在我的原生 C++ Win32 GUI 应用程序中绘制一列垂直文本(在日语中 - 它是从上到下而不是从左到右绘制的)。我浏览了 MSDN,只发现如何绘制从右到左的文本。

除了单独绘制每个字符之外,如何输出从上到下的文本?

【问题讨论】:

    标签: user-interface winapi visual-c++ fonts


    【解决方案1】:

    直接的 Win32 API 无法以这种方式绘制(未旋转的)垂直文本(使用任意字体),一次只能绘制 1 个字符。

    您可以使用GDI+ 进行更复杂的文本输出 但这可能也不是您想要的,因为文本将是垂直的,但字符也会旋转。

    同样,您可以使用 lfEscapement 值为 900 或 2700 的 CreateFont 来获取 rotated 文本,但这会旋转所有内容。所以这也无济于事。

    要进行从上到下的日文绘图,您希望字符不旋转,但每个字符的放置在 Y 中而不是在 X 中前进。Windows 没有对所有字体执行此操作的 API。 (您可以从右到左和从左到右,但不能从上到下)。

    理论上,创建一个方向为 900 且擒纵机构为 2700 的字体可以满足您的要求,但如果您设置了擒纵机构,那么大多数字体的方向都会被忽略。对于日文字体,这可能会有所不同。值得花一些时间来玩。 (有关这方面的更多信息,请参阅附录)

    我认为您最好的选择可能是使用ExtTextOut 一次绘制一个角色的循环,这使您可以完全控制每个角色的位置。

    如果您使用 ETO_OPAQUE 绘制列中的第一个字符,而不是绘制所有其他字符,那么您可以在需要时垂直调整字符间距。

    附录

    Roygbiv 指出一篇有趣的文章说,当您使用 lfEscapement 值为 2700 的字体时,名称以 @ 开头的字体与其他字体的行为不同,这些特殊字体会在页面向下移动的同时产生直立字符。因此,虽然没有办法为任意字体做你想做的事,但你可以使用某些字体让它工作。

    Options for Displaying Text

    出于好奇,我编写了一个小型控制台应用程序来枚举字体并列出名称。我的 Windows Server 2003 机器没有名称以 @ 开头的字体。但是我的 Windows 7 机器有一些。虽然所有似乎都是中文字体,但我在默认的 Windows 7 Ultimate 安装中看不到日文字体。

    【讨论】:

    • 不真实 - Win32 可以做到。看我的帖子。
    【解决方案2】:

    在 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 函数的在线帮助

    【讨论】:

    • 再次阅读问题,在这种情况下旋转字符没有帮助。
    • 我收回了,据说这适用于某些字体,而不是普通的英文字体。
    【解决方案3】:

    只是一个想法: 您是否尝试过使用 DrawTextDrawTextEx 使用非常窄的矩形,只适合最宽的字符?

    【讨论】:

    • 这听起来是个坏主意,考虑到日语混合了汉字、平假名和片假名脚本。
    【解决方案4】:

    这个库使用的方法听起来很慢,但如果确实需要,似乎提供了源代码:

    http://www.ucancode.net/faq/CDC-DrawText-Drawing-Vertical-Text.htm

    您可能还会发现此讨论很有用 - http://www.eggheadcafe.com/forumarchives/win32programmergdi/Aug2005/post23542233.asp - 显然您需要一种垂直字体(以 @ 开头的字体),其余部分由 API 处理。

    【讨论】:

      【解决方案5】:

      正确答案是:

      有三种方法可以做到这一点:

      • 使用 Edit 或 RichEdit 控件呈现您的文本
      • 使用Uniscribe API
      • TextOut 函数与以at 符号(@) 开头的字体名称一起使用。

      Here 是一篇讨论其中一些方法的文章。

      幸运的是,使用 Win32,您无需编写代码来旋转字符。要在 Windows 2000 和 Windows XP 上垂直显示文本,请照常枚举可用字体,然后选择字体名称以 at 符号 (@) 开头的字体。然后创建一个 LOGFONT 结构,将擒纵机构和方向都设置为 270 度。对 TextOut 的调用与水平文本的调用相同。

      【讨论】:

        【解决方案6】:

        作为一种快速破解类型的答案,如果您使用标准控件(例如 CEdit)并在每个键入的字符后插入一个换行符会发生什么?

        【讨论】:

          【解决方案7】:

          使用lfEscapement(如有必要,lfOrientation)在许多方面都优于使矩形宽度最小(例如:荷兰语单词“wij”将“i”和“j”相邻, 因为它们的组合宽度小于 'w'),或者在每个字符后插入换行符。

          【讨论】:

            【解决方案8】:
            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" );
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-07-18
              • 1970-01-01
              • 1970-01-01
              • 2012-03-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多