如何绘制独立于 DPI 的 GDI + 文本

2024-04-04

我正在使用 GDI+ 绘制文本。我最近注意到,当 DPI 更改时,该文本会自动缩放。有没有办法让GDI+文本绘制独立于DPI?例如。我想绘制最大 20 像素的文本,无论 DPI 是多少。是否可以?这个怎么做?

下面是示例代码。我想以恒定的大小绘制第一个文本,无论 DPI 为何,而通常绘制第二个文本:

    case WM_PAINT:
    {
        inherited::WndProc(message);

        Canvas->Brush->Style = bsSolid;
        Canvas->Brush->Color = clWhite;
        Canvas->FillRect(ClientRect);

        // get GDI+ graphics from canvas
        Gdiplus::Graphics graphics(Canvas->Handle);

        // set text rendering hint
        graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintSystemDefault);

        std::auto_ptr<Gdiplus::Font>         pFont(new Gdiplus::Font(Canvas->Handle, Font->Handle));
        std::auto_ptr<Gdiplus::SolidBrush>   pBrush(new Gdiplus::SolidBrush(Gdiplus::Color(255, 0, 0, 0)));
        std::auto_ptr<Gdiplus::StringFormat> pFormat(new Gdiplus::StringFormat());

        Gdiplus::FontFamily fontFamily;
        pFont->GetFamily(&fontFamily);

        std::auto_ptr<Gdiplus::Font> pFont2(new Gdiplus::Font(&fontFamily, pFont->GetSize(),
                pFont->GetStyle(), Gdiplus::UnitPixel));
        Gdiplus::Unit test = pFont->GetUnit();
        Gdiplus::Unit test2 = pFont2->GetUnit();

        pFormat->SetAlignment(Gdiplus::StringAlignmentNear);
        pFormat->SetLineAlignment(Gdiplus::StringAlignmentNear);

        Gdiplus::StringFormatFlags flags = Gdiplus::StringFormatFlagsBypassGDI;
        //flags = (Gdiplus::StringFormatFlags)(flags | Gdiplus::StringFormatFlagsDirectionRightToLeft);
        //flags = (Gdiplus::StringFormatFlags)(flags | Gdiplus::StringFormatFlagsDirectionVertical);
        //flags = (Gdiplus::StringFormatFlags)(flags | Gdiplus::StringFormatFlagsNoWrap);
        //flags = (Gdiplus::StringFormatFlags)(flags | Gdiplus::StringFormatFlagsNoClip);
        pFormat->SetFormatFlags(flags);

        pFormat->SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter);
        pFormat->SetHotkeyPrefix(Gdiplus::HotkeyPrefixNone);

        std::wstring text = L"This is a sample code";

        Gdiplus::Unit prevPageUnit = graphics.GetPageUnit();

        try
        {
            graphics.SetPageUnit(Gdiplus::UnitPixel);

            // draw text
            graphics.DrawString(text.c_str(), text.length(), pFont2.get(), Gdiplus::RectF(ClientRect.Left,
                    ClientRect.Top, ClientWidth, ClientHeight), pFormat.get(), pBrush.get());
        }
        __finally
        {
            graphics.SetPageUnit(prevPageUnit);
        }

        // draw text 2
        graphics.DrawString(text.c_str(), text.length(), pFont.get(), Gdiplus::RectF(ClientRect.Left,
                ClientRect.Top + 25, ClientWidth, ClientHeight), pFormat.get(), pBrush.get());

        return;
    }

Regards


我想提一些与你的问题稍微无关的事情。你不应该使用Graphics.DrawString不再是 GDI+ 了。它在 .NET 2 中已被弃用。相反,Microsoft 创建了TextRenderer.DrawString.

在 .NET 中绘制文本有两种方法:

  • GDI+ (graphics.MeasureString and graphics.DrawString)
  • GDI (TextRenderer.MeasureText and TextRenderer.DrawText)

在 .NET 1.1 中使用的一切GDI+用于文本渲染。但也出现了一些问题 https://blogs.msdn.microsoft.com/cjacks/2006/05/19/gdi-vs-gdi-text-rendering-performance/:

  • GDI+ 的无状态特性会导致一些性能问题,其中设备上下文将被设置,然后在每次调用后恢复原始状态。
  • Windows/Uniscribe 和 Avalon (Windows Presentation Foundation) 的国际文本整形引擎已更新多次,但尚未更新 GDI+,这导致对新语言的国际渲染支持不具有相同的质量水平。

所以他们知道他们想要更改 .NET 框架以停止使用GDI+的文本渲染系统,并使用GDI。起初他们希望能够简单地改变:

graphics.DrawString

打电话给旧的DrawTextAPI 而不是 GDI+。但他们无法使文本换行和间距与 GDI+ 完全匹配。所以他们被迫保留graphics.DrawString调用 GDI+(兼容性原因;调用的人graphics.DrawString会突然发现他们的文本没有像以前那样换行)。

