Trouble drawing theme elements transparently

I'm trying to draw a windows theme element (the window close button, specifically) to an image, and whenever I do, the image has ragged non-transparent bits. I got this code from a sample that didn't do this (it was all owner-drawn, mine draws to an image.) Any idea why it won't draw with full transparency

Bitmap output = new Bitmap(closeButton.Width, closeButton.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics fx = Graphics.FromImage(output);
      
IntPtr hTheme = OpenThemeData (Handle, "Window");
         
Rectangle rClose = new Rectangle(0, 0, closeButton.Width, closeButton.Height);
RECT reClose = rClose;
RECT reClip = reClose;
IntPtr hDC = fx.GetHdc();
DrawThemeBackground (hTheme, hDC, WP_CLOSEBUTTON, state, ref reClose, ref reClip);
fx.ReleaseHdc (hDC);
fx.DrawImage(output,rClose);
CloseThemeData (hTheme);
fx.Dispose();


Answer this question

Trouble drawing theme elements transparently

  • soader

    Control windows don't support alpha transparency. You need to either use graphical components, all drawn on a single control, or use windows with alpha transparency -- they cannot be child windows.

    Regards,
    Frank Hileman

    check out VG.net: http://www.vgdotnet.com
    Animated vector graphics system
    Integrated Visual Studio .NET graphics editor



  • ToddNR

    Bitmap output = new Bitmap(closeButton.Width, closeButton.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Graphics fx = Graphics.FromImage(output);
               

                IntPtr hTheme = OpenThemeData (Handle, "Window");
               
                if (hTheme == IntPtr.Zero)
                {
                    fx.Dispose();
                    return drawLegacyCloseButton (state);
                }

                Rectangle rClose = new Rectangle(0, 0, closeButton.Width, closeButton.Height);
                RECT reClose = rClose;
                RECT reClip = reClose; // should fx.VisibleClipBounds be used here
               
                fx.Clear(Color.Transparent);
                IntPtr hDC = fx.GetHdc();
                if (IsThemeBackgroundPartiallyTransparent(hTheme, WP_CLOSEBUTTON, state) != 0)
                {
                    DrawThemeParentBackground(this.Handle, hDC, ref reClose);
                }
                DrawThemeBackground (hTheme, hDC, WP_CLOSEBUTTON, state, ref reClose, ref reClip);
                fx.ReleaseHdc (hDC);
                fx.DrawImage(output,rClose);
                CloseThemeData (hTheme);
                fx.Dispose();

                output.Save("close" + state.ToString() + ".png");

                return output;

  • David Christie

    In this case maybe you are not drawing child controls, so my last post may be irrelevent. Have you looked at IsThemeBackgroundPartiallyTransparent



  • 大頭仔

    This works perfectly for me.
    What are you doing with the output Bitmap

  • ETSUGeek

     

    if (IsThemeBackgroundPartiallyTransparent(_hTheme, BP_PUSHBUTTON, _iStateId))
      {
        DrawThemeParentBackground(_hwnd, hdcPaint, prcPaint);
      }

      DrawThemeBackground(_hTheme,
                        hdcPaint,
                        BP_PUSHBUTTON,
                        _iStateId,
                        &rcClient,
                        prcPaint);

     

    That is the MSDN sample. If IsThemeBackgroundPartiallyTransparent returns false, there is no alpha blending -- that is the correct behavior.

  • Mike for VB

    Yes, I've tried that, but it didn't help. See, I'm not drawing to a control, I'm drawing to a bitmap - it seems that this should be pretty simple in that case, right

  • HumanPixel

    I don't see any code clearing your bitmap to transparent alpha.

    fx.Clear(Color.Transparent);
     


  • DaveDeath

    I think that explains why the button looks so oogly as well Smile You may need your own close button if you want something better.

  • OwenSmith

    No ideas why this wouldn't draw the element transparently

  • Yesb2k

    When I use that code, I still get the same result - all the alpha-blended bits are drawn onto gray, and only the fully-transparent bits are transparent. And I set a breakpoint - IsThemeBackgroundPartiallyTransparent is returning true.

    This is weird because the code I took this from (which did all its drawing itself, in WmPaint), does not have this problem - it is able to draw the same button nicely alpha-blended. The only difference is that I draw to a Bitmap.

  • Dan Wahlin

    Still works perfectly for me although I did change the code very slightly.

    Rectangle and RECT are not interchangeable.

    struct RECT
    {
     public int Left, Top, Right, Bottom;
     public RECT(int l, int t, int r, int b)
     {
      Left = l;
      Top = t;
      Right = r;
      Bottom = b;
     }
     public RECT(Rectangle r)
     {
      Left = r.Left;
      Top = r.Top;
      Right = r.Right;
      Bottom = r.Bottom;
     }
     public Rectangle ToRectangle()
     {
      return Rectangle.FromLTRB(Left, Top, Right, Bottom);
     }
    }
    
    Rectangle rClose = new Rectangle(0, 0, closeButton.Width, closeButton.Height);
    RECT reClose = new RECT(rClose);
    

    Although Format32bppArgb does work for me, the format should really be Format32bppPArgb.


  • xyzt

    Well, I was assigning it to a PictureBox (I'm trying to fake a themed close button). I also called Save on it so I could check it out as a PNG, but the image is non-transparent there too.

    A clarification - the image I get is index-transparent, but not alpha transparent. There are little bits that are transparent, but none of the pixels on the edge are half-transparent.  

  • JohnVP

    I just tried that out (Yeah, I forgot about this thread and gave up) and it still doesn't work...

  • Trouble drawing theme elements transparently