使用WS_EX_TRANSPARENT绘制的C Win32 API STATIC控件中更新文本

4

我有一个窗口,上面有一些静态标签和按钮。我将所有标签设置为透明背景,这样我就可以将背景设置为红色。

在回调函数中处理WM_CTLCOLORSTATIC消息,使用GetDlgCtrlID()确定控件的ID,然后执行以下操作:

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

目前为止还不错。表格已绘制,背景为红色,标签文本位于顶部。

用户交互后,我需要更改文本,所以我发出了一个 SetDlgItemText() 消息,并绘制了新文本。问题是旧文本没有被擦除,新文本在其上绘制。

根据今天的一些阅读,似乎问题在于控件的父级(即表格)负责绘制背景。这意味着当您更改标签文本时,控件会重新绘制新文本,但表格不会自动重新绘制背景。

问题是如何强制表格重新绘制标签控件的矩形区域(最好不要子类化任何内容)?

添加:

我已尝试以下操作:

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

同时:

我并没有处理WM_PAINT消息,只有:

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;
} 

马克,谢谢,这个可行。


RDW_ERASE不会起作用,因为您在WM_CTLCOLORSTATIC处理程序中禁用了擦除功能。但是WS_EX_TRANSPARENT应该确保在控件之前绘制父级。请检查我的最新编辑,我同时使控件和父级失效。 - Mark Ransom
再试一次:将第二个InvalidateRect替换为RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE); 我也会更新我的答案。 - Mark Ransom
我感同身受,我也曾经遇到过静态控件无法正确更新的问题。很明显,Windows并不希望它们在绘制后再发生变化。 - Mark Ransom
2个回答

6
使用InvalidateRect函数在控件所占据的矩形区域上进行无效化处理。
RECT rect;
GetClientRect(hctrl, &rect);
InvalidateRect(hctrl, &rect, TRUE);
MapWindowPoints(hctrl, hwnd, (POINT *) &rect, 2);
RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE);

'MapWindowPoints':无法将第3个参数从'RECT *'转换为'LPPOINT'。 - Mike Trader
修好了,至少我希望是这样。这就是我从脑海中打代码的后果。 - Mark Ransom
在此示例中,RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE)InvalidateRect(hwnd, &rect, TRUE) 相同。 - Mark Ingram
1
@MarkIngram 我认为不是这样的,因为使静态控件无效并不会擦除它。你可以自己试试看。 - Mark Ransom
@MarkRansom 它是使父级失效,而不是子级静态。我已经亲自尝试过了,并且使用更简单的 InvalidateRect 调用完全正常 :-)。 - Mark Ingram

0

另一个简单而短小的解决方案 -

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接