將「介面佈局邏輯」與「視覺表現資源」完全分離:
<?xml version="1.0" encoding="UTF-8"?>
<Skin>
<ImageFile>LoginSkin.png</ImageFile> <!-- 整張圖集 -->
<Controls>
<Control name="BtnMin" type="Button">
<Size><Width>18</Width><Height>18</Height></Size>
<FormPos><Left>302</Left><Top>2</Top></FormPos>
<States>
<Normal><Left>0</Left><Top>268</Top></Normal>
<Hover><Left>0</Left><Top>291</Top></Hover>
<Down><Left>0</Left><Top>314</Top></Down>
<Disabled/>
<Focus/>
</States>
</Control>
<Control name="BtnClose" type="Button"> ... </Control>
<Control name="EdtUser" type="Edit"> ... </Control>
<Control name="EdtPass" type="Edit" password="true"> ... </Control>
<Control name="BtnLogin" type="Button"> ... </Control>
</Controls>
<Window>
<Size><Width>350</Width><Height>200</Height></Size>
<Region><!-- 非矩形視窗區域,可為圓角矩形、多邊形、位圖透明色 --></Region>
</Window>
</Skin>
class TSkinManager {
Graphics::TBitmap* FAtlas; // 載入的圖集
TStringList* FControlDefs; // 解析後的控件定義
public:
bool LoadSkin(const AnsiString& XmlFile);
void ApplySkin(TWinControl* Parent); // 遞迴套用至表單所有子控件
Graphics::TBitmap* GetStateBitmap(const AnsiString& CtrlName, const AnsiString& State);
TRect GetControlRect(const AnsiString& CtrlName);
// 九宮格繪製支援
void DrawNinePatch(TCanvas* Canvas, TRect DstRect, Graphics::TBitmap* SrcBmp, TRect SrcRect, TRect Margins);
};
class TSkinForm : public TForm {
TSkinManager* SkinMgr;
protected:
virtual void __fastcall CreateParams(TCreateParams& Params) {
TForm::CreateParams(Params);
Params.Style &= ~WS_CAPTION; // 移除標題列
Params.ExStyle |= WS_EX_LAYERED; // 分層視窗支援透明/非矩形
}
virtual void __fastcall Paint() {
// 繪製背景、九宮格邊框、標題列區域等
}
virtual void __fastcall WndProc(TMessage& Msg) {
// 處理 WM_NCHITTEST 實現拖曳、縮放、系統選單
}
public:
__fastcall TSkinForm(TComponent* Owner) : TForm(Owner) {
SkinMgr = new TSkinManager();
}
bool LoadSkin(const AnsiString& XmlFile) { return SkinMgr->LoadSkin(XmlFile); }
};
WS_EX_LAYERED + SetLayeredWindowAttributes (色鍵透明) 或 UpdateLayeredWindow (Alpha 混合,需 Win2000+)。CopyRect 從圖集切出,避免重複解碼 PNG。LoadSkin(newXml) 即時切換,無需重啟。Skins\ 子資料夾。