最大化、最小化和關閉按鈕

 

概述

最大化、最小化和關閉按鈕是窗口中最主要的元素。首先要說明,說他們是按鈕其實是不準確的,按鈕是一種窗口,而這三個組件根本就不是窗口,而是一個窗口常見的組成部分。出於習慣的原因,這裏還是稱呼他們爲按鈕。

這三個按鈕是否顯示似乎只能在窗口創建是決定。首先,要顯示這三個按鈕,窗口必須有標題條和系統菜單,沒有標題條和系統菜單的窗口是不能顯示這三個按鈕的,也就是說,要想有這三個按鈕,創建窗口時必須有WS_CAPTION和WS_SYSMENU風格。當窗口創建時有風格WS_MAXIMIZEBOX時,窗口顯示最大化按鈕,當有風格WS_MINIMIZEBOX時,窗口顯示最小化按鈕,而只要有標題條並且有系統菜單,關閉按鈕就必然會顯示出來。

對這三個按鈕的操作往往都是系統菜單來進行的,這也解釋了爲什麼要顯示這三個按鈕必須有系統菜單。一般而言,當一個窗口有最大化按鈕時,在系統菜單裏也會有對應的菜單項,對這個菜單項的操作一般都能反饋到這各按鈕中。其中,最大化按鈕在系統菜單中的ID爲SC_MAXIMIZE,最小化按鈕爲SC_MINIMIZE,而關閉按鈕爲SC_CLOSE。當窗口處於最大化狀態時,系統菜單SC_MAXIMIZE則變會並被禁止,而此時最大化按鈕變爲恢復按鈕,ID對應爲系統菜單中的SC_RESTORE。

變灰和使能

一般從功能上來講,界面元素有使能(Enabled)和禁止(Disabled)兩種狀態,當界面元素處於使能狀態時,用戶可以使用它,否則用戶不能使用它。而從外觀的顏色角度講,界面元素有灰色狀態(Grayed)和普通狀態兩種狀態,一般對於使能的界面元素,不應該是灰色的,而對於禁止的界面元素,則應該是灰色的。

這三個按鈕也是如此。讓人奇怪的是,雖然這三個按鈕通過系統菜單操作,它的行爲似乎並不和普通菜單項不完全一致。使能、禁止、變灰一個菜單項的操作都是通過EnableMenuItem,一般常見的使能一個菜單項ID_MY_MENU的代碼爲:

       EnableMenuItem(hMenu,ID_MY_MENU,MF_BYCOMMAND|MF_ENABLED);
                          或者用CMenu的成員函數
       pMenu->EnableMenuItem(ID_MY_MENU,MF_BYCOMMAND|MF_ENABLED);

而禁止並同時使它變灰的代碼則爲:

       EnableMenuItem(hMenu,ID_MY_MENU,MF_BYCOMMAND|MF_GRAYED|MF_DISABLED);
                          或者用CMenu的成員函數
       pMenu->EnableMenuItem(ID_MY_MENU,MF_BYCOMMAND|MF_GRAYED|MF_DISABLED);

注意:雖然從一般的視覺效果上變灰和禁止是一起起作用的,實際上在內部實現上,這兩者並沒有捆綁在一起,只有同時設置MF_GRAYED|MF_DISABLED,兩個功能才同時作用。否則如果只使用MF_GRAYED,則只變灰不禁止,如果只使用MF_DISABLED,則只禁止不變灰。

後續文字根據網友留言修改。感謝網元提醒

這段代碼對於菜單項總是很有效的,對關閉按鈕也有作用,但是對於最大化和最小化按鈕,則完全沒有作用。對系統菜單應用上述代碼後,系統菜單內的對應項的狀態已經正確轉變,但是窗口這兩個按鈕的功能和外觀都未變化。

爲了禁止並變灰兩個按鈕中的一個,唯一的方法是從系統菜單中刪除這個菜單項,代碼如下:

         CMenu* pSysMenu = GetSystemMenu(FALSE);
         ASSERT_VALID(pSysMenu);
         if(NULL == pSysMenu)
         {
                return;
          }
          pSysMenu->DeleteMenu(SC_MINIMIZE,MF_BYCOMMAND);

爲了使能一個按鈕,則需要向系統菜單中添加這個按鈕對應的項,代碼爲:

         CMenu* pSysMenu = GetSystemMenu(FALSE);
         ASSERT_VALID(pSysMenu);
         if(NULL == pSysMenu)
         {
                return;
          }
          pSysMenu->AppendMenu(MF_STRING,SC_MINIMIZE,_T("最小化(&N)"));

消息處理

對於這三個消息的響應,也一樣通過系統菜單的途徑來處理的。系統菜單中的所有項都是通過消息WM_SYSCOMMAND來處理的,這個消息的wParam包含了需要處理的消息類型,其含義如下表:

含義
SC_CLOSE 關閉按鈕
SC_MAXIMIZE 最大化按鈕
SC_MINIMIZE 最小化按鈕
SC_RESTORE 恢復按鈕

這裏只列出了和三個按鈕的相關說明,其他值的說明請讀者閱讀MSDN。

爲了自己截獲這三個按鈕的處理,需要處理WM_SYSCOMMAND消息。下面的代碼示例就是處理SC_MINIMIZE消息並隱藏對話框到任務欄的常見操作。

void CTdDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX) {
CAboutDlg dlgAbout; dlgAbout.DoModal();
} else if(nID == SC_MINIMIZE) {
NOTIFYICONDATA nid; nid.cbSize = sizeof(nid); nid.hIcon = m_hIcon; nid.hWnd = GetSafeHwnd(); GetWindowText(nid.szTip ,sizeof(nid.szTip )); nid.uCallbackMessage = WM_NOTIFY_ICON_MESSAGE; nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON; nid.uID = 1; ShowWindow(SW_HIDE); Shell_NotifyIcon(NIM_ADD,&nid);
}else{
CDialog::OnSysCommand(nID, lParam);
}
}

對於對話框的SC_CLOSE按鈕,缺省調用OnCancel,用戶也可以仿照上面代碼截獲並不調用OnCancel

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章