让我先从目标开始:我将静态控件的背景设置为对话框,而静态控件内容不是固定字符串,并且在切换案例语句之后更改。换句话说,我将把带有动态内容的静态控件的背景设置为带有静态bimap图像的对话窗口。
为了达到这个目标,三个句柄消息定义如下: OnEraseBkgnd(),OnDestroy(),OnCtlColor()
为了显示文本,在每个Switch case语句之后我设置了一个SetWindowText函数:
::SetWindowText(GetDlgItem(IDC_STATIC_FORM)->m_hWnd, ArrayName);
这里唯一的问题是overlapping。预览事件或案例中的所有文本都保留在SetWindowText
。要在每个SetWindowText
定义一个InvalidateRect(Null)之后解决这个问题,这个问题也解决了,但是在程序中我收到了一个总是闪烁的对话框,如果我在技术上说,闪烁。我认为问题只是因为Invalidate应用于整个对话框而不仅仅是静态控件。对于对话而不是控件,OnCtlColor被覆盖。因为我只想让控件无效,所以我必须继承CStatic控件,只覆盖它的OnCtlColor(不是对话框),而只调用它的Invalidate。
我的问题:
假设我在主代码中为静态控件声明了一个变量,并在构造函数中初始化它,我定义了一个名为CSTATICCTRL的类,其基类为CDialogEX,那么消息处理程序如下:
变量成员定义为:
CSTATICCTRL m_STATIC_FORM;
和
BOOL CSTATICCTRL::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmap* pOldbitmap = dcMemory.SelectObject(&Background);
CRect rcClient;
const CSize& sbitmap = bitmapSize;
pDC->BitBlt(0, 0, sbitmap.cx, sbitmap.cy, &dcMemory, 0, 0, SRCCOPY);
/*The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels
from the specified source device context into a destination device context.*/
dcMemory.SelectObject(pOldbitmap);
return 1;
//return CDialogEx::OnEraseBkgnd(pDC);
}
HBRUSH CSTATICCTRL::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
//HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd->GetDlgCtrlID() == IDC_STATIC_FORM)
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255, 255, 255));
Invalidate();
}
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
void CSTATICCTRL::OnDestroy() //free the resources created for the bitmap,
{
CDialog::OnDestroy();
Background.DeleteObject(); // Delete Background bitmap
BrushHol.DeleteObject();
// Delete Brush
}
我也将这些消息留在了主代码上。然后我尝试以这种方式在每个开关案例之后使静态控件无效:
m_STATIC_FORM.Invalidate();
此外,在新类的末尾添加了一个PreSubclassWindow()句柄,如下所示。
void CSTATICCTRL::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
CDialogEx::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW); // make the button owner drawn
}
什么都没发生!我不知道我的代码有什么问题!!以这种新的方式,静态控制内容发生了变化,但它不透明,重叠仍然存在。
更新
实际上刚才我意识到新的Class在评论一些行后对静态控件和对话框没有任何影响!!我想首先我应该激活CSTATICCTRL然后我可以处理它的句柄消息。
对于对话框代码,使用了这三个句柄消息:
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(&Background);
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;
//return CDialog::OnEraseBkgnd(pDC);
}
void CMainDlg::OnDestroy() //free the resources created for the bitmap,
{
CDialog::OnDestroy();
// Delete Brush
}
HBRUSH CMainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
// TODO: Change any attributes of the DC here
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
答案 0 :(得分:2)
我没试过这个,但我认为它会起作用。
在对话框中覆盖OnCtlColor
。当它检测到正在绘制静态控件时,返回空刷。这样可以防止背景被擦除,这是导致闪烁的原因。
在静态控件上设置WS_EX_TRANSPARENT
样式。这将导致控件下方的对话框部分在绘制控件之前重新绘制,从而删除旧文本。
编辑:根据an article by Raymond Chen WS_EX_TRANSPARENT
样式在这种情况下无效,因为对话框不是静态控件的兄弟,它是父对象。您可以使用RedrawWindow
重新绘制静态控件下方的部分。
您不应该需要自己的课程,CStatic
可以正常使用这些修改。如果你做决定你需要你自己的类,你不应该从CDialogEx
派生它,那应该保留给对话窗口。
pStatic->SetWindowText(str);
CRect rcChild;
pStatic->GetClientRect(&rcChild);
pStatic->MapWindowPoints(this, &rcChild);
RedrawWindow(rcChild, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
pStatic->InvalidateRect(NULL);