我的主代码中有一个回调函数,包括Switch case语句。在每个案例之后,我定义了一个SetWindowText
函数来打印在对话框(或父窗口)上创建的静态控件中的文本,如下所示:
::SetWindowText(GetDlgItem(IDC_STATIC)->m_hWnd, "loading");
我将静态控件的背景设置为对话框的背景。一切顺利,除了相互放置的所有案例的文本,我收到一个带有重叠文本的静态控件,如下所示:
我不知道为什么在每一步都没有关闭静态窗口以避免这种问题。
我添加了OnEraseBkgnd
,OnDestroy
,OnCtlColor
消息,如下所示:
BOOL CmainDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmap* pOldbitmap = dcMemory.SelectObject(&CBmp);
CRect rcClient;
GetClientRect(&rcClient);
const CSize& sbitmap = bitmapSize;
pDC->BitBlt(0, 0, sbitmap.cx, sbitmap.cy, &dcMemory, 0, 0, SRCCOPY);
dcMemory.SelectObject(pOldbitmap);
return TRUE;
}
HBRUSH CmainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd->GetDlgCtrlID() == IDC_STATIC)
//Example of changing Text colour specific to a certain
//Static Text Contol in this case IDC_STATIC.
{
pWnd->GetExStyle() & (WS_EX_TRANSPARENT);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255, 255, 255));
}
if (pWnd->GetDlgCtrlID() == IDC_OPERATION)
{
pWnd->GetExStyle() & (WS_EX_TRANSPARENT);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255, 255, 0));
// Return handle to our CBrush object
}
return reinterpret_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
}
void CmainDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
Background.DeleteObject(); // Delete Background bitmap
BrushHol.DeleteObject();
}
//subclass the static control, just to make sure the code is the only one handling WM_ERASEBKGND and WM_PAINT messages.
void CmainDlg::PreSubclassWindow()
{
CWnd::PreSubclassWindow();
const LONG_PTR exStyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, exStyle | WS_EX_TRANSPARENT);
}
更新
我评论了OnEraseBkgnd
,OnDestroy
,OnCtlColor
个函数。所以我收到了相同的重叠文本,现在更确定一点,我可以说问题来自setWindowText
,因为在完成每个 Case 后,文本仍保留在我在每个中定义的静态控制窗口开关案件的声明。
我尝试使用以下命令但没有发生任何事情:
EnableWindow( GetDlgItem(m_hWnd, IDC_STATIC), FALSE);
m_static.EnableWindow(FALSE);
或
::SetDlgItemText(m_hWnd, IDC_STATIC, "");
我会感激任何帮助。
答案 0 :(得分:3)
最简单的解决方案是:
唯一的技巧是将对话框的颜色变为COLORREF。如果您正在使用标准内容,则可以使用其中一种库存颜色常量调用GetSysColor。
如果对话框背景不是纯色(例如,渐变填充),则您必须做更复杂的事情:
WS_EX_TRANSPARENT样式应该使静态控件下面的对话框部分在静态控件之前被绘制。那应该&#34;擦除&#34;上一个文本,然后静态控件将绘制新文本。
请注意,WS_EX_TRANSPARENT也会生成控件transparent to hit testing(例如,鼠标点击)。由于它是一个静态控制,这不重要。但这就是为什么这不是其他类型控件的通用解决方案。
答案 1 :(得分:3)
绘制不透明:
使用m_Brush
初始化CreateSolidBrush
并使用SetBkMode(OPAQUE)
代替TRANSPARENT
绘图透明:
按照Adrian McCarthy的回答和 return (HBRUSH)GetStockObject(NULL_BRUSH)
进行静态控制,而不是返回m_Brush
。
确保对话框没有 WS_CLIPCHILDREN
标记,否则在静态控件中重写文本时会遇到相同的重叠问题。
应该这样做。
另一个选项,此代码将其他控件与背景图像(编辑控件,单选按钮和复选框)混合使用Dialog可以有WS_CLIPCHILDREN
标志,但如果要重绘,静态控件将需要一个正ID( IDC_STATIC
通常设置为-1)。对话框项目也需要WS_EX_TRANSPARENT
标记。我没有测试过这么多。
不要忘记将ON_WM_DESTROY
添加到留言地图。
class TDlg : public CDialogEx
{
public:
std::map<int, HBRUSH> BrushMap;
CBitmap Bitmap;
TDlg(int id, CWnd *wnd) : CDialogEx(id, wnd){};
void MakeBrush(CDC *pdc, CDC &memdc, int id);
BOOL OnEraseBkgnd(CDC* pDC);
void OnDestroy();
BOOL OnInitDialog();
HBRUSH OnCtlColor(CDC* pDC, CWnd* wnd, UINT nCtlColor);
DECLARE_MESSAGE_MAP()
};
BOOL TDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
Bitmap.LoadBitmap(IDB_BITMAP1);
return 1;
}
void TDlg::OnDestroy()
{
CDialogEx::OnDestroy();
Bitmap.DeleteObject();
for (std::map<int, HBRUSH>::iterator it = BrushMap.begin(); it != BrushMap.end(); ++it)
if (it->second)
DeleteObject(it->second);
}
void TDlg::MakeBrush(CDC *pdc, CDC &memdc, int id)
{
CWnd *item = GetDlgItem(id);
CRect rc;
item->GetClientRect(&rc);
item->MapWindowPoints(this, &rc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&memdc, rc.Width(), rc.Height());
memdc.SelectObject(bmp);
memdc.BitBlt(0, 0, rc.Width(), rc.Height(), pdc, rc.left, rc.top, SRCCOPY);
BrushMap[id] = CreatePatternBrush(bmp);
}
BOOL TDlg::OnEraseBkgnd(CDC* pDC)
{
BITMAP bm;
Bitmap.GetBitmap(&bm);
CDC memdc;
memdc.CreateCompatibleDC(pDC);
CBitmap* pOldbitmap = memdc.SelectObject(&Bitmap);
pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memdc, 0, 0, SRCCOPY);
//BrushMap should be intialized once
if (!BrushMap.size())
for (CWnd *p = GetWindow(GW_CHILD); p; p = p->GetNextWindow(GW_HWNDNEXT))
if (p->GetDlgCtrlID() > 0)
MakeBrush(pDC, memdc, p->GetDlgCtrlID());
memdc.SelectObject(pOldbitmap);
return TRUE;
}
HBRUSH TDlg::OnCtlColor(CDC* pDC, CWnd* wnd, UINT nCtlColor)
{
HBRUSH br = CDialogEx::OnCtlColor(pDC, wnd, nCtlColor);
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkMode(TRANSPARENT);
int id = wnd->GetDlgCtrlID();
if (id > 0 && BrushMap[id])
return BrushMap[id];
if (nCtlColor == CTLCOLOR_STATIC)
return (HBRUSH)GetStockObject(NULL_BRUSH);
return br;
}