Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#中的重载控件绘图存在文本呈现问题_C#_Winforms_Rendering_Alphablending - Fatal编程技术网

c#中的重载控件绘图存在文本呈现问题

c#中的重载控件绘图存在文本呈现问题,c#,winforms,rendering,alphablending,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(

我对一个控件(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
  • 设置
    textrendinghint
  • newGraphics
    的像素格式设置为32Bpp ARGB和预乘ARGB
  • 在请求基类渲染之前,请使用控件背景色清除
    newGraphics

    • TL;DR:您需要使用重新实现
      OnRenderItemText
      ,可能使用graphics.DrawString()来最终绘制文本的

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


      这似乎是文本在最低层次上呈现的固有问题。如果添加一个普通ToolStripStatusLabel并将其TextDirection设置为Vertical90,则会得到相同的结果,其中文本的抗锯齿看起来与背景没有alpha

      查看,您将看到调用了一个非常类似的代码位,其中文本被渲染为位图,然后在本例中旋转:

                  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);
                      }
                  }
      
      因此,当文本呈现到位图图形上下文(与控件的图形上下文相反)时,这似乎是一个基本问题。最终的结果是:

      我认为这是进入GDI(与GDI+相反)的过程,而GDI+已经


      最好的方法是编写一个重新实现
      OnRenderItemText
      ,可能是从源代码中获得了一些“灵感”.

      尝试
      PixelFormat.Format32bppPArgb
      以获得
      位图
      ,或者在绘制之前清除位图而不是控件。如果我没有弄错的话,这是一种需要预乘alpha的问题。我忘了提到我已经尝试显式设置像素格式-我尝试了32bppARGB,但将其更改为32bppPARGB没有任何效果。我还尝试在将控件转到renderSorry之前清除newGraphics上下文,基类只是一个ToolStripStatusLabel@joey关于背景清理:当使用DrawString()时,这当然有帮助(我刚刚用它做了一个测试),但奇怪的是,它对基类绘图的结果没有影响。我想知道微软在那里做什么!如果您试图自定义
      ToolStripStatusLabel
      的外观,则创建渲染器是一种方法。举个例子来看。
              using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, flags ))
              {
                  using (WindowsFont wf = WindowsGraphicsCacheManager.GetWindowsFont( font, fontQuality )) {
                      wgr.WindowsGraphics.DrawText( text, wf, bounds, foreColor, GetIntTextFormatFlags( flags ) );
                  }
              }