本文介绍了如何绘制独立于DPI的GDI +文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

下面是示例代码.我想以不变的大小绘制第一个文本,而与DPI无关,然后正常地绘制第二个文本:

 案例WM_PAINT:{继承:: WndProc(message);画布->画笔->样式= bsSolid;画布->画笔->颜色= clWhite;画布-> FillRect(ClientRect);//从画布获取GDI +图形Gdiplus :: Graphics graphics(Canvas-> Handle);//设置文字渲染提示graphics.SetTextRenderingHint(Gdiplus :: TextRenderingHintSystemDefault);std :: auto_ptr< Gdiplus :: Font>pFont(新的Gdiplus :: Font(Canvas-> Handle,Font-> Handle));std :: auto_ptr< Gdiplus :: SolidBrush>pBrush(新的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(新的Gdiplus :: Font(& fontFamily,pFont-> GetSize(),pFont-> GetStyle(),Gdiplus :: UnitPixel));Gdiplus :: Unit测试= pFont-> GetUnit();Gdiplus :: Unit test2 = pFont2-> GetUnit();pFormat-> SetAlignment(Gdiplus :: StringAlignmentNear);pFormat-> SetLineAlignment(Gdiplus :: StringAlignmentNear);Gdiplus :: StringFormatFlags标志= 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这是示例代码";Gdiplus :: Unit prevPageUnit = graphics.GetPageUnit();尝试{graphics.SetPageUnit(Gdiplus :: UnitPixel);//绘制文字graphics.DrawString(text.c_str(),text.length(),pFont2.get(),Gdiplus :: RectF(ClientRect.Left,ClientRect.Top,ClientWidth,ClientHeight),pFormat.get(),pBrush.get());}__最后{graphics.SetPageUnit(prevPageUnit);}//绘制文字2graphics.DrawString(text.c_str(),text.length(),pFont.get(),Gdiplus :: RectF(ClientRect.Left,ClientRect.Top + 25,ClientWidth,ClientHeight),pFormat.get(),pBrush.get());返回;} 

致谢

解决方案

我想提些与您的问题无关的内容.您不应该再在GDI +中使用 Graphics.DrawString .在.NET 2中已弃用.相反,Microsoft创建了 TextRenderer.DrawString .

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

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

在.NET 1.1中,所有内容都使用 GDI + 进行文本呈现.

  • 全部整理:快速浏览Whidbey的TextRenderer
  • MSDN:LOGFONT结构
  • AppCompat Guy:GDI与GDI +文本渲染性能
  • GDI +文本,分辨率独立性和渲染方法.或者-为什么我的文本在GDI +和GDI中看起来不同?
  • I'm drawing a text using GDI+. I recently noticed that this text is automatically scaled when the DPI is changed. Is there a way to make the GDI+ text drawing independent of the DPI? E.g. I want to draw a text up to 20 pixels, regardless of the DPI. Is it possible? How to do this?

    Below is a sample code. I want to draw the first text with a constant size, regardless of the DPI, and the second text normally:

        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

    解决方案

    I wanted to mention something, slightly unrelated to your question. You shouldn't be using Graphics.DrawString in GDI+ anymore. It was deprecated in .NET 2. Instead Microsoft created TextRenderer.DrawString.

    There are two ways of drawing text in .NET:

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

    In .NET 1.1 everything used GDI+ for text rendering. But there were some problems:

    So they knew they wanted to change the .NET framework to stop using GDI+'s text rendering system, and use GDI. At first they hoped they could simply change:

    graphics.DrawString
    

    to call the old DrawText API instead of GDI+. But they couldn't make the text-wrapping and spacing match exactly as what GDI+ did. So they were forced to keep graphics.DrawString to call GDI+ (compatiblity reasons; people who were calling graphics.DrawString would suddenly find that their text didn't wrap the way it used to).

    A new static TextRenderer class was created to wrap GDI text rendering. It has two methods:

    TextRenderer.MeasureText
    TextRenderer.DrawText
    


    Then there was the issue of what to do with all the existing .NET controls, e.g.:

    • Label
    • Button
    • TextBox

    They wanted to switch them over to use TextRenderer (i.e. GDI), but they had to be careful. There might be people who depended on their controls drawing like they did in .NET 1.1. And so was born "compatible text rendering".

    By default controls in application behave like they did in .NET 1.1 (they are "compatible").

    You turn off compatibility mode by calling:

    Application.SetCompatibleTextRenderingDefault(false);
    

    This makes your application better, faster, with better international support. To sum up:

    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
    


    It's also useful to note the mapping between GDI+ TextRenderingHint and the corresponding LOGFONT Quality used for GDI font drawing:

    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

    Here's some comparisons of GDI+ (graphics.DrawString) verses GDI (TextRenderer.DrawText) text rendering:

    GDI+: TextRenderingHintClearTypeGridFit, GDI: CLEARTYPE_QUALITY:

    GDI+: TextRenderingHintAntiAlias, GDI: ANTIALIASED_QUALITY:

    GDI+: TextRenderingHintAntiAliasGridFit, GDI: not supported, uses ANTIALIASED_QUALITY:

    GDI+: TextRenderingHintSingleBitPerPixelGridFit, GDI: PROOF_QUALITY:

    GDI+: TextRenderingHintSingleBitPerPixel, GDI: DRAFT_QUALITY:

    i find it odd that DRAFT_QUALITY is identical to PROOF_QUALITY, which is identical to CLEARTYPE_QUALITY.

    See also

    这篇关于如何绘制独立于DPI的GDI +文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-03 23:19
    查看更多