问题描述
我正在使用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 + 进行文本呈现.
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
andgraphics.DrawString
) - GDI (
TextRenderer.MeasureText
andTextRenderer.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
- UseCompatibleTextRendering - Compatible with whaaaaaat?
- Sorting it all out: A quick look at Whidbey's TextRenderer
- MSDN: LOGFONT Structure
- AppCompat Guy: GDI vs. GDI+ Text Rendering Performance
- GDI+ Text, Resolution Independence, and Rendering Methods.Or - Why does my text look different in GDI+ and in GDI?
这篇关于如何绘制独立于DPI的GDI +文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!