一个新的静态TextRenderer创建类是为了包装 GDI 文本渲染。它有两种方法:

TextRenderer.MeasureText
TextRenderer.DrawText

Note:
- TextRenderer是 GDI 的包装
- graphics.DrawString仍然是 GDI+ 的包装


然后是如何处理所有现有 .NET 控件的问题,例如:

  • Label
  • Button
  • TextBox

他们想把它们转过来使用TextRenderer(即 GDI),但他们必须小心。可能有人像在 .NET 1.1 中那样依赖控件绘制。于是就诞生了“兼容的文本渲染".

默认情况下,应用程序中的控件的行为就像在 .NET 1.1 中一样(它们是“兼容的").

You turn off通过调用兼容模式:

Application.SetCompatibleTextRenderingDefault(false);

这使您的申请更好、更快,并获得更好的国际支持。总结:

SetCompatibleTextRenderingDefault(true)  SetCompatibleTextRenderingDefault(false)
=======================================  ========================================
 default                                  opt-in
 bad                                      good
 the one we don't want to use             the one we want to use
 uses GDI+ for text rendering             uses GDI for text rendering
 graphics.MeasureString                   TextRenderer.MeasureText
 graphics.DrawString                      TextRenderer.DrawText
 Behaves same as 1.1                      Behaves *similar* to 1.1
                                          Looks better
                                          Localizes better
                                          Faster

注意 GDI+ 之间的映射也很有用TextRenderingHint以及相应的LOGFONT Quality http://msdn.microsoft.com/en-us/library/dd145037%28v=vs.85%29.aspx用于GDI字体绘制:

TextRenderingHint           mapped by TextRenderer to LOGFONT quality
========================    =========================================================
ClearTypeGridFit            CLEARTYPE_QUALITY (5) (Windows XP: CLEARTYPE_NATURAL (6))
AntiAliasGridFit            ANTIALIASED_QUALITY (4)
AntiAlias                   ANTIALIASED_QUALITY (4)
SingleBitPerPixelGridFit    PROOF_QUALITY (2)
SingleBitPerPixel           DRAFT_QUALITY (1)
else (e.g.SystemDefault)    DEFAULT_QUALITY (0)

Samples

以下是 GDI+ (graphics.DrawString) 与 GDI (TextRenderer.DrawText) 文本渲染的一些比较:

GDI+: TextRenderingHintClearTypeGridFit, GDI: CLEARTYPE_QUALITY:

GDI+: TextRenderingHintAntiAlias, GDI: ANTIALIASED_QUALITY:

GDI+: TextRenderingHintAntiAliasGridFit, GDI: 不支持,使用ANTIALIASED_QUALITY:

GDI+: TextRenderingHintSingleBitPerPixelGridFit, GDI: PROOF_QUALITY:

GDI+: TextRenderingHintSingleBitPerPixel, GDI: DRAFT_QUALITY:

我觉得奇怪的是DRAFT_QUALITYPROOF_QUALITY,这与CLEARTYPE_QUALITY.

See also

  • UseCompatibleTextRendering - 与 whaaaaaat 兼容? http://blogs.msdn.com/b/jfoscoding/archive/2005/10/13/480632.aspx
  • 整理一下:快速浏览一下 Whidbey 的 TextRenderer http://www.siao2.com/2005/06/27/432986.aspx
  • MSDN:LOGFONT 结构 http://msdn.microsoft.com/en-us/library/dd145037%28v=vs.85%29.aspx
  • AppCompat Guy:GDI 与 GDI+ 文本渲染性能 http://blogs.msdn.com/b/cjacks/archive/2006/05/19/gdi-vs-gdi-text-rendering-performance.aspx
  • GDI+ 文本、分辨率独立性和渲染方法。 或者 - 为什么我的文本在 GDI+ 和 GDI 中看起来不同? http://windowsclient.net/articles/gdiptext.aspx
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何绘制独立于 DPI 的 GDI + 文本 的相关文章

  • Perl 脚本中的大小写敏感性 - 如何使其不敏感?

    我如何更改以下马尔可夫脚本以将大写和小写单词视为相同 整个想法是帮助提高马尔可夫文本生成器的输出质量 就目前情况而言 如果您在其中插入 99 个小写句子和 1 个大写句子 您几乎总是会在输出中找到大写句子的非标记化版本 Copyright
  • 将文件夹名称添加到输出 Pig Latin

    我在 HDFS 中有下一个目录结构 logs folder 2021 03 01 log1 log2 log3 2021 03 02 log1 log2 2021 03 03 log1 log2 日志由文本数据组成 数据中没有日期 因为它已
  • 正则表达式从文本文件中提取文本块?

    我需要使用正则表达式从 Python 文本文件中提取标题及其下方的文本块 但我发现这很困难 我转换了这个PDF https www docdroid net rduS8oC pdfsam doc pdf文本 现在看起来像这样 到目前为止 我
  • 在文本矩阵中使用多个 CGAffineTransform

    我正在使用 Quartz 显示文本 这是我的代码 CGContextRef myContext UIGraphicsGetCurrentContext CGContextSelectFont myContext Helvetica 12 k
  • DPI 意识真的需要吗?

    我正在学习如何使用 GDI GDI 绘制 GUI 我发现了这个http msdn microsoft com en us library windows desktop dd756596 v vs 85 aspx step 2 declar
  • 用于图像中文本检测的霍夫变换算法[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 霍夫变换算法是用于文本行检测和边缘检测的算法之一 霍夫变换算法可以用于检测图像中的文本吗 这道题在java中的流程或者实现应该是怎样的
  • 使用 PHP 从

    我想获取里面的文字
  • HTML5 文本画布在文本宽度大于允许的最大宽度时旋转

    朋友们 我发现旋转文本画布对象有点棘手 问题是 我正在绘制一个图形 但有时每个条形的宽度小于该条形的 值 所以我必须将 值 评定为 90 度 在大多数情况下它都会起作用 我正在做以下事情 a function x y text maxWid
  • 保存 PDF 时的 matplotlib 线宽

    我有一个具有一些对线宽敏感的相当微妙的特征的图形 我想将此图保存为可以轻松打印的 PDF 即接收器端无需缩放 只需 Command P 即可 不幸的是 当我设置 Figsize 8 5 11 以便正确调整 PDF 的打印大小时 matplo
  • Paint.getTextWidths。什么是提前宽度?

    什么是提前宽度 该术语出现在 android 类中Paint 具体来说是函数getTextWidths 文档指出 返回字符串中字符的提前宽度 什么是 提前宽度 前进宽度是与字体 版式相关的度量术语 这里有一些关于 SO 的问答涵盖了它 但简
  • 椭圆绘制WPF动画

    我正在开发一个矩形区域的控件 当触发发生时 将在矩形区域中绘制一个椭圆形 该控件将能够承载其他控件 例如文本框 按钮等 因此在触发时将在它们周围绘制圆圈 我希望将圆圈绘制为动画 就像您用笔圈出内部控件一样 实现这一目标的最佳方法是什么 我一
  • 使用 Powershell 按列拆分 csv 文件

    我是 powershell 的新手 但这看起来是完成此任务的最佳工具 有一个如下所示的 csv 文件 Date mary1 mary2 maryr3 mary4 9 01 2011 1 00 1 39 3 43 3 29 1 83 9 01
  • 当包含 textColor 的样式应用于 textView 的 textAppearance 时,文本的颜色不会改变

    我想减少 xml 代码的重复 所以我为textView中的文本做了一些标准样式 我们可以在textView中的 style 属性和 android textAppearance 属性下应用样式 以下是我为文本外观制作的一些样式
  • 读取一个文本文件,替换其中的单词,输出到另一个文本文件

    所以我试图在 GO 中编写一个程序来获取一个充满代码的文本文件并将其转换为 GO 代码 然后将该文件保存到 GO 文件或文本文件中 我一直在试图弄清楚如何保存对文本文件所做的更改 但我可以看到更改的唯一方法是通过 println 语句 因为
  • CSS:变换:翻译(-50%,-50%)使文本模糊[重复]

    这个问题在这里已经有答案了 我想将我的div我使用这种方法 但它使我的文本在div blurry div top 50 left 50 webkit transform translate 50 50 transform translate
  • SQLAlchemy - 将文本查询与过滤器结合起来

    我在用着SA 0 6 6 Python 2 66 and Postgres 8 3 我有某些查询需要一些复杂的安全检查 可以使用WITH RECURSIVE询问 我想做的是将文本查询与查询对象结合起来 这样我就可以根据需要应用过滤器 我最初
  • WPF 应用程序在每个系统规模上具有相同的大小(与规模无关)

    有没有办法让 WPF 应用程序在每个系统规模上获得相同的大小 当我改变时更改文本 应用程序和其他项目的大小在windows系统设置中125 推荐 to 100 在全高清屏幕中 我的 WPF 应用程序变得太小 为了实现独立的系统缩放应用程序
  • 是否可以在 gnuplot 中设置标签相对于键的位置?

    我的情节的本质是这样的 绝对的标签并不能真正发挥作用 我无法限制 y 中的范围 所以想知道是否有办法将我的标签文本包含在键内或将其相对于键放置 即下面 set term png enhanced size 1024 768 set titl
  • DPI 图形屏幕分辨率像素 WinForm PrintPageEventArgs

    对于运行我的应用程序的任何显示器 Dpi 点与像素有何关系 int points Screen primary public Form1 InitializeComponent points 1 primary null void OnPa
  • Pygame 文本不渲染

    好的 我正在用 python 和 pygame 制作一个多项选择测验游戏 不过 我已经完成了开始屏幕并尝试制作问题屏幕 我根本不明白为什么文本不呈现 这是我的代码 enter pressed False random question ra

随机推荐