0

In my program I have a custom window frame, the frame is extended using DwmExtendFrameIntoClientArea. I have placed a button control on top of the frame, the problem is that the button text is black and it is transparent. I am trying to use the BufferedPaintXXX functions and I've subclassed the button to try and make the button opaque.

I have hooked the WM_PAINT handler, and this is the solution I've come up with:

if (msg == WM_PAINT)
    {
        PAINTSTRUCT ps;
        if (BeginPaint(hWnd, &ps))
        {
            HDC bHdc;
            HPAINTBUFFER buffer = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_TOPDOWNDIB, NULL, &bHdc);
            if (buffer)
            {
                SendMessageW(hWnd, WM_PRINTCLIENT, (WPARAM)bHdc, PRF_CLIENT | PRF_ERASEBKGND);
                BufferedPaintMakeOpaque(buffer, NULL);
                EndBufferedPaint(buffer, TRUE);
            }
            EndPaint(hWnd, &ps);
        }

        return 0;
    }

This works, however there is one problem: there are no more animations on the button control. For example, when hovering over the button, there is no more "fade in" effect that the control usually has, instead, the pointer-over state is painted, so it just appears. I suspect this is because of the WM_PRINTCLIENT usage.

So in order to get the nice animations back, I tried another approach:

    if (msg == WM_PAINT)
    {
        DefSubclassProc(hWnd, msg, wParam, lParam);
        RECT rc;
        GetClientRect(hWnd, &rc);
        HDC dc = GetDC(hWnd), bHdc;
        HPAINTBUFFER buffer = BeginBufferedPaint(dc, &rc, BPBF_TOPDOWNDIB, NULL, &bHdc);
        
        BitBlt(bHdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, dc, 0, 0, SRCCOPY);
        BufferedPaintMakeOpaque(buffer, NULL);
        EndBufferedPaint(buffer, TRUE);
        ReleaseDC(hWnd, dc);
        return 0;
    }

This solution does work, the animations do appear, however, since I'm calling DefSubclassProc, the button control is drawing onto the screen first. Then, my buffered logic takes over, then draws the opaque client area over the button control's current client area. The problem with this is that there is an occasional flicker between the semi-transparent drawing performed by the button control and then it being immediately overwritten by the buffered paint calls.

Is there a way to "set" the DC of the control to a buffered paint HDC, so that I won't have to get a flicker while painting, and so that I can keep the button animations? Or is there a better way to approach this?

I am aware that I can change the color key using SetLayeredWindowAttributes, however, I don't want to do that, and also I'll be displaying images and I can't risk random colors becoming transparent.

Arush Agarampur
  • 1,340
  • 7
  • 20

0 Answers0