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

C++Builder 實現 GDI+ 半透明漸變異形窗口:分層窗口技術與動態換膚完整指南

     編輯:關於C語言

前言

利用 GDI+ 強大的圖形渲染能力配合 Windows 分層窗口(Layered Window)特性,可輕鬆實現半透明、漸變、異形、動態換膚的炫酷界面。本文基於 C++Builder 6 環境,詳細講解 GDI+ 初始化、PNG 圖片載入、Alpha 混合繪製、分層窗口更新、窗口拖動、右鍵菜單、動態換膚等完整實現流程。

效果圖:半透明漸變異形窗口

一、C++Builder 環境配置 GDI+

1.1 生成導入庫

BCB6 自帶 gdiplus.h,需生成 gdiplus.lib:

// 命令行執行
implib gdiplus.lib gdiplus.dll
// 若 gdiplus.dll 不在當前目錄,需指定完整路徑

1.2 項目設置

  1. 條件編譯定義:Project → Options → Directories/Conditionals → Conditionals → 添加 STRICT
  2. 添加導入庫:Project → Add To Project → 選擇生成的 gdiplus.lib
  3. 頭文件包含順序(關鍵):
#include <math.hpp>
#include <algorithm> // for std::min/max
using std::min;
using std::max;
#include <gdiplus.h>
using namespace Gdiplus;

二、核心類成員設計


class TfrmMain : public TForm {
private: // 用戶聲明
    ULONG_PTR m_GdiplusToken;           // GDI+ 啟動令牌
    GdiplusStartupInput m_GdiplusStartupInput;
    int __fastcall SetTransparent(LPWSTR lpSkinFile, int nTran); // 核心設置函數
    BLENDFUNCTION m_Blend;              // Alpha 混合參數
    HDC m_hdcMemory;                    // 內存 DC
    Gdiplus::Image* m_Image;            // GDI+ 圖片對象

public: // 用戶聲明
    __fastcall TfrmMain(TComponent* Owner);
    __fastcall ~TfrmMain(void);
};

三、關鍵實現代碼詳解

3.1 構造函數:初始化 GDI+ 與窗口屬性


__fastcall TfrmMain::TfrmMain(TComponent* Owner)
    : TForm(Owner) {
    BorderStyle = bsNone; // 無邊框,實現異形窗口基礎
    
    // 初始化 GDI+
    GdiplusStartup(&m_GdiplusToken, &m_GdiplusStartupInput, NULL);
    
    // 配置 Alpha 混合參數
    m_Blend.BlendOp = AC_SRC_OVER;      // 僅支持的混合操作
    m_Blend.BlendFlags = 0;
    m_Blend.AlphaFormat = AC_SRC_ALPHA; // 來源圖片含 Alpha 通道
    m_Blend.SourceConstantAlpha = 255;  // 全局透明度(0-255)
    
    // 默認載入皮膚
    if (FileExists(ExtractFilePath(ParamStr(0)) + "\\test.png")) {
        SetTransparent(WideString("test.png"), 100);
    }
    
    // 置頂顯示
    SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

3.2 析構函數:關閉 GDI+


__fastcall TfrmMain::~TfrmMain(void) {
    GdiplusShutdown(m_GdiplusToken); // 釋放 GDI+ 資源
}

3.3 核心函數 SetTransparent:載入 PNG、繪製、更新分層窗口


int __fastcall TfrmMain::SetTransparent(LPWSTR lpSkinFile, int nTran) {
    // 1. 載入 PNG 圖片(支持 Alpha 通道)
    m_Image = Gdiplus::Image::FromFile(lpSkinFile);
    if (!m_Image) return 0;
    
    // 2. 調整窗口大小匹配圖片
    Width = m_Image->GetWidth();
    Height = m_Image->GetHeight();
    
    // 3. 創建兼容內存 DC 與位圖
    HDC hdcTemp = GetDC(0);
    m_hdcMemory = CreateCompatibleDC(hdcTemp);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdcTemp, 
        m_Image->GetWidth(), m_Image->GetHeight());
    SelectObject(m_hdcMemory, hBitmap);
    
    // 4. 設置透明度(0-100 映射 0-255)
    if (nTran < 0 || nTran > 100) nTran = 100;
    m_Blend.SourceConstantAlpha = int(nTran * 2.55);
    
    // 5. 使用 GDI+ Graphics 在內存 DC 上繪製
    HDC hdcScreen = GetDC(0);
    RECT rct; GetWindowRect(Handle, &rct);
    POINT ptWinPos = {rct.left, rct.top};
    
    Gdiplus::Graphics graphics(m_hdcMemory);
    graphics.DrawImage(m_Image, 0, 0, m_Image->GetWidth(), m_Image->GetHeight());
    
    // 6. 設置窗口為分層窗口(WS_EX_LAYERED)
    DWORD dwExStyle = GetWindowLong(Handle, GWL_EXSTYLE);
    if ((dwExStyle & WS_EX_LAYERED) != WS_EX_LAYERED) {
        SetWindowLong(Handle, GWL_EXSTYLE, dwExStyle | WS_EX_LAYERED);
    }
    
    // 7. 核心:更新分層窗口實現 Alpha 混合
    SIZE sizeWnd = {m_Image->GetWidth(), m_Image->GetHeight()};
    POINT ptSrc = {0, 0};
    BOOL bRet = UpdateLayeredWindow(Handle, hdcScreen, &ptWinPos, &sizeWnd,
        m_hdcMemory, &ptSrc, 0, &m_Blend, ULW_ALPHA);
    
    // 8. 清理資源
    graphics.ReleaseHDC(m_hdcMemory);
    ReleaseDC(0, hdcScreen);
    ReleaseDC(0, hdcTemp);
    DeleteObject(hBitmap);
    DeleteDC(m_hdcMemory);
    m_hdcMemory = NULL;
    m_Image = NULL;
    
    return bRet;
}

