Text 如何绘制GDI+;独立于新闻部的文本

Text 如何绘制GDI+;独立于新闻部的文本,text,gdi+,draw,dpi,Text,Gdi+,Draw,Dpi,我正在使用GDI+绘制文本。我最近注意到,当DPI更改时,此文本会自动缩放。有没有办法使GDI+文本绘图独立于DPI?例如,我想画一个不超过20像素的文本,而不考虑DPI。可能吗?如何做到这一点 下面是一个示例代码。我希望以恒定的大小绘制第一个文本,而不考虑DPI,第二个文本通常: case WM_PAINT: { inherited::WndProc(message); Canvas->Brush->Style = bsSolid;

我正在使用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;
    }
case WM_PAINT:
{
继承::WndProc(消息);
画布->画笔->样式=bsSolid;
画布->画笔->颜色=白色;
Canvas->FillRect(ClientRect);
//从画布获取GDI+图形
图形(画布->句柄);
//设置文本呈现提示
graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintSystemDefault);
std::auto_ptr pFont(新的Gdiplus::Font(画布->句柄,字体->句柄));
std::auto_ptr pBrush(新的Gdiplus::SolidBrush(Gdiplus::Color(255,0,0,0));
std::auto_ptr pFormat(新的Gdiplus::StringFormat());
Gdiplus::FontFamily FontFamily;
pFont->GetFamily(&fontFamily);
std::auto_ptr pFont2(新的Gdiplus::Font(&fontFamily,pFont->GetSize(),
pFont->GetStyle(),Gdiplus::UnitPixel));
Gdiplus::unittest=pFont->GetUnit();
Gdiplus::unittest2=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);
p格式->设置格式标志(标志);
p格式->设置修剪(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);
}
//绘制文本2
graphics.DrawString(text.c_str()、text.length()、pFont.get()、Gdiplus::RectF(ClientRect.Left、,
ClientRect.Top+25,ClientWidth,ClientHeight),pFormat.get(),pBrush.get();
返回;
}

这对我来说很有用

using namespace Gdiplus; 

HDC hDC = ::GetDC( NULL );
int nDPI = ::GetDeviceCaps( hDC, LOGPIXELSY );
::ReleaseDC( NULL, hDC );

REAL fFontHeight = 96 / (REAL)nDPI * 8;

FontFamily fontFamily( L"Arial" );
Gdiplus::Font font( &fontFamily, fFontHeight, UnitPixel );

REAL fMeasuredFontHeight = font.GetHeight( &gr );
事实证明,尽管Gdiplus::Font是以像素为单位指定的,但它使用用户的DPI设置来调整生成的字体(即使该字体用于绘制位图!)。标准DPI为96是一个很好的值,用于确定调整字体大小的正确比率

在上面的代码片段中,所寻求的字体高度为8像素高


通过所有DPI设置,fMeasuredFontHeight几乎保持不变(大约为12)。

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

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

  • GDI+(
    graphics.MeasureString
    graphics.DrawString
  • GDI(
    textrender.MeasureText
    textrender.DrawText
在.NET 1.1中,用于文本呈现的所有内容都GDI+

  • GDI+的无状态特性导致了一些性能问题,在GDI+中,设备上下文将被设置,然后在每次调用后恢复原始上下文
  • Windows/Uniscribe和Avalon(Windows Presentation Foundation)的国际文本成形引擎已多次更新,但尚未针对GDI+进行更新,这导致对新语言的国际呈现支持的质量不尽相同
因此他们知道他们想改变.NET框架,停止使用GDI+的文本呈现系统,而使用GDI。起初,他们希望他们可以简单地改变:

graphics.DrawString
调用旧的
DrawText
API而不是GDI+。但他们无法使文本的换行和间距与GDI+完全匹配。因此,他们被迫保留
graphics.DrawString
来调用GDI+(兼容性原因;调用
graphics.DrawString
的人会突然发现他们的文本没有以前的包装方式)

创建了一个新的静态
TextRenderer
类来包装GDI文本呈现。它有两种方法:

TextRenderer.MeasureText
TextRenderer.DrawText
注意:
-
TextRenderer
是GDI的包装器
-
graphics.DrawString仍然是GDI的包装器+


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

  • 标签
  • 按钮
  • TextBox
他们想将它们切换到使用
textrender
(即GDI),但必须小心。可能有人像在.NET1.1中那样依赖于控件的绘制。于是“兼容文本呈现”诞生了

默认情况下,应用程序中的控件的行为与.NET 1.1中的控件类似(它们是“兼容的”)

您可以通过调用以下命令来关闭兼容模式:

Application.SetCompatibleTextRenderingDefault(false);
这使您的应用程序更好、更快、具有更好的i
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
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)