Transparent 無效?MFC CComboBox 繼承自 CWnd,預設由系統繪製下拉列表框與編輯框,WS_EX_TRANSPARENT 僅影響視窗合成層級,不改變控件自身繪製邏輯。Windows 原生 ComboBox 不支援透明背景繪製,必須子類化並處理 WM_CTLCOLORLISTBOX/WM_CTLCOLOREDIT 或完全自繪。
// MyComboBox.h
class CMyComboBox : public CComboBox {
DECLARE_MESSAGE_MAP()
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
};
// MyComboBox.cpp
BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()
HBRUSH CMyComboBox::CtlColor(CDC* pDC, UINT nCtlColor) {
// 設置文字/背景模式為透明
pDC->SetBkMode(TRANSPARENT);
// 返回空畫筆,讓父視窗背景透出
return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
}
父視窗 OnCtlColor 需返回真實背景畫筆(如位圖畫筆),ComboBox 區域即顯示父視窗背景。
MeasureItem、DrawItem、CompareItem、DeleteItem。DrawItem 範例:
void CMyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rc = lpDrawItemStruct->rcItem;
UINT state = lpDrawItemStruct->itemState;
// 1. 繪製背景(透明:直接不填充,或填充父視窗背景色)
if (state & ODS_SELECTED) {
pDC->FillSolidRect(rc, GetSysColor(COLOR_HIGHLIGHT));
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
} else {
// 透明:不填充,或 pDC->FillSolidRect(rc, parentBgColor);
pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
}
// 2. 繪製文字
if (lpDrawItemStruct->itemID != -1) {
CString str;
GetLBText(lpDrawItemStruct->itemID, str);
pDC->DrawText(str, rc, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
}
// 3. 焦點矩形
if (state & ODS_FOCUS) pDC->DrawFocusRect(rc);
}
視窗設置 WS_EX_LAYERED,UpdateLayeredWindow 合成 Alpha 通道位圖,實現半透明/漸變/不規則形狀。適用於整個對話框/控件組透明,單個 ComboBox 維護成本高。
GetComboBoxInfo 可獲取 hwndList),需單獨子類化或設置 WM_CTLCOLORLISTBOX。CBS_DROPDOWN)發送 WM_CTLCOLOREDIT,同樣需處理。GetStockObject(HOLLOW_BRUSH) 可能閃爍,建議緩存自定義空畫筆 CreateSolidBrush + SetBrushOrgEx。InitCommonControlsEx + Manifest)下系統繪製優先,Owner Draw 需手動模擬視覺狀態(熱點、按下、禁用)。總結:繼承 CComboBox,映射 ON_WM_CTLCOLOR_REFLECT,返回 HOLLOW_BRUSH 並設置 TRANSPARENT 模式 是成本最低、兼容性最好的透明背景方案。極致定製轉 Owner Draw。