判斷一款軟體是否優秀,除了功能完善、效能穩定、操作直觀外,介面美觀度愈發受到重視。使用者不再滿足於傳統矩形視窗,不規則造型、可自由換膚的介面已成主流趨勢。本文將介紹一種基於 C++Builder 的完整換膚實作方案,涵蓋介面元素定義、美術資源規範、XML 佈局描述、高效解析策略、不規則視窗區域建立,以及以 TImage 模擬按鈕的繪圖技巧。
專案伊始,程式設計師依據功能需求定義介面元素(控制項),控制項名稱 作為核心識別碼,雙方以此對接。美術人員依據元素清單繪製素材圖集,並輸出一份 XML 描述檔,記錄每個元素在圖集中的座標、尺寸、於視窗中的位置,以及普通、滑鼠懸停、按下、失效、聚焦等狀態對應的圖片區塊。
以下節錄登入對話框的最小化、關閉按鈕定義:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<control>
<ctrlName>BMin</ctrlName>
<size><height>18</height><width>18</width></size>
<formPos><left>302</left><top>2</top></formPos>
<action>
<normal><left>0</left><top>268</top></normal>
<mouseUp><left>0</left><top>291</top></mouseUp>
<mouseDown><left>0</left><top>314</top></mouseDown>
<disable/><focus/>
</action>
</control>
<control>
<ctrlName>BClose</ctrlName>
<size><height>18</height><width>18</width></size>
<formPos><left>327</left><top>2</top></formPos>
<action>
<normal><left>28</left><top>268</top></normal>
<mouseUp><left>28</left><top>291</top></mouseUp>
<mouseDown><left>28</left><top>314</top></mouseDown>
</action>
</control>
...
</root>

圖一:介面元素定義

圖二:美術繪製的登入視窗元素圖集
為避免執行期頻繁讀取、解析 XML 造成介面載入停頓,採用啟動時一次性解析,將所有控制項資訊填入結構體陣列:
typedef struct Ctrls {
String ctrlName; // 控制項名稱
TPoint formPos; // 視窗內位置
int width, height; // 尺寸
bool hasNormal, hasMouseUp, hasMouseDown, hasDisable, hasFocus; // 狀態圖是否存在
TPoint normal, mouseUp, mouseDown, disable, focus; // 圖集內座標
} m_ctrls;
利用背景圖透明色(取左上角像素)掃描每一掃描線的首尾非透明像素,構建多邊形區域並套用 SetWindowRgn:
Graphics::TBitmap *bitmap0 = new Graphics::TBitmap;
bitmap0->LoadFromFile(".\\login\\Login_Bg.bmp");
LoginDlgBG->Picture->Bitmap = bitmap0;
TColor baseColor = LoginDlgBG->Canvas->Pixels[0][0];
// 分配座標陣列、建立矩形區域、逐行掃描首尾非透明點
// 以 CreatePolygonRgn + CombineRgn(RGN_AND) 取交集
// 最後 SetWindowRgn(Handle, WndRgn, true);

圖三:完成後的登入對話框效果
TSpeedButton 繼承 TGraphicControl 無視窗句柄,難以配合 SetWindowRgn 做不規則造型。靈活做法是使用 TImage:
Canvas->CopyRect 從總圖集剪裁對應狀態圖片OnMouseMove、OnMouseDown、OnMouseUp 事件切換狀態圖void __fastcall TForm1::createButtonCtrl(TImage *image, String ctrlName, String actionName) {
// 1. 依 ctrlName 查找 m_ctrls 陣列
// 2. 設定 image 尺寸與位置
// 3. 依 actionName 取得對應圖集座標
// 4. CopyRect 從 LoginDlgBG 扣圖至 image
}
換膚核心在於「資料驅動介面」:美術只需替換圖集與 XML,程式碼完全不用動。若需支援多主題,可建立多組「圖集+XML」資料包,啟動時依使用者設定載入對應資源即可。
本方案以 XML 解耦版面與邏輯,結構體快取提升啟動速度,TImage 扣圖技巧解決不規則按鈕難題,完整展示了 C++Builder 實現專業級換膚的關鍵技術點。原始碼已整理於附件,歡迎參考改良。