許多後台服務程式需以對話方塊形式啟動並最小化至系統托盤,但 MFC 對話方塊在 OnInitDialog 階段尚未提供 ShowWindow(SW_HIDE) 時機,直接呼叫無效。本文對比四種隱藏方案的優劣、實作細節與副作用,助你選擇最適合專案的作法。
BOOL CMyDlg::OnInitDialog() {
CDialog::OnInitDialog();
SetTimer(1, 1, NULL); // 1ms 後觸發
return TRUE;
}
void CMyDlg::OnTimer(UINT_PTR nIDEvent) {
if (nIDEvent == 1) {
KillTimer(1);
ShowWindow(SW_HIDE);
}
}
SetWindowPlacement 設定初始顯示狀態(無閃爍,但位置/啟動狀態需修補)
BOOL CMyDlg::OnInitDialog() {
CDialog::OnInitDialog();
WINDOWPLACEMENT wp = { sizeof(wp) };
wp.flags = WPF_RESTORETOMAXIMIZED;
wp.showCmd = SW_HIDE;
SetWindowPlacement(&wp);
GetWindowRect(&m_rectInit); // 記住正常位置
return TRUE;
}
// 顯示時
WINDOWPLACEMENT wp = { sizeof(wp) };
wp.showCmd = SW_SHOW;
SetWindowPlacement(&wp);
SetWindowPos(&wndTop, m_rectInit.left, m_rectInit.top,
m_rectInit.Width(), m_rectInit.Height(), SWP_SHOWWINDOW);
CenterWindow();
WM_NCPAINT 首次非用戶區繪製時隱藏(推薦,效果最佳)
void CMyDlg::OnNcPaint() {
static int first = 2; // 需處理兩次:系統先送一次,Hide 後因 WS_VISIBLE 移除又送一次
if (first-- > 0) {
ShowWindow(SW_HIDE);
} else {
CDialog::OnNcPaint();
}
}
// 顯示時直接 ShowWindow(SW_SHOW)
WM_NCPAINT 觸發機制(兩次),static int 計數器不可省略。CMainFrame 永久隱藏。CMainFrame::OnCreate 中 m_dlg.Create(IDD_MYDLG, this); m_dlg.ShowWindow(SW_HIDE);。m_dlg.ShowWindow(SW_SHOW);。在 OnInitDialog 加入:
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); // 隱藏任務列按鈕
// 顯示前恢復:
ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);
| 場景 | 推薦方案 |
|---|---|
| 快速原型、工具小程式 | 方案三 (WM_NCPAINT) |
| 需完美啟動體驗、商業級產品 | 方案三 + 任務列圖示控制 |
| 已採用 SDI/MDI 架構 | 方案四 |
| 臨時測試、不介意閃爍 | 方案一 |
方案三綜合體驗最佳,程式碼量極小,強烈建議作為預設選擇。