利用位圖透明色建立任意形狀對話框是打造個性化 UI 常用技術。本文介紹封裝良好的 CBitmapDialog 類別:載入位圖、指定透明色、自動計算區域 (Region)、支援任意拖曳、靜態控件透明化,幾行代碼即可擁有不規則視窗。
LoadBitmap(nID):載入資源位圖 (IDB_BITMAP1)。SetTransparent(TRUE):啟用透明色模式。SetTransColor(RGB(0,0,0)):指定透明色 (位圖中此色像素不顯示、不佔用點擊區域)。SetStaticTransparent(TRUE):子靜態控件背景透明化。SetClickAnywhereMove(TRUE):滑鼠在客戶區任意處按下可拖曳視窗 (無標題列時必備)。MakeWindowRgn:掃描位圖像素,以非透明色像素構建 HRGN,呼叫 SetWindowRgn 套用。屬性 → Border: None, Title bar: False。
資源視圖 → 右鍵 Add Resource → Bitmap,編輯位圖:
- 背景繪製所需形狀
- **透明區域統一填滿純色** (如純黑 RGB(0,0,0) 或純洋紅 RGB(255,0,255))
- 位圖尺寸即視窗初始尺寸
// 原始
class CBitmapDlgDlg : public CDialog
// 修改為
class CBitmapDlgDlg : public CBitmapDialog
同步修改訊息映射:BEGIN_MESSAGE_MAP(CBitmapDlgDlg, CBitmapDialog)。
BOOL CBitmapDlgDlg::OnInitDialog()
{
CBitmapDialog::OnInitDialog();
LoadBitmap(IDB_BITMAP1); // 載入位圖並建立區域
SetTransparent(TRUE); // 啟用透明
SetTransColor(RGB(0,0,0)); // 透明色 = 位圖背景色
SetStaticTransparent(TRUE); // 子靜態文字透明
SetClickAnywhereMove(TRUE); // 任意處拖曳
return TRUE;
}
HRGN CBitmapDialog::MakeWindowRgn()
{
// 1. 取得位圖資訊
BITMAP bm; m_bitmap.GetBitmap(&bm);
// 2. 鎖定像素緩衝區
BYTE* pBits = (BYTE*)bm.bmBits; // 需 DIBSECTION
// 3. 掃描每行,合併連續非透明像素為矩形,CombineRgn(RGN_OR)
// 4. 回傳最終 HRGN
}
為效能考量,掃描時以 **水平掃描線** 為單位合併矩形,而非逐像素 CombineRgn,大幅減少區域複雜度。
OnMouseMove/OnLButtonDown 切換 LoadBitmap 並 Invalidate。CBitmapButton 或自繪實現異形。LR_CREATEDIBSECTION 載入才能直接存取像素。LoadBitmap + SetWindowRgn + SetWindowPos。完整 CBitmapDialog.h/cpp 及範例專案可下載,VC6.0/VS2005+ 皆可編譯。