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

VC++ 實作 Windows XP 風格關機漸變淡出特效

     編輯:關於VC++

Windows XP 關機時螢幕會呈現平滑的灰階漸變淡出效果,而非簡單的灰色刷填。本文分析並實作此核心演算法:擷取全螢幕位圖 → 轉灰階 → 以 Alpha 混合逐漸疊加白色,達到動態漸變視覺效果。

核心演算法:FadeBitmap

HBITMAP CMyFade::FadeBitmap(HBITMAP hBmp, double dfTrans) // dfTrans: 0~100 透明度百分比 { if (!hBmp) return NULL; HDC hBufDC = CreateCompatibleDC(NULL); HGDIOBJ hOldBuf = SelectObject(hBufDC, hBmp); HDC hDirDC = CreateCompatibleDC(NULL); BITMAP bm; GetObject(hBmp, sizeof(bm), &bm); // 建立 32-bit DIB Section 以直接操作像素 (ARGB) BITMAPINFO bmi = {0}; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = bm.bmWidth; bmi.bmiHeader.biHeight = bm.bmHeight; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; UINT* pPixels = NULL; HBITMAP hDirBmp = CreateDIBSection(hDirDC, &bmi, DIB_RGB_COLORS, (void**)&pPixels, NULL, 0); if (!hDirBmp) { DeleteDC(hDirDC); SelectObject(hBufDC, hOldBuf); DeleteDC(hBufDC); return NULL; } HGDIOBJ hOldDir = SelectObject(hDirDC, hDirBmp); // 將原螢幕位圖複製至 DIB Section BitBlt(hDirDC, 0, 0, bm.bmWidth, bm.bmHeight, hBufDC, 0, 0, SRCCOPY); int nAlpha = (int)(255.0 * dfTrans / 100.0); // 0~255 int nSize = bm.bmWidth * bm.bmHeight; for (int i = 0; i < nSize; i++) { // DIB Section 記憶體排列為 BGRA (小端序) int iSrcB = pPixels[i] & 0xFF; int iSrcG = (pPixels[i] >> 8) & 0xFF; int iSrcR = (pPixels[i] >> 16) & 0xFF; // 灰階轉換 (ITU-R BT.601 權重) int iGrey = (iSrcR * 54 + iSrcG * 182 + iSrcB * 19) >> 8; // 近似 0.2126R + 0.7152G + 0.0722B // Alpha 混合:灰階色 (R=G=B=iGrey) 與原色混合 // 目標 = Src * (1 - Alpha) + Grey * Alpha int r = (iSrcR * (255 - nAlpha) + iGrey * nAlpha) >> 8; int g = (iSrcG * (255 - nAlpha) + iGrey * nAlpha) >> 8; int b = (iSrcB * (255 - nAlpha) + iGrey * nAlpha) >> 8; pPixels[i] = (r << 16) | (g << 8) | b; // 寫回 BGR (無 Alpha 通道) } SelectObject(hDirDC, hOldDir); DeleteDC(hDirDC); SelectObject(hBufDC, hOldBuf); DeleteDC(hBufDC); return hDirBmp; // 呼叫端需負責 DeleteObject }

關鍵技術點解析

  1. DIB Section (CreateDIBSection):提供直接存取像素緩衝區的指標 (pPixels),避免 GetPixel/SetPixel 極慢的效能。
  2. 32-bit 像素格式 (BGRA):記憶體中每像素 4 Bytes,排列為 Blue、Green、Red、Alpha (保留)。位運算提取各通道值。
  3. 灰階權重:採用標準亮度公式 Y = 0.2126R + 0.7152G + 0.0722B,程式中以整數運算近似 (R*54 + G*182 + B*19) >> 8。
  4. Alpha 混合:線性插值 Dst = Src*(1-a) + Grey*a,a = dfTrans/100。dfTrans 從 0 遞增至 100 即可產生動畫幀。
  5. 位移運算優化:除以 256 使用 >> 8,乘以權重後右移 8 位相當於除以 256,全整數運算無浮點開銷。

完整關機特效流程

  1. 建立全螢幕無邊框視窗 (WS_EX_TOPMOST | WS_EX_LAYERED)。
  2. 呼叫 BitBlt 擷取桌面至記憶體位圖。
  3. 迴圈 dfTrans = 0 → 100 (步進 5,Sleep 30ms):
    • 呼叫 FadeBitmap(hDeskBmp, dfTrans) 取得漸變位圖。
    • 使用 UpdateLayeredWindow 或 BitBlt 將結果繪製到全螢幕視窗。
  4. 完成後呼叫 ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0) 真正關機。

已知限制與改進方向

  • 滑鼠游標未捕捉:BitBlt 不包含游標,需額外 DrawIconEx 繪製游標。
  • 多螢幕支援:需枚舉 EnumDisplayMonitors 擷取各螢幕並拼接。
  • 權限問題:ExitWindowsEx 需 SE_SHUTDOWN_NAME 特權,服務或管理員權限下執行較無問題。
  • 現代替代方案:Windows Vista+ 可用 DwmEnableBlurBehindWindow、DirectComposition 或 Windows Animation Manager 實作更流暢的 GPU 加速特效。

完整範例碼包含 CMyFade 類別與對話框測試專案,可從 VC 知識庫下載。歡迎交流:xuwenq88@126.com

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