首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

透明視窗另一實作法:SetLayeredWindowAttributes 完整應用

     編輯:關於VC++

透明視窗常見做法是 SetWindowRgn 配合像素掃描建立裁切區域,但支援視窗縮放時需重複掃描計算,易導致閃爍且效能不佳。本文介紹更簡單高效的 SetLayeredWindowAttributes 方法(需 Windows 2000 以上)。

核心 API:SetLayeredWindowAttributes

BOOL SetLayeredWindowAttributes(
    HWND hwnd,        // 目標視窗控制代碼
    COLORREF crKey,   // 遮罩顏色(透明色)
    BYTE bAlpha,      // Alpha 值:0 全透明,255 不透明
    DWORD dwFlags     // 透明模式旗標
);

需在專案中動態載入 user32.dll 取得函式指標(或使用最新 SDK 直接引用)。

完整實作步驟

1. 準備背景圖片與透明色

建立背景圖片,以特定顏色(如綠色 RGB(0,255,0))標記透明區域。

2. 對話方塊屬性設定

  • 移除 Title Bar(Caption)
  • Border Style 設為 None

3. 核心程式碼實作

// 成員變數
CBitmap* m_oldBitmap;  // 原始點陣圖指標
CDC m_DC;              // 記憶體 DC

BOOL CTransWindowDlg::OnInitDialog() {
    CDialog::OnInitDialog();
    SetIcon(m_hIcon, TRUE); SetIcon(m_hIcon, FALSE);

    // 載入背景圖並調整視窗大小
    CBitmap bitmap;
    BITMAP bitInfo;
    bitmap.LoadBitmap(IDB_BACKGROUND);
    bitmap.GetBitmap(&bitInfo);
    CRect rect; GetWindowRect(&rect);
    rect.right = rect.left + bitInfo.bmWidth;
    rect.bottom = rect.top + bitInfo.bmHeight;
    MoveWindow(rect);

    // 建立相容 DC 並選入圖片
    m_DC.CreateCompatibleDC(GetDC());
    m_oldBitmap = m_DC.SelectObject(&bitmap);

    // 取得透明色(以左上角像素為準)
    COLORREF maskColor = m_DC.GetPixel(0, 0);

    // 動態載入 SetLayeredWindowAttributes
    #define LWA_COLORKEY 0x00000001
    #define WS_EX_LAYERED 0x00080000
    typedef BOOL (WINAPI *LPFN_SETLAYEREDWINDOWATTRIBUTES)(HWND, COLORREF, BYTE, DWORD);
    LPFN_SETLAYEREDWINDOWATTRIBUTES pSetLayeredWindowAttributes;
    HMODULE hUser32 = GetModuleHandle("user32.dll");
    pSetLayeredWindowAttributes = (LPFN_SETLAYEREDWINDOWATTRIBUTES)
        GetProcAddress(hUser32, "SetLayeredWindowAttributes");

    // 設定分層視窗樣式
    SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE,
        GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE) | WS_EX_LAYERED);
    // 套用透明色鍵
    pSetLayeredWindowAttributes(GetSafeHwnd(), maskColor, 255, LWA_COLORKEY);
    FreeLibrary(hUser32);

    return TRUE;
}

4. 繪製背景與消除閃爍


void CTransWindowDlg::OnPaint() {
    if (IsIconic()) { /* 預設圖示繪製 */ }
    else {
        CDC* pDC = GetDC();
        CRect rect; GetWindowRect(&rect);
        pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_DC, 0, 0, SRCCOPY);
    }
}

// 禁用背景擦除以消除啟動閃爍
BOOL CTransWindowDlg::OnEraseBkgnd(CDC* pDC) {
    return TRUE;  // 不呼叫基底類別
}

5. 資源釋放與關閉處理


void CTransWindowDlg::OnClose() {
    CBitmap* bitmap = m_DC.SelectObject(m_oldBitmap);
    m_DC.DeleteDC();
    bitmap->DeleteObject();
    CDialog::OnClose();
}

void CTransWindowDlg::OnLButtonDblClk(UINT nFlags, CPoint point) {
    PostMessage(WM_CLOSE);  // 雙擊關閉
    CDialog::OnLButtonDblClk(nFlags, point);
}

優缺點與擴充建議

  • 優點:程式碼簡潔、無需像素掃描、支援縮放不重算、效能佳。
  • 缺點:僅支援 Windows 2000+;標題列視窗支援不佳(僅客戶區透明)。
  • 擴充:可加入拖曳移動、漸隱/漸現(調整 Alpha)、半透明遮罩等效果。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved