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

效果圖:半透明漸變異形窗口
BCB6 自帶 gdiplus.h,需生成 gdiplus.lib:
// 命令行執行
implib gdiplus.lib gdiplus.dll
// 若 gdiplus.dll 不在當前目錄,需指定完整路徑
STRICTgdiplus.lib#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);
};
__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);
}
__fastcall TfrmMain::~TfrmMain(void) {
GdiplusShutdown(m_GdiplusToken); // 釋放 GDI+ 資源
}
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;
}
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); // 模擬標題欄拖動
}
}
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;
}
// 關於
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 雙緩衝 | 避免閃爍,先在內存繪製完畢再一次性更新窗口 |
GdiplusStartup 是否成功,Image::FromFile 路徑是否正確(建議絕對路徑)WS_EX_LAYERED 風格已設置,BLENDFUNCTION.AlphaFormat = AC_SRC_ALPHA,PNG 確實包含 Alpha 通道graphics.SetSmoothingMode(SmoothingModeAntiAlias)UpdateLayeredWindow 參數正確,避免頻繁創建/銷毀 DCdpiAware,或調用 SetProcessDPIAwareSourceConstantAlpha 實現淡入淡出UpdateLayeredWindow 配合 ULW_COLORKEY 或命中測試實現透明區域點擊穿透通過 GDI+ 載入 PNG、內存 DC 雙緩衝繪製、UpdateLayeredWindow Alpha 混合更新分層窗口,結合 WM_SYSCOMMAND 模擬拖動、動態載入皮膚文件,在 C++Builder 中實現了完整的半透明漸變異形窗口與動態換膚功能。核心代碼精簡高效,易於移植到 VC++、Delphi 等 Windows 原生開發環境。掌握分層窗口、Alpha 混合、GDI+ 繪製三大核心技術,是構建現代化炫酷 Windows 桌面應用的關鍵基礎。