系統選單 (標題列圖標右鍵或 Alt+Space) 是每個視窗的標準配置。本文教你在 MFC 對話框中 **添加自訂項目 (關於、退出)、修改現有項目文字 (關閉→隱藏)、刪除項目、處理 WM_SYSCOMMAND 路由、結合系統托盤實現「關閉按鈕最小化到托盤」** 完整實戰流程。
OnInitDialog)// resource.h 定義唯一 ID (必須 < 0xF000 避開系統保留範圍)
#define IDM_ABOUT 16
#define IDM_EXIT 17
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 修正 Win95 Bug 的斷言 (標準模板代碼)
ASSERT((IDM_ABOUT & 0xFFF0) == IDM_ABOUT);
ASSERT(IDM_ABOUT < 0xF000);
ASSERT((IDM_EXIT & 0xFFF0) == IDM_EXIT);
ASSERT(IDM_EXIT < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE); // FALSE=取得指標, TRUE=重置為預設
if (pSysMenu)
{
pSysMenu->AppendMenu(MF_STRING, IDM_EXIT, _T("退出(&X)"));
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUT, _T("關於(&A)..."));
}
// ... 其他初始化 (如托盤圖標建立) ...
return TRUE;
}
WM_SYSCOMMAND 路由自訂命令void CMyDialog::OnSysCommand(UINT nID, LPARAM lParam)
{
switch (nID & 0xFFF0) // 同樣需屏蔽低 4 位修正 Win95 Bug
{
case IDM_ABOUT:
{
CAboutDlg dlg; dlg.DoModal();
}
break;
case IDM_EXIT:
::PostQuitMessage(0); // 真正退出程式
break;
case SC_CLOSE: // 系統預設「關閉」命令
OnClose(); // 我們覆寫 OnClose 實現「隱藏到托盤」而非退出
break;
default:
CDialog::OnSysCommand(nID, lParam); // 其他交給預設處理 (最大化、最小化等)
}
}
// 修改「關閉」文字為「隱藏」
pSysMenu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND, IDM_HIDE, _T("隱藏(&H)"));
// 或按位置修改 (索引 0 為第一項)
pSysMenu->ModifyMenu(0, MF_BYPOSITION, IDM_HIDE, _T("隱藏(&H)"));
// 刪除「關閉」項
pSysMenu->RemoveMenu(SC_CLOSE, MF_BYCOMMAND);
pSysMenu->RemoveMenu(0, MF_BYPOSITION);
| 命令 | 常數 | 行為 |
|---|---|---|
| 關閉 | SC_CLOSE | 關閉視窗 (預設退出程式) |
| 最大化 | SC_MAXIMIZE / SC_ZOOM | 最大化視窗 |
| 最小化 | SC_MINIMIZE / SC_ICON | 最小化視窗 |
| 移動 | SC_MOVE | 啟動視窗移動模式 |
| 還原 | SC_RESTORE | 還原最大化/最小化視窗 |
| 大小調整 | SC_SIZE | 啟動視窗縮放模式 |
WS_EX_TOOLWINDOW + 托盤最小化WS_EX_TOOLWINDOW → 標題列無圖標,但右鍵標題列/任務列仍可彈出系統選單。CTrayIcon 等),OnClose 隱藏視窗 ShowWindow(SW_HIDE),托盤圖標右鍵選單提供「顯示/退出」。GetSystemMenu(FALSE) 獲取指標,**切勿傳 TRUE** (會重置選單丟失自訂項)。OnSysCommand 中 nID & 0xFFF0 是標準寫法,兼容系統內部使用低 4 位。