3.4 窗口拖動實現(無標題欄時必須)


void __fastcall TfrmMain::FormMouseDown(TObject* Sender,
    TMouseButton Button, TShiftState Shift, int X, int Y) {
    if (Button == mbLeft) {
        ReleaseCapture(); // 釋放鼠標捕獲
        Perform(WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0); // 模擬標題欄拖動
    }
}

3.5 動態換膚菜單實現


void __fastcall TfrmMain::miChangeSkinClick(TObject* Sender) {
    TOpenDialog* dlgOpen = new TOpenDialog(this);
    dlgOpen->Filter = "PNG file (*.png)|*.png";
    if (dlgOpen->Execute()) {
        SetTransparent(WideString(dlgOpen->FileName), 100);
        Invalidate(); // 觸發重繪
    }
    delete dlgOpen;
}

3.6 其他菜單功能


// 關於
void __fastcall TfrmMain::miShowAboutClick(TObject* Sender) {
    MessageBox(Handle, 
        "在 BCB 中用 GDI+ 實現半透明漸變的特效窗口\n"
        "-------------------------\n"
        "by ccrun(老妖)\n"
        "Welcome to www.ccrun.com",
        "GDI+ Window", MB_OK | MB_ICONINFORMATION);
}

// 退出
void __fastcall TfrmMain::miCloseAppClick(TObject* Sender) { Close(); }

// 訪問主頁
void __fastcall TfrmMain::miGoToCcrunClick(TObject* Sender) {
    ShellExecute(Handle, "Open", "https://www.ccrun.com", NULL, NULL, SW_SHOW);
}

// 置頂切換
void __fastcall TfrmMain::miStayOnTopClick(TObject* Sender) {
    TMenuItem* mi = (TMenuItem*)Sender;
    mi->Checked = !mi->Checked;
    SetWindowPos(Handle, mi->Checked ? HWND_TOPMOST : HWND_NOTOPMOST,
        0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

四、關鍵技術原理解析

技術點原理說明
分層窗口 (WS_EX_LAYERED)Windows 2000+ 支持,允許逐像素 Alpha 混合,實現半透明、異形窗口
UpdateLayeredWindow核心 API,將內存 DC 內容按 BLENDFUNCTION 參數 Alpha 混合到桌面
BLENDFUNCTION控制混合模式:AC_SRC_OVER + AC_SRC_ALPHA 表示使用源圖片 Alpha 通道
GDI+ Image::FromFile原生支持 PNG、JPG、GIF、BMP、TIFF 等格式,自動解析 Alpha 通道
Graphics::DrawImage高質量縮放、旋轉、Alpha 混合繪製,硬件加速
內存 DC 雙緩衝避免閃爍,先在內存繪製完畢再一次性更新窗口

五、常見問題與調試技巧

  1. 圖片不顯示/全黑:檢查 GdiplusStartup 是否成功,Image::FromFile 路徑是否正確(建議絕對路徑)
  2. 透明度不生效:確認 WS_EX_LAYERED 風格已設置,BLENDFUNCTION.AlphaFormat = AC_SRC_ALPHA,PNG 確實包含 Alpha 通道
  3. 邊緣鋸齒:GDI+ 默認抗鋸齒,若仍有問題可設置 graphics.SetSmoothingMode(SmoothingModeAntiAlias)
  4. 動態換膚閃爍:確保 UpdateLayeredWindow 參數正確,避免頻繁創建/銷毀 DC
  5. 高 DPI 模糊:清單文件中聲明 dpiAware,或調用 SetProcessDPIAware

六、擴展方向

  • 動畫效果:定時器漸變 SourceConstantAlpha 實現淡入淡出
  • 非矩形點擊穿透:UpdateLayeredWindow 配合 ULW_COLORKEY 或命中測試實現透明區域點擊穿透
  • 多層疊加:多個分層窗口疊加實現複雜 UI
  • Direct2D 遷移:現代替代方案,性能更優,API 相似

七、總結

通過 GDI+ 載入 PNG、內存 DC 雙緩衝繪製、UpdateLayeredWindow Alpha 混合更新分層窗口,結合 WM_SYSCOMMAND 模擬拖動、動態載入皮膚文件,在 C++Builder 中實現了完整的半透明漸變異形窗口與動態換膚功能。核心代碼精簡高效,易於移植到 VC++、Delphi 等 Windows 原生開發環境。掌握分層窗口、Alpha 混合、GDI+ 繪製三大核心技術,是構建現代化炫酷 Windows 桌面應用的關鍵基礎。

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