WM_PAINT with PROGRESS_CLASS

801 Views Asked by At

I'm creating Win32 control:

m_progress = CreateWindowExW(0, PROGRESS_CLASSW, L"ProgressBar", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 153, 339, 135, 33, m_window, (HMENU)0, m_instance, 0);
SendMessageW(m_progress, WM_SETFONT, (WPARAM)m_fontBold, TRUE);
SendMessageW(m_progress, PBM_SETRANGE, 0, MAKELPARAM(0, 100));

It's working, but I also want to draw text with percentage on it So I've subclassed progress control like this:

m_progressPrevProc = (WNDPROC)SetWindowLongPtrW(m_progress, GWLP_WNDPROC, (LONG_PTR)ProgressMsgProcessor);
...
static LRESULT CALLBACK ProgressMsgProcessor(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    if (msg == WM_PAINT)
    {
        PAINTSTRUCT ps;
        RECT rc = { 5, 5, 135, 33 };
        //HDC hdc = BeginPaint(hwnd, &ps);
        //SelectObject(hdc, g_App.m_fontBold);
        //DrawTextA(hdc, "100 %", -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        //EndPaint(hwnd, &ps);
    }

    return CallWindowProcW((WNDPROC)PrevWndProcProzess, hwnd, msg, wparam, lparam);
}

But if uncomment atleast "HDC hdc = BeginPaint(hwnd, &ps);" then text appears, but default control absolutely disappears (like it's not drawn) How can I fix it to show default windows control with text on it, because I don't need to draw custom control, only add overlay text? Thank you

1

There are 1 best solutions below

3
Paul Sanders On BEST ANSWER

The problem here is that you cleared the update region with your BeginPaint and EndPaint calls, so the progress bar doesn't think it has to draw anything. It's a weakness of the way WM_PAINT works that you can't paint over an existing control in this way. Instead, you have to do something like this:

static LRESULT CALLBACK ProgressMsgProcessor(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    if (msg == WM_PAINT)
    {
        // Paint the control first
        CallWindowProcW ((WNDPROC)PrevWndProcProzess, hwnd, msg, wparam, lparam);

        // Then draw over it
        HDC hDC = GetDC (hwnd);
        HFONT hOldFont = (HFONT) SelectObject(hDC, g_App.m_fontBold);

        // Draw your own stuff into hDC

        SelectObject (hDC, hOldFont);
        ReleaseDC (hwnd, hDC);
        return 0;
    }

    return CallWindowProcW ((WNDPROC)PrevWndProcProgress, hwnd, msg, wparam, lparam);
}

Other notes:

  • Your code as posted is drawing under the control, not over it (!). My code fixes that.
  • If you select and object into a DC, you should select the old one back in when you are done. Again, my code shows how to do this.