在c#中重载控件绘图有文本渲染问题

时间:2018-01-23 15:52:51

标签: c# winforms rendering alphablending

我已经对控件(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);
    }
  }
}

当我运行此代码时,控件上的文字非常奇怪,预期的图像位于顶部,实际输出位于底部:

output

看起来当控件正在绘制文本时,与抗锯齿文本的alpha混合出错了。

我尝试过的事情:

  • 设置e.graphicsnewGraphics
  • 的CompositingMode
  • 设置TextRenderingHint
  • newGraphics的像素格式设置为32Bpp ARGB和预乘ARGB
  • 在要求基类渲染之前,使用控件背景颜色清除newGraphics

1 个答案:

答案 0 :(得分:0)

TL; DR:您需要使用重新实现OnRenderItemText的{​​{3}}自行呈现文本,可能需要使用graphics.DrawString()最终完成绘图。

另一种选择是使用custom renderer(如@Reza Aghaei所述)。然后,您可以将UseCompatibleTextRendering设置为true,以使其使用GDI +而不是GDI

这似乎是文本在最低级别呈现方式的固有问题。如果添加一个普通的ToolStripStatusLabel并将其TextDirection设置为Vertical90,那么你会得到相同的结果,其中文本的消除锯齿似乎没有背景的alpha。

查看label in the status bar,您会看到一个非常相似的代码被调用,其中文本呈现为位图,然后在这种情况下旋转:

            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);
                }
            }

因此,当文本呈现到位图图形上下文(而不是控件的图形上下文)时,这似乎是一个基本问题。最终source是:

        using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, flags ))
        {
            using (WindowsFont wf = WindowsGraphicsCacheManager.GetWindowsFont( font, fontQuality )) {
                wgr.WindowsGraphics.DrawText( text, wf, bounds, foreColor, GetIntTextFormatFlags( flags ) );
            }
        }

我认为这种情况正在涉及到code that is called的GDI(与GDI +相对)。

你最好的办法就是写一个trouble with alpha on text来重新实现OnRenderItemText,可能会带来一些启发性的'来自custom renderer

的来源