如何绘制独立于 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 + 文本 的相关文章

  • Ubuntu 上的 Vim:文本渲染错误,奇怪地重复和消失

    不久前我在 ubuntu 12 04 上安装了 vim 有时 当我在代码上运行光标 使用键盘 而不是鼠标 时 文本会消失 就好像渲染字符时出现问题一样 当我再次运行光标时 它通常会重新出现 这似乎是随机发生的 但通常足以让人恼火 为了更清楚
  • 如何将 WPF 大小转换为物理像素?

    将 WPF 与分辨率无关 宽度和高度转换为物理屏幕像素的最佳方法是什么 我正在 WinForms 表单中显示 WPF 内容 通过 ElementHost 并尝试制定一些大小调整逻辑 当操作系统以默认 96 dpi 运行时 我可以正常工作 但
  • 如何使用文本相似性删除 pandas 数据框中相似(不重复)的行?

    我有数千个数据 这些数据可能相似也可能不相似 使用 python 的默认函数 drop duplicates 并没有真正的帮助 因为它们只检测相似的数据 例如 如果我的数据包含类似以下内容怎么办 嗨 早上好 嗨 早上好 Python 不会将
  • GDI 函数 BitBlt 和 StretchBlt 在 Win32 中是否硬件加速?

    我似乎无法通过搜索得到明确的答案 Win32 blitting 操作是否硬件加速 GDI 而不是 GDI 我不知道这些函数如何与图形驱动程序交互 是否有任何函数调用来验证此功能 例如 GetCaps 对于特定的图形设备 win32图形设备
  • 如何在状态更改时更改 Android 切换按钮的文本颜色?

    我的切换按钮对于每个状态都有不同的颜色背景 红色和白色 现在我需要在激活时更改切换按钮文本 红色 白色 的颜色 使用 xml 我无法让它工作 也许有人知道我做错了什么 我的布局 xml 中的按钮
  • 测量以指定宽度包裹的文本高度

    如何计算渲染以指定宽度包裹的文本所需的高度 我在中找到了以下方法Graphics graphicsObj MeasureString text font width 但它需要一个实例Graphics当时我还没有图形实例 事实上 我更喜欢使用
  • url文本压缩(不是缩短)并存储在mysql中

    我在 mysql 中有一个 url 表 其中只有两个字段 id 和 varchar 255 用于 url 目前那里有超过 5000 万个 url 我的老板刚刚向我提供了有关当前项目扩展的线索 这将导致在该 url 表中添加更多的 url 预
  • 当语料库有100亿个独特的DNA序列时,如何使用BK树实现快速模糊搜索引擎?

    我正在尝试使用BK tree https news ycombinator com item id 14022424python 中的数据结构 用于存储约 100 亿个条目的语料库 1e10 以实现快速模糊搜索引擎 一旦我添加超过 1000
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 仅从 PDF 中提取粗体文本的最佳方法

    iTextSharp 是一个很棒的工具 我可以使用PdfTextExtractor GetTextFromPage reader iPage 它工作得很好 但是有没有办法从 pdf 中只提取粗体文本 例如标题 而不是所有内容 无论编程语言如
  • 如何自动替换多个文件的文本内容中的字符?

    我有一个文件夹 myfolder包含许多乳胶表 我需要替换其中每个字符 即替换任何minus sign by an en dash 只是为了确定 我们正在替换连字符INSIDE该文件夹中的所有 tex 文件 我不关心 tex 文件名 手动执
  • 如何让文字适合Button?

    在我的 Android 应用程序中 我有一个用于对照片进行投票的按钮 当用户选择这个按钮时 这个按钮上的文字变成 感谢您的投票 当他看到他之前投票过的照片时 按钮上会看到文字 您已经为这张照片投票 问题是它看起来像这样 http i55 t
  • 使用 setMessage() 在 AlertDialog 中显示多行文本和变量

    我需要在警报对话框中显示多行文本 如果我使用多个 setMessage 方法 则仅显示最后一个 setMessage 如下所示 final AlertDialog alertDialog new AlertDialog Builder th
  • Oracle Text 包含单字符索引搜索不起作用

    我有一个名为 index search 的简单表 创建如下 BEGIN ctx ddl create preference my pref BASIC WORDLIST ctx ddl set attribute my pref SUBST
  • 确定 GDI 句柄和 USER 对象的数量

    我们为 Windows Forms UI 渲染引擎开发了一个小型测试套件 它允许在以自动方式运行测试用例时测量性能并检测内存泄漏 现在我们还要检查手柄是否泄漏 在桌面平台上我们可以使用这段代码 DllImport User32 privat
  • 在按钮背景上拉伸/收缩时,位图会失去质量

    简介及相关信息 我有一个所有者绘制的静态控件 它应该在渐变背景上有位图 静态控制尺寸不固定 它们是在创建父窗口期间计算的 我从资源文件加载背景颜色为 RGB 255 163 94 的位图 Using TransparentBlt RGB 2
  • 围绕另一个点旋转一个点

    我的任务是绘制特定图形 作为此任务的一部分 我需要将一些点旋转 45 度 我已经花了两天时间尝试计算公式 但就是无法得到正确的结果 我一直在到处搜索 包括这个特定的网站 我已经非常接近了 但我仍然不在那里 这里是 我需要画4个不同的点 我有
  • 动态显示数百张图像

    我必须创建一个能够显示电影院大厅 不知道确切的词 模式的表单 本质上 我必须显示大量 由另一个来源提供 独立的椅子状图像 这些图像可以在单击时改变颜色 状态 我上网寻找解决方案 但我真的不知道如何管理这个问题 有人能帮我吗 如果您需要绘制那
  • DotNET 应用程序中的 GDI 句柄

    我的纯 DotNET 库作为非托管桌面应用程序中的插件运行 我收到了稳定的 虽然低 崩溃报告流 这些报告似乎表明 GDI 句柄存在问题 错误消息中的字体等 恢复为系统字体 各种控件的显示崩溃 不久后发生大规模崩溃 我的窗体几乎没有控件 但我
  • 在Android中绘制带有曲线底部的矩形视图

    美好的一天 我想画一个矩形作为视图 但底部应该是弯曲的 我不想应用这样的背景图像或使用任何视图 因为如果我使用视图并设置背景 曲线部分仍然会有不可见的空白空间 我将无法将另一个曲线图像附加到自定义视图的底部曲线 那么我该如何绘制一个带有底部

随机推荐