傳統做法在 WM_INITDIALOG 循環呼叫 MoveWindow 漸變大小,但速度慢且因 MFC 記憶體洩漏導致畫面殘留,效果不佳。
利用 SetWindowRgn 設定視窗可見區域。對話框初始隱藏,然後以中心點為基準,循環建立逐漸放大的矩形/橢圓區域並套用,形成「由小變大」的彈出動畫。
int SetWindowRgn(HRGN hRgn, BOOL bRedraw);
// hRgn: 區域控制代碼(由 CRgn 建立)
// bRedraw: 是否立即重繪
BOOL CAboutDlg::OnInitDialog() {
CDialog::OnInitDialog();
ShowWindow(SW_HIDE); // 先隱藏
CRect dlgRect; GetClientRect(&dlgRect);
CPoint center(dlgRect.Width()/2, dlgRect.Height()/2);
CRgn rgn;
// 為避免邊框干擾,取得系統邊框寬度
int frame = GetSystemMetrics(SM_CYSIZEFRAME);
for(int i = 10; i < dlgRect.Width()/2 + frame; i += 5) {
rgn.CreateRectRgn(center.x - i, center.y - i, center.x + i, center.y + i);
SetWindowRgn((HRGN)rgn, TRUE);
ShowWindow(SW_SHOW);
CenterWindow(); // 確保置中
rgn.DeleteObject();
// 可加入 Sleep(10) 控制速度
}
return TRUE;
}
本範例假設對話框接近正方形。若長寬比懸殊,建議依比例建立橢圓區域(CreateEllipticRgn)或圓角矩形(CreateRoundRectRgn),並同步調整 X/Y 方向擴展步長,以獲得自然視覺效果。
| 方案 | 速度 | 殘影 | 實作複雜度 |
|---|---|---|---|
| MoveWindow 循環 | 慢 | 明顯 | 低 |
| SetWindowRgn 區域擴展 | 快 | 無 | 中 |
| Layered Window (WS_EX_LAYERED) + Alpha 淡入 | 最快 | 無 | 高(需 Win2K+) |
SetWindowRgn 方案在不需分層視窗支援的舊系統上也能完美運行,是實現動態彈出特效的經典技巧。