I have a WIN32 owner-drawn static control that draws a progress bar using two source images (filled and unfilled). Works great on the initial draw:
case WM_DRAWITEM:
{
DRAWITEMSTRUCT* draw = (DRAWITEMSTRUCT*)lparam;
// Manually draw the progress bar.
if( draw->hwndItem == hwndProgress )
{
// Progress bar is 526 pixels wide.
int left = progressPercent * 526 / 100;
// Paint sections of window with filled and unfilled bitmaps
// based on progress bar position.
HDC hdcMem = ::CreateCompatibleDC(draw->hDC);
::SelectObject(hdcMem, hBmpProgressFull);
::BitBlt(draw->hDC, 0, 0, left, 36, hdcMem, 0, 0, SRCCOPY);
::DeleteDC(hdcMem);
HDC hdcMem2 = ::CreateCompatibleDC(draw->hDC);
::SelectObject(hdcMem2, hBmpProgressEmpty);
::BitBlt(draw->hDC, left, 0, 526-left, 36, hdcMem2, left, 0, SRCCOPY);
::DeleteDC(hdcMem2);
return TRUE;
}
}
return 0;
However, I can’t seem to get the thing to erase and repaint properly. I’ve tried SendMessage with WM_PAINT and RedrawWindow and neither one has worked quite right:
bool SetLoginProgressBar(float value)
{
if( hwndProgress != NULL )
{
progressPercent = (int)(value * 100.0);
//::RedrawWindow(hwndProgress, NULL, NULL, RDW_INVALIDATE|RDW_INTERNALPAINT);
::SendMessage(hwndProgress, WM_PAINT, NULL, NULL);
}
return true;
}
Instead of redrawing the window with the new values, it just sits there with the initially drawn image and ignores further drawing commands. It draws the progress correctly for the initial value, whether it’s 0%, 50%, etc, and I can verify that my WM_DRAWITEM message handler code is being called.
So, what is the correct way to tell this control to erase and redraw in WIN32?
Is is possible that I need to do something like BeginPaint/EndPaint, or delete the hDC in the DRAWITEMSTRUCT that I’ve been passed?
You aren’t deselecting the bitmaps from the memory DC before you destroy the DC. Perhaps the bitmaps are in a state where Windows won’t allow you to select them again, so the BitBlts are failing.
P.S. RedrawWindow is what I use in this situation. InvalidateRect works too, but only if your message loop is running. Which leads to another observation: if you’re in the middle of a long running operation, you may not get back to the message loop and your app will appear to be hung, including updates to the progress window.