標準 Windows 控制項 (Edit、ComboBox、ListBox 等) 不支援背景圖片屬性。本文示範如何繼承 CEdit 實作 CMyEditCtrl,透過覆寫 OnEraseBkgnd 繪製背景圖、CtlColor 設定透明文字模式、OnChange/OnLButtonUp 強制重繪解決殘留問題,並支援執行期切換背景圖。
class CMyEditCtrl : public CEdit {
public:
CBitmap m_bmp; // 背景位圖
protected:
CBrush m_brHollow; // 空心筆刷 (透明背景用)
CBitmap* m_pbmCurrent; // 目前繪製位圖指標
// 訊息對應
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnChange();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
DECLARE_MESSAGE_MAP()
};
BOOL CMyEditCtrl::OnEraseBkgnd(CDC* pDC) {
BITMAP bm; m_bmp.GetBitmap(&bm);
m_pbmCurrent = &m_bmp;
CDC memDC; memDC.CreateCompatibleDC(pDC);
CBitmap* pOld = memDC.SelectObject(m_pbmCurrent);
pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(pOld);
return TRUE; // 告訴系統背景已處理,不再預設填滿
}
HBRUSH CMyEditCtrl::CtlColor(CDC* pDC, UINT nCtlColor) {
pDC->SetBkMode(TRANSPARENT); // 關鍵:透明背景模式
pDC->SetTextColor(RGB(255,255,255)); // 白色文字 (依背景調整)
return m_brHollow; // 回傳空心筆刷
}
建構子中需初始化 m_brHollow.CreateStockObject(HOLLOW_BRUSH)。
void CMyEditCtrl::OnChange() {
Invalidate(); // 強制觸發 WM_PAINT -> OnEraseBkgnd -> 重繪背景+文字
}
void CMyEditCtrl::OnLButtonUp(UINT nFlags, CPoint point) {
Invalidate(); // 解決選取反白後背景不更新問題
CEdit::OnLButtonUp(nFlags, point);
}
void CMyEditCtrl::SetBackgroundBitmap(UINT nResourceID) {
m_bmp.DeleteObject();
m_bmp.LoadBitmap(nResourceID);
Invalidate(); // 立即更新
}
CMyEditCtrl 基於 CEdit,加入成員變數關聯控制項。OnInitDialog 中:m_MyEdit.SetBackgroundBitmap(IDB_MYBACKGROUND)。OnEraseBkgnd 使用 StretchBlt 縮放或平鋪。SetTextColor 方法依背景亮度自動調整。Invalidate 可能導致閃爍,可改用雙緩衝或僅更新變更區域 (InvalidateRect)。CListBox、CComboBox、CTreeCtrl 等控制項。透過 OnEraseBkgnd 繪製背景 + CtlColor 透明文字 + 關鍵事件強制重繪,即可讓標準 Edit 控制項擁有豐富視覺效果,技術成熟穩定,廣泛應用於皮膚化介面開發。