【问题标题】:Updating text in a C Win32 API STATIC control drawn with WS_EX_TRANSPARENT更新使用 WS_EX_TRANSPARENT 绘制的 C Win32 API STATIC 控件中的文本
【发布时间】:2010-12-21 21:16:51
【问题描述】:

我的窗口上有一些静态标签和按钮。 我将所有标签都设为透明背景,这样我就可以将背景设为红色。 在 CALLBACK 中,我处理 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 应该确保父控件在控件之前绘制。检查我的最新编辑,其中我使控件和父级都无效。
  • 再来一次:将第二个 InvalidateRect 替换为 RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE); 我也会更新我的答案。
  • P.S.我感觉到你的痛苦,我也很难让静态控件正确更新。很明显,Windows 不希望它们在绘制后发生变化。

标签: c++ winapi


【解决方案1】:

在控件占用的矩形上使用 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'
  • 已修复,至少我希望如此。这就是我从头顶输入代码得到的结果。
  • 在本例中,RedrawWindow(hwnd, &rect, NULL, RDW_ERASE | RDW_INVALIDATE) 与 InvalidateRect(hwnd, &rect, TRUE) 相同。
  • @MarkIngram 我相信不是,因为使静态控件无效并不会删除它。自己试试吧。
  • @MarkRansom 它使父级无效,而不是子级静态。我已经为自己尝试过,它与更简单的InvalidateRect 通话非常有效:-)。
猜你喜欢
  • 2023-03-15
  • 2010-09-24
  • 2021-12-04
  • 2010-12-28
  • 2020-11-13
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多