这段代码有点奇怪,特别是因为你没有给我们任何上下文。什么是dc
设备上下文?此代码是否在OnPaint
消息处理函数中?无论哪种方式,为什么要手动绘制图标而不是让按钮控件自动绘制?
更简单的方法是通过成员函数监听WM_ENABLE
消息OnEnable
,并调用SetIcon
成员函数更新按钮的图标来监控控件的启用状态。这样,按钮控件会跟踪图标,因此无需将其保存在成员变量 ( m_hIcon
) 中。删除图标就像将其设置为显示空图标一样简单。没有必要或所有这些丑陋的技巧,例如使用第二个透明图标,或用纯色矩形在图标上绘制。
示例代码,其中CMyButton
扩展CButton
:
void CMyButton::OnEnable(BOOL bEnable)
{
CButton::OnEnable(bEnable); // call the base class
if (bEnable)
{
// The button was enabled, so load and set the icon.
const HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
this->SetIcon(hIcon);
}
else
{
// The button was disabled.
// First, retrieve the current icon from the button.
const HICON hIcon = this->GetIcon();
// Then, remove the icon from the button by setting a null icon.
this->SetIcon(NULL);
// Finally, delete the original icon to prevent memory leaks.
::DestroyIcon(hIcon);
}
}
当然,OnPaint
如果您绝对必须的话,可以在函数内部按自己的方式进行操作(尽管这是糟糕的设计)。诀窍是图标只有在绘制它的代码被执行时才会被绘制。否则,不会绘制任何图标。基类不会绘制图标。
所以你只需要:
void CMyWindow::OnPaint()
{
CPaintDC dc(this);
const CWnd* pBtn = GetDlgItem(IDC_BUTTON1);
if (pBtn->IsWindowEnabled())
{
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
dc.DrawIcon(DT_CENTER, DT_CENTER, m_hIcon);
// make sure that you delete m_hIcon when the window is destroyed!
}
else
{
// Do not draw the icon here!
// But write whatever other code you want, like...
dc.SetTextColor(RGB(192,192,192));
}
}
显然,这种策略只有在您的代码位于OnPaint
函数内部时才有效,但您应该在此处进行所有绘图。否则,无论何时重新绘制窗口,它都会丢失。对于演示,只需尝试最小化窗口或将其移出屏幕即可。通过调用强制重绘CWnd::Invalidate
,后跟CWnd::UpdateWindow
(或 `CWnd::RedrawWindow)。