4

I have window with some STATIC labels and BUTTONs on it. I make all the LABELS transparent background so I can make the background RED say. In the CALLBACK i process the WM_CTLCOLORSTATIC message, determine the ID of the control with GetDlgCtrlID() and then:

SetBkMode((HDC)wParam, TRANSPARENT); // Make STATIC control Bkgd transparent
return (INT_PTR)(HBRUSH)GetStockObject(NULL_BRUSH);

So far so good. Form is drawn, background is RED and label text is drawn on top.

After user interaction I need to change the text, so I issue a SetDlgItemText() message and the new text is draw. The problem is the old text is not erased, and the new text is drawn on top of it.

Having read somewhat today, it seems the problem is the controls parent (the form) is responsible for drawing the background. This means that when you change the label text, the control redraws the new text, BUT the form doesn't automatically redraw the background.

THe question is HOW do I force the form to redraw the rectangle area of the label control (preferably without subclassing anything)?

ADDED:

I have tried the following:

HWND hctrl;
hctrl = GetDlgItem(hwnd, ControlID);
RedrawWindow( hctrl, 0, 0, 
RDW_UPDATENOW || RDW_ALLCHILDREN || RDW_FRAME || RDW_INVALIDATE || RDW_ERASE || RDW_INTERNALPAINT ); // RDW_UPDATENOW 

and:

I am not handling the WM_PAINT message at all, only:

case WM_CTLCOLORSTATIC:
 SetBkMode((HDC)wParam, TRANSPARENT); 
 return (INT_PTR)(HBRUSH)GetStockObject(NULL_BRUSH);




int Library::SetControlTxt( int ControlID, string sText  ) // Dialog Out
{ 
 int RetVal;

  RetVal = SetDlgItemText( hwnd, ControlID, sText.c_str() ); 
  RECT rect;
  HWND hctrl;
  hctrl = GetDlgItem(hwnd, ControlID);
  GetClientRect(hctrl, &rect);
  MapWindowPoints(hctrl, hwnd, (POINT *)&rect, 2);
  InvalidateRect(hwnd, &rect, TRUE);

       return RetVal;
} 

Mark, Thank you this works.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Mike Trader
  • 8,564
  • 13
  • 55
  • 66
  • RDW_ERASE won't do any good, because you've disabled the erase in your WM_CTLCOLORSTATIC handler. But the WS_EX_TRANSPARENT should insure that the parent is drawn before the control. Check my latest edit where I invalidate both the control and the parent. – Mark Ransom Dec 01 '09 at 04:41
  • One more time: replace the second InvalidateRect with `RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE);` I'll update my answer too. – Mark Ransom Dec 01 '09 at 05:59
  • P.S. I feel your pain, I've had trouble getting static controls to update properly too. It's obvious Windows doesn't expect them to change once they're drawn. – Mark Ransom Dec 01 '09 at 06:03

2 Answers2

5

Use InvalidateRect on the rectangle occupied by the control.

RECT rect;
GetClientRect(hctrl, &rect);
InvalidateRect(hctrl, &rect, TRUE);
MapWindowPoints(hctrl, hwnd, (POINT *) &rect, 2);
RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE);
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

Another simple and short solution -

ShowWindow(hctrl, SW_HIDE);
// do the actual update
ShowWindow(hctrl, SW_SHOW);