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

C++ 實現 Windows Vista Aero 毛玻璃效果:DWM API 完整指南

     編輯:關於C++

Windows Vista 引入的桌面窗口管理器(DWM)帶來了標誌性的 Aero 毛玻璃視覺效果。本文演示如何在基於 WTL 的 C++ 原生程序中集成毛玻璃界面,涵蓋框架窗口與對話框兩種場景,並處理繪製文本、圖標及動態狀態變更。

環境配置與頭文件設置

需定義 Vista 版本宏(0x0600)並包含 DWM API:

#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#define _WIN32_IE 0x0700

#define _WTL_NO_WTYPES
#include <atlbase.h>
#include <atltypes.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>
#include <atlframe.h>
#include <atlmisc.h>
#include <atlcrack.h>
#include <atltheme.h> // XP/Vista 主題支持
#include <dwmapi.h>   // DWM API

注意:Windows SDK 中 atltheme.h 的 GetThemeTextMetrics 轉換代碼與 Platform SDK 不兼容,需刪除該轉換行以編譯通過。

核心 API:DwmExtendFrameIntoClientArea

將非客戶區的毛玻璃效果擴展到客戶區:

MARGINS mar = {0};
mar.cyBottomHeight = 100; // 底部擴展 100 像素
DwmExtendFrameIntoClientArea(m_hWnd, &mar);

MARGINS 結構控制四邊擴展距離(cxLeftWidth、cxRightWidth、cyTopHeight、cyBottomHeight)。

關鍵繪製技巧:黑色背景實現透明

毛玻璃區域像素 Alpha 必須為 0 才能顯示效果。最簡單方法是在 OnEraseBkgnd 中用黑刷填充:

BOOL OnEraseBkgnd(HDC hdc) {
    CDCHandle dc = hdc;
    CRect rcClient;
    GetClientRect(rcClient);
    dc.FillSolidRect(rcClient, RGB(0,0,0)); // RGBA 全 0
    return TRUE;
}

在毛玻璃區域繪製發光文本

GDI 函數不支持 Alpha 通道,必須使用主題 API DrawThemeTextEx 配合雙緩衝:

  1. 創建內存 DC 與 32 位 DIB(biHeight 設為負值,頂-down 格式)。
  2. 選入字體,設置 DTTOPTS 啟用 DTT_COMPOSITED(合成繪製)與 DTT_GLOWSIZE(發光)。
  3. 調用 DrawThemeTextEx 繪製到內存位圖。
  4. BitBlt (SRCCOPY) 複製到屏幕 DC。
if (IsCompositionEnabled()) {
    CDC dcMem; CBitmap bmp; BITMAPINFO dib = {0};
    dcMem.CreateCompatibleDC(dc);
    dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    dib.bmiHeader.biWidth = rcText.Width();
    dib.bmiHeader.biHeight = -rcText.Height(); // 負值:top-down
    dib.bmiHeader.biPlanes = 1;
    dib.bmiHeader.biBitCount = 32;
    dib.bmiHeader.biCompression = BI_RGB;
    bmp.CreateDIBSection(dc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);

    dcMem.SelectBitmap(bmp);
    dcMem.SelectFont(m_font);

    DTTOPTS dto = { sizeof(DTTOPTS) };
    dto.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
    dto.iGlowSize = 10; // 發光半徑
    CRect rcText2 = rcText; rcText2 -= rcText2.TopLeft(); // 歸零座標
    DrawThemeTextEx(m_hTheme, dcMem, 0, 0, CT2CW(szTime), -1,
                    DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_NOPREFIX,
                    rcText2, &dto);

    BitBlt(dc, rcText.left, rcText.top, rcText.Width(), rcText.Height(),
           dcMem, 0, 0, SRCCOPY);
}

動態響應 Composition 狀態變更

系統廣播 WM_DWMCOMPOSITIONCHANGED 通知,需重新應用邊距:

LRESULT OnCompositionChanged(...) {
    if (IsCompositionEnabled()) {
        MARGINS mar = {0};
        mar.cyBottomHeight = 100;
        DwmExtendFrameIntoClientArea(m_hWnd, &mar);
    }
    return 0;
}

對話框程序中的毛玻璃集成

流程類似,但需注意:

  • 在 OnInitDialog 中調用 OpenThemeData()(對話框無 WM_CREATE)。
  • 靜態文本控件設置 SS_OWNERDRAW 風格,在 OnDrawItem 中繪製。
  • 背景繪製放在 OnPaint 而非 OnEraseBkgnd(對話框默認處理背景)。
  • 調用 EnableThemeDialogTexture(ETDT_ENABLE) 使對話框背景跟隨主題。

進階:GDI+ 繪製透明圖標

毛玻璃區域繪製圖片需用 GDI+ Image 類保留 Alpha 通道:

// OnDrawItem 中
Graphics g(dcMem);
Image img(L"mylogo.png");
g.DrawImage(&img, x, y); // 自動處理透明度

全窗口毛玻璃與子控件問題

設置 MARGINS mar = {-1}; 可使整個窗口毛玻璃化,但子控件(按鈕等)會顯示異常(不透明矩形框、文字顏色錯誤)。解決方案:子控件區域繪製不透明背景,參考「Windows Mobility Center」風格。

總結

  • 毛玻璃效果依賴 DWM Composition,需運行時檢測 DwmIsCompositionEnabled。
  • 黑色填充(RGB 0,0,0)是啟用客戶區透明的關鍵。
  • 文本繪製必須用 DrawThemeTextEx + 32位 DIB 雙緩衝。
  • 動態響應 WM_DWMCOMPOSITIONCHANGED 保證狀態切換正確。
  • 全窗口毛玻璃需處理子控件繪製衝突。

本文代碼基於 WTL 7.5 + VC++ 2003/2005,可直接移植到 MFC 或純 Win32 專案。

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