c#中重载控件绘制有文本渲染问题
Overloading control drawing in c# has text rendering problems
我已经子class编辑了一个控件 (ToolStripStatusLabel) 来尝试覆盖它的绘制方式。目前我希望这段代码实际上什么都不做,但它会导致一个奇怪的输出:
protected override void OnPaint(PaintEventArgs e)
{
// Create a temp image to draw to and then put that onto the control transparently
using (Bitmap bmp = new Bitmap(this.Width, this.Height))
{
using (Graphics newGraphics = Graphics.FromImage(bmp))
{
// Paint the control to the temp graphics
PaintEventArgs newEvent = new PaintEventArgs(newGraphics, e.ClipRectangle);
base.OnPaint(newEvent);
// Copy the temp image to the control
e.Graphics.Clear(this.BackColor);
e.Graphics.DrawImage(bmp, new Rectangle(0, 0, this.Width, this.Height), 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel);//, imgAttr);
}
}
}
当我运行这段代码时,控件上的文字很奇怪,预期的图像在顶部,实际输出在底部:
看起来当控件绘制文本时,alpha 与抗锯齿文本的混合出错了。
我尝试过的事情:
- 设置
e.graphics
和newGraphics
的合成模式
- 正在设置
TextRenderingHint
.
- 将
newGraphics
的像素格式设置为 32Bpp ARGB 和预乘 ARGB
- 在请求基础 class 渲染之前用控件背景颜色清除
newGraphics
。
TL;DR: 您需要使用重新实现 OnRenderItemText
的 custom renderer 自己渲染文本,可能使用 [=41] =]() 最终完成绘图。
另一种选择是使用 (如@Reza Aghaei 所述)。然后您可以将 UseCompatibleTextRendering
设置为 true 以使其使用 GDI+ 而不是 GDI
这似乎是文本在最低级别呈现方式的固有问题。如果您添加一个普通的 ToolStripStatusLabel 并将其 TextDirection 设置为 Vertical90,那么您会得到相同的结果,其中文本的抗锯齿似乎没有背景的 alpha。
查看 source,您会看到一段非常相似的代码被调用,其中文本呈现为位图,然后在本例中旋转:
using (Bitmap textBmp = new Bitmap(textSize.Width, textSize.Height,PixelFormat.Format32bppPArgb)) {
using (Graphics textGraphics = Graphics.FromImage(textBmp)) {
// now draw the text..
textGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
TextRenderer.DrawText(textGraphics, text, textFont, new Rectangle(Point.Empty, textSize), textColor, textFormat);
textBmp.RotateFlip((e.TextDirection == ToolStripTextDirection.Vertical90) ? RotateFlipType.Rotate90FlipNone : RotateFlipType.Rotate270FlipNone);
g.DrawImage(textBmp, textRect);
}
}
因此,当文本呈现到位图图形上下文(与控件的图形上下文相对)时,这似乎是一个基本问题。最终 code that is called 是:
using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, flags ))
{
using (WindowsFont wf = WindowsGraphicsCacheManager.GetWindowsFont( font, fontQuality )) {
wgr.WindowsGraphics.DrawText( text, wf, bounds, foreColor, GetIntTextFormatFlags( flags ) );
}
}
我认为它正在涉足具有 trouble with alpha on text.
的 GDI(而不是 GDI+)
你最好的选择是写一个 custom renderer 重新实现 OnRenderItemText
,可能有一些 'inspiration' 来自 默认实现 [=39] =].
我已经子class编辑了一个控件 (ToolStripStatusLabel) 来尝试覆盖它的绘制方式。目前我希望这段代码实际上什么都不做,但它会导致一个奇怪的输出:
protected override void OnPaint(PaintEventArgs e)
{
// Create a temp image to draw to and then put that onto the control transparently
using (Bitmap bmp = new Bitmap(this.Width, this.Height))
{
using (Graphics newGraphics = Graphics.FromImage(bmp))
{
// Paint the control to the temp graphics
PaintEventArgs newEvent = new PaintEventArgs(newGraphics, e.ClipRectangle);
base.OnPaint(newEvent);
// Copy the temp image to the control
e.Graphics.Clear(this.BackColor);
e.Graphics.DrawImage(bmp, new Rectangle(0, 0, this.Width, this.Height), 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel);//, imgAttr);
}
}
}
当我运行这段代码时,控件上的文字很奇怪,预期的图像在顶部,实际输出在底部:
看起来当控件绘制文本时,alpha 与抗锯齿文本的混合出错了。
我尝试过的事情:
- 设置
e.graphics
和newGraphics
的合成模式
- 正在设置
TextRenderingHint
. - 将
newGraphics
的像素格式设置为 32Bpp ARGB 和预乘 ARGB - 在请求基础 class 渲染之前用控件背景颜色清除
newGraphics
。
TL;DR: 您需要使用重新实现 OnRenderItemText
的 custom renderer 自己渲染文本,可能使用 [=41] =]() 最终完成绘图。
另一种选择是使用 UseCompatibleTextRendering
设置为 true 以使其使用 GDI+ 而不是 GDI
这似乎是文本在最低级别呈现方式的固有问题。如果您添加一个普通的 ToolStripStatusLabel 并将其 TextDirection 设置为 Vertical90,那么您会得到相同的结果,其中文本的抗锯齿似乎没有背景的 alpha。
查看 source,您会看到一段非常相似的代码被调用,其中文本呈现为位图,然后在本例中旋转:
using (Bitmap textBmp = new Bitmap(textSize.Width, textSize.Height,PixelFormat.Format32bppPArgb)) {
using (Graphics textGraphics = Graphics.FromImage(textBmp)) {
// now draw the text..
textGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
TextRenderer.DrawText(textGraphics, text, textFont, new Rectangle(Point.Empty, textSize), textColor, textFormat);
textBmp.RotateFlip((e.TextDirection == ToolStripTextDirection.Vertical90) ? RotateFlipType.Rotate90FlipNone : RotateFlipType.Rotate270FlipNone);
g.DrawImage(textBmp, textRect);
}
}
因此,当文本呈现到位图图形上下文(与控件的图形上下文相对)时,这似乎是一个基本问题。最终 code that is called 是:
using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, flags ))
{
using (WindowsFont wf = WindowsGraphicsCacheManager.GetWindowsFont( font, fontQuality )) {
wgr.WindowsGraphics.DrawText( text, wf, bounds, foreColor, GetIntTextFormatFlags( flags ) );
}
}
我认为它正在涉足具有 trouble with alpha on text.
的 GDI(而不是 GDI+)你最好的选择是写一个 custom renderer 重新实现 OnRenderItemText
,可能有一些 'inspiration' 来自 默认实现 [=39] =].