MFC 開發中,窗口被其他窗口遮擋後恢復,按鈕上的圖標消失,需滑過才顯示;且嵌套 Tab 控件間通信困擾開發者。本文分析自繪按鈕重繪機制,並提供 Tab 控件跨頁面數據交互的標準做法。
CButton::SetIcon 設置圖標若按鈕設置了 BS_OWNERDRAW 風格(自繪),系統不再自動繪製圖標,開發者必須重寫 DrawItem 虛函數手動繪製。被覆蓋後收到 WM_PAINT,若 DrawItem 未正確繪製圖標,則顯示空白。
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rect = lpDrawItemStruct->rcItem;
UINT state = lpDrawItemStruct->itemState;
// 繪製背景
pDC->FillSolidRect(rect, GetSysColor(COLOR_BTNFACE));
// 繪製圖標
if (m_hIcon) {
CSize size(32, 32); // 圖標尺寸
CPoint pt((rect.Width() - size.cx) / 2, (rect.Height() - size.cy) / 2);
::DrawIconEx(pDC->GetSafeHdc(), pt.x, pt.y, m_hIcon, size.cx, size.cy, 0, NULL, DI_NORMAL);
}
// 繪製焦點矩形
if (state & ODS_FOCUS) {
pDC->DrawFocusRect(rect);
}
}
確保按鈕類繼承 CButton 並聲明 virtual void DrawItem(LPDRAWITEMSTRUCT)。
CTab2(CWnd* pParentTab1)this:m_tab2 = new CTab2(this)m_pParentTab1 = pParentTab1m_pParentTab1->UpdateTab2Edit(value)m_tab2.GetDlgItem(IDC_EDIT)->SetWindowText(...)
// Tab1.h
class CTab1 : public CTabCtrl {
public:
CTab2* m_pTab2;
void UpdateTab2Edit(CString str); // 公共接口
};
// Tab1.cpp
void CTab1::OnButtonClick() {
if (m_pTab2) m_pTab2->SetEditValue(_T("新值"));
// 或調用自身公共方法
UpdateTab2Edit(_T("新值"));
}
void CTab1::UpdateTab2Edit(CString str) {
if (m_pTab2) {
CWnd* pEdit = m_pTab2->GetDlgItem(IDC_EDIT2);
if (pEdit) pEdit->SetWindowText(str);
}
}
// Tab2 創建時
m_pTab2 = new CTab2(this); // 傳遞 this
WM_USER_UPDATE_EDITGetParent()->SendMessage(WM_USER_UPDATE_EDIT, 0, (LPARAM)str)