【发布时间】:2015-07-01 08:53:00
【问题描述】:
让我从目标开始:我要将静态控件的背景设置为对话框,而静态控件的内容不是固定字符串,并且在 switch case 语句之后会发生变化。换句话说,我打算将具有动态内容的静态控件的背景设置为具有静态双图图像的对话框窗口。
为了达到这个目标,三个句柄消息定义如下: OnEraseBkgnd(), OnDestroy(), OnCtlColor()
为了显示文本,在每个 Switch case 语句之后,我设置了一个 SetWindowText 函数:
::SetWindowText(GetDlgItem(IDC_STATIC_FORM)->m_hWnd, ArrayName);
这里唯一的问题是overlapping。预览事件或案例的所有文本仍保留在SetWindowText。为了在每个SetWindowText 定义一个 InvalidateRect(Null) 之后解决这个问题并且这个问题也解决了,但是在这个过程中我收到了一个总是闪烁的对话框,如果我从技术上说,闪烁。我认为问题只是因为 Invalidate 应用于整个对话框而不仅仅是静态控制。 OnCtlColor 被覆盖对话框而不是控件。因为我只是想让控件失效,所以我必须继承 CStatic 控件,只覆盖它的 OnCtlColor(不是对话框的),并且只调用它的 Invalidate。
我的问题:
假设我在主代码中声明了一个用于静态控制的变量并在构造函数中对其进行了初始化,我使用基类 CDialogEX 定义了一个名为 CSTATICCTRL 的类,那么消息处理程序如下:
变量成员定义为:
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
}
我也在主代码上留下了这些信息。然后我尝试以这种方式在每个 switch case 之后使静态控件无效:
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);
}
【问题讨论】:
-
您对 Windows API 的了解是否足以理解,MFC 与它有何关系?听起来您几乎迷失了方向,试图同时学习两种 API,其中一种是另一种的强制性先决条件。
-
还没有!!!!不过我正在学习。好的,谢谢。
-
@IInspectable 你可以同时学习两者,我就是这样做的。但是你需要注意界限。还有一些我不太了解的东西,比如父窗口和子窗口之间的消息路由,因为 MFC 对你隐藏了一些。
-
@Mark:正如您所指出的,当您尝试同时学习两者时,您将无法同时流利地学习两者。我宁愿不提倡浪费时间,因为回报太少。此外,MFC 不会隐藏任何东西。如果您需要了解消息路由,可以阅读 TN 文章,如果需要,还可以阅读源代码。
标签: c++ visual-c++ mfc subclass static-content