1. 程式人生 > >MFC隱藏/顯示最大化、最小化按鈕

MFC隱藏/顯示最大化、最小化按鈕

在該MFC專案中Ctrl+F,查詢EXSTYLE WS_EX_APPWINDOW,查詢結果在 專案名.rc 檔案中,如:


IDD_TESTMFC_DIALOG DIALOGEX  0, 0, 320, 200
STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION
 | WS_THICKFRAME
 | WS_SYSMENU
 | WS_MINIMIZEBOX
 | WS_MAXIMIZEBOX
EXSTYLE WS_EX_APPWINDOW


隱藏最大化按鈕:去掉 | WS_MAXIMIZEBOX
隱藏最小化按鈕:去掉 | WS_MINIMIZEBOX
顯示最大化按鈕:新增 | WS_MAXIMIZEBOX
顯示最小化按鈕:新增 | WS_MINIMIZEBOX


參考資料:
最大化、最小化和關閉按鈕是視窗中最主要的元素。首先要說明,說他們是按鈕其實是不準確的,按鈕是一種視窗,而這三個元件根本就不是視窗,而是一個視窗常見的組成部分。出於習慣的原因,這裡還是稱呼他們為按鈕。
這三個按鈕是否顯示似乎只能在視窗建立是決定。首先,要顯示這三個按鈕,視窗必須有標題條和系統選單,沒有標題條和系統選單的視窗是不能顯示這三個按鈕的,也就是說,要想有這三個按鈕,建立視窗時必須有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);
}


}