1

When I draw on a Bitmap Graphics an image that have translucent pixels, and then drawing bitmap on the screen, these pixels become black.

At the same time, purely transparent pixels around the image remain transparent.

Who knows how to fix this?

Here is the code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Drawing.Drawing2D;

namespace SimpleTest
{
  public partial class Form12_BitmapAlpha : Form
  {
    public Form12_BitmapAlpha()
    {
      InitializeComponent();
    }

    private void Panel1_Paint(object sender, PaintEventArgs e)
    {
      //Back
      e.Graphics.FillRectangle(new SolidBrush(Color.Coral), new Rectangle(5, 5, 25, 85));

      // 1
      RadioButtonRenderer.DrawRadioButton(e.Graphics, new Point(10, 10), RadioButtonState.CheckedNormal);

      //2
      Size cbSize = RadioButtonRenderer.GetGlyphSize(e.Graphics, RadioButtonState.CheckedNormal);
      Bitmap cbBitmap = new Bitmap(cbSize.Width, cbSize.Height);

      using (Graphics offscreen = Graphics.FromImage(cbBitmap))
      {
        //offscreen.CompositingMode = CompositingMode.SourceCopy; //doesn't work
        //offscreen.Clear(Color.Transparent); //it doesn't help
        RadioButtonRenderer.DrawRadioButton(offscreen, new Point(0, 0), RadioButtonState.CheckedNormal);
      }

      e.Graphics.DrawImage(cbBitmap, new Point(10, 40));

      //3
      RadioButtonRenderer.DrawRadioButton(e.Graphics, new Point(10, 70), RadioButtonState.CheckedNormal);
      Bitmap cbBitmap1 = new Bitmap(20, 20);

      using (Graphics offscreen = Graphics.FromImage(cbBitmap1))
      {
        offscreen.FillRectangle(new SolidBrush(Color.FromArgb(128, Color.Red)), new Rectangle(2, 2, 16, 16));
      }

      e.Graphics.DrawImage(cbBitmap1, new Point(0, 65));
    }
  }
}

In the first part of the code, (under //1) I draw directly on the Graphics of the Panel and you can see that the edges of the RadioButton are drawn in a semi-transparent color.

In the second part of the code (under //2), I draw the same thing, but through a Bitmap object. Here the border is drawn black.

And in the third part (under //3), I draw a translucent square on a Bitmap and then draw this Bitmap on the screen to show that Bitmap supports translucent areas.

and the result

enter image description here

DmitryB
  • 455
  • 1
  • 5
  • 18
  • The question is a little unclear imo. a) you may need to clarify which is which. b) note that drawing anything with transparency onto a control will not result in real transparency but will only make the background shine through. c) also note that you can't draw make anything tranparent by drawing transparent pixels. To create transparency you need to call graphics.Clear(Color.Transparent) – TaW Apr 25 '19 at 21:27
  • 1
    You're drawing in two diffrent device contexts. `VisualStyleRenderer.DrawBackground` can determine the backgound of an hDC coming from a Control. A Bitmap doesn't have a background. That `nothing` is translated to a `black-ish` background. But it will render perfectly on a black canvas :) – Jimi Apr 25 '19 at 21:51
  • You could paint on `e.Graphics`, then grab that piece of drawing and transfer it on a Bitmap. Well, it's an idea :) – Jimi Apr 25 '19 at 21:54
  • It draws black borders even if I clear background with white color. offscreen.Clear(Color.White); – DmitryB Apr 26 '19 at 00:53
  • 1
    A Bitmap has no background. You're using `RadioButtonRenderer.DrawRadioButton`, thus `VisualStyleRenderer`. It's used to draw on Controls. Controls have a background. – Jimi Apr 26 '19 at 01:04
  • Is there any documentation describing this concept of "background"? I always thought that I read the GDI documentation in some detail. – DmitryB Apr 26 '19 at 01:14
  • There's no such documentation. Or all documentations are valid, as you want to see it. It's all a matter of context. You can draw, using the Graphics object, a partially transparent Bitmap on a surface or another Bitmap and the transparency (full or partial) will be preserved. GDI+ *understands* transparency, thus is aware that there's a *background* (colors in a DC that don't overlap and need to be preserved/reproduced on the canvas). See the [Bitmap::GetHBITMAP](https://learn.microsoft.com/en-us/windows/desktop/api/gdiplusheaders/nf-gdiplusheaders-bitmap-gethbitmap) method. – Jimi Apr 26 '19 at 02:00
  • In another context, these values/properties have no meaning. Other values/properties are considered instead. A Controls can create its own DC. But it's not related to what an HBITMAP points to. – Jimi Apr 26 '19 at 02:00
  • This is an interesting observation. Looking at the sources it gets even more interesting. Seems that depending on the circumstances the black/white will or won't get replaced by the fore/backcolors..: [DrawFrameControl](http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/whidbey/REDBITS/ndp/fx/src/WinForms/Managed/System/WinForms/ControlPaint@cs/2/ControlPaint@cs)..Not sure what you could do about it. What was the original goal? Rendering to a Bitmap? Usually DrawToBitmap will do.. Maybe a subclass with your custom code and then DrawToBitmap ? – TaW Apr 26 '19 at 07:40
  • The original problem arose when it became clear that the function RadioButtonRenderer.DrawRadioButton is too slow. I have a lot of RadioButtons in the grid and the grid scrolls too slowly due to slow redrawing. Drawing RadioButtons through a buffering Bitmap works 5 times faster. But I can't get an exact copy of the RadioButton inside the Bitmap. – DmitryB Apr 26 '19 at 09:48
  • radioButton1.DrawToBitmap(radioDrawBitmap, new Rectangle(0, 0, 13, 13)); fills Bitmap background rectangle with Control.BackColor color on which radioButton1 lies. – DmitryB Apr 26 '19 at 12:32
  • Here, a similar question was. https://stackoverflow.com/questions/16030798/visualstylerenderer-to-bitmap – DmitryB Apr 26 '19 at 12:37
  • What kind of 'grid' (and what numbers) are we talking about here? I'd be surpised if the speed issue is really real and calls for such measures.. - Do try [DoubleBuffering](https://stackoverflow.com/questions/44185298/update-datagridview-very-frequently/44188565#44188565) that 'grid'.. – TaW Apr 26 '19 at 18:46

0 Answers0