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

Windows 透明視窗技術全解析:從 Win2000 分層視窗到 Win9x 手工 Alpha Blending

     編輯:關於C++

透明/半透明視窗是打造現代 UI 的關鍵技術。Windows 2000 引入 WS_EX_LAYERED 與 GDI+ 原生支援,而 Win9x/NT 4.0 需手工實現。本文系統整理兩種時代的技術方案,並提供核心程式碼片段。

方案一:Windows 2000+ 分層視窗 (原生 API)

半透明視窗 (恆定 Alpha)

void __fastcall TForm1::FormCreate(TObject *Sender) {
    LONG lExStyle = GetWindowLong(Handle, GWL_EXSTYLE);
    lExStyle |= WS_EX_LAYERED;
    SetWindowLong(Handle, GWL_EXSTYLE, lExStyle);
    // 200/255 ≈ 78% 不透明度,clBlue 為透明色鍵 (此處用 LWA_ALPHA 忽略色鍵)
    SetLayeredWindowAttributes(Handle, clBlue, 200, LWA_ALPHA);
}

LWA_ALPHA 使用 bAlpha (0-255) 控制整體透明度;LWA_COLORKEY 則指定單一透明色。

關鍵 API

  • SetLayeredWindowAttributes(HWND, COLORREF, BYTE, DWORD):設定透明度/色鍵。
  • UpdateLayeredWindow:高效更新分層視窗內容 (支援 Alpha Blending 位圖)。
  • AnimateWindow:視窗動畫 (摺疊、滑入、淡入淡出)。

方案二:Win9x/NT 4.0 手工 Alpha Blending (離屏合成)

核心流程:

  1. 取得桌面 DC,建立相容位圖,捕獲桌面畫面 (如螢幕截圖)。
  2. 將自有視窗內容繪製至另一位圖。
  3. 對兩張位圖執行 Alpha Blending (或其他混合模式) 產生合成圖。
  4. 將合成圖 BitBlt 回螢幕。

關鍵技術難點

參考實作碼片段 (MFC 風格,邏輯同樣適用 BCB)

int CFadeWindow::FadeAndSwitchWindow(CWnd* pWndFrom, CWnd* pWndTo) {
    CWnd* pDesktop = CWnd::GetDesktopWindow();
    CWnd* pMain = AfxGetMainWnd();
    CClientDC dc(pMain);
    CRect rc;
    pWndFrom->GetWindowRect(rc);
    pMain->ScreenToClient(rc);

    // 1. 捕獲來源視窗畫面
    CDC *pDCFrom = pWndFrom->GetDC();
    m_dib1.PasteDC(pDCFrom, 0, 0, rc.Width(), rc.Height());
    m_dib3.PasteDC(pDCFrom, 0, 0, rc.Width(), rc.Height());
    pWndFrom->ReleaseDC(pDCFrom);

    // 2. 捕獲目標視窗畫面 (WM_PRINT)
    CClientDC dcWndTo(pWndTo);
    CDC dcTo; dcTo.CreateCompatibleDC(&dcWndTo);
    CBitmap bmpTo; bmpTo.CreateCompatibleBitmap(&dcWndTo, rc.Width(), rc.Height());
    CBitmap* pOld = dcTo.SelectObject(&bmpTo);
    SetWindowPos(pWndFrom->GetSafeHwnd(), HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
    pWndTo->ShowWindow(SW_SHOW);
    pWndTo->SendMessage(WM_PRINT, (WPARAM)dcTo.GetSafeHdc(),
        PRF_CLIENT|PRF_CHILDREN|PRF_OWNED);
    m_dib2.PasteDC(&dcTo, 0, 0, rc.Width(), rc.Height());
    dcTo.SelectObject(pOld);
    SetWindowPos(pWndTo->GetSafeHwnd(), HWND_TOP,0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_SHOWWINDOW);
    SetWindowPos(pWndFrom->GetSafeHwnd(), NULL,0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_HIDEWINDOW);

    // 3. Alpha Blending 淡入淡出動畫
    int index = 5;
    for (int i=0; i

其中 m_dib1/2/3 為封裝 DIB 操作的類別,Blend 實現像素級 Alpha 混合:Dst = Src*Alpha + Dst*(255-Alpha)。

Alpha Blending 實作參考

// 像素級 Alpha Blending (24-bit DIB)
void AlphaBlend(BYTE* pSrc, BYTE* pDst, int width, int height, BYTE alpha) {
    int invAlpha = 255 - alpha;
    for (int y=0; y> 8; // B
            pDst[idx+1] = (pSrc[idx+1] * alpha + pDst[idx+1] * invAlpha) >> 8; // G
            pDst[idx+2] = (pSrc[idx+2] * alpha + pDst[idx+2] * invAlpha) >> 8; // R
        }
    }
}

技術演進與現代最佳實踐

問題解決方案
如何繪製隱藏視窗到位圖?使用 WM_PRINT 訊息 (而非 WM_PAINT),可捕獲被遮蓋區域。需先將視窗置頂 (SetWindowPos HWND_TOP)、顯示 (ShowWindow SW_SHOW)、發送 WM_PRINT、再隱藏/恢復 Z-order。
WM_PRINT 不支援的控制項 (如 Static)手工在記憶體位圖上繪製該控制項外觀。
如何取得視窗下方其他應用程式畫面?極其困難。真正的桌面合成需 DWM (Vista+) 或鏡像驅動。本法僅適用於 Splash 視窗、工具提示等靜態/半靜態透明視窗。
時代技術適用場景
Win9x/NT4手工離屏合成 + WM_PRINTSplash 畫面、工具提示、簡單透明視窗
Win2000/XPWS_EX_LAYERED + SetLayeredWindowAttributes恆定半透明視窗、簡單淡入淡出
Vista/7/8/10/11DWM (Desktop Window Manager) + DwmExtendFrameIntoClientArea玻璃效果、全視窗 Aero Glass、高效硬體加速合成
現代跨平台DirectComposition / WinUI 3 / Skia / Flutter高性能 GPU 加速 UI、複雜動畫、向量圖形

BCB 開發者建議

  • 目標系統 ≥ Win2000:優先使用 WS_EX_LAYERED + SetLayeredWindowAttributes / UpdateLayeredWindow。
  • 需支援 Win9x:僅針對 Splash、登入框等非互動視窗使用手工合成,主視窗避免使用。
  • 現代專案:考慮遷移至 FMX (FireMonkey) 或支援 DWM 的 VCL 風格 (Windows 10 VCL Styles)。
  • Alpha Blending 核心邏輯可封裝為通用工具單元,服務於自繪控制項、圖片淡入淡出、視窗切換動畫等場景。

理解透明視窗技術演進脈絡,能幫助開發者根據目標平台選擇最適合的方案,在相容性與視覺效果間取得最佳平衡。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved