如何定製對話框系統菜單

本文例子是一個典型的C++/MFC對話框程序,設置了 EX_WM_TOOLWINDOW 擴展式樣,所以在標題欄左上角看不到系統菜單圖標,但經過 Ctrl+Space 或者在標題欄單擊鼠標右鍵能夠調出系統菜單。例子程序對系統菜單進行了定製,在原有菜單基礎上添加了兩個菜單命令:一個是顯示「關於」對話框;另外一個是「退出」。之因此要加一個「退出」菜單命令,是由於例子程序改寫了對話框原來默認的「關閉」菜單命令行爲(Alt-F4),用來隱藏對話框。所以必須加一個程序的「退出」出口。此外,例子程序利用一個第三方的系統托盤處理類,利用系統托盤圖標能夠顯示/隱藏對話框。 下面咱們就來看看用 C++/MFC 實現的細節。函數

添加菜單ui

首先在資源定義文件 resource.h 中定義菜單項標示,也能夠在標準頭文件中定義。菜單項標示必須具備惟一性。其次,Windows 對系統菜單的處理與常規菜單的處理方法是不一樣的,不論是缺省的菜單仍是定製的菜單,它們都沒有象常規菜單命令那樣的消息處理例程。假設咱們要添加兩個定製的系統單:spa

1.#define IDM_ABOUT 16命令行

2.#define IDM_EXIT 17指針

IDM_的意思是該定義爲菜單項ID。添加菜單命令是在對話框的初始化例程以及窗口建立函數(OnInitDialog(), OnCreate())中進行的。如:對象

01.BOOL CBabelOnDlg::OnInitDialog()索引

02.{資源

03.CDialog::OnInitDialog();文檔

04. 字符串

05.// 在系統菜單中添加 "關於..." 和 "退出菜單項

06. 

07. 

08.// 解決 Windows 95 中的 bug

09.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

10. 

11.// 命令 IDs 必須在預約義的系統菜單以後

12.ASSERT(IDM_ABOUTBOX < 0xF000);

13. 

14.// 解決 Windows 95 中的 bug

15.ASSERT((IDM_EXIT & 0xFFF0) == IDM_EXIT);

16. 

17.// 命令 IDs 必須在預約義的系統菜單以後

18.ASSERT(IDM_EXIT < 0xF000);

19. 

20.CMenu* pSysMenu = GetSystemMenu(FALSE);

21.if (pSysMenu != NULL)

22.{

23.pSysMenu->AppendMenu(MF_STRING,IDM_EXIT,"退出(&x)");

24.pSysMenu->AppendMenu(MF_SEPARATOR);

25.pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, "關於(&A)...");

26.......

27.}

28. 

29.......

30. 

31.//other initialization

32.}

這裏在添加每一個菜單前都有兩個 ASSERT 語句,第一個 ASSERT 的目的是修復 Windows 95 中存在的 Bug,第二個 ASSERT 保證定製的命令 IDs 是在預約義的系統菜單以後,以避免發生衝突。查一下 MSDN 庫的 MFC 文檔關於系統菜單的描述,你會發現下面的內容:

「......全部預約義的控制菜單項(也就是系統菜單)的ID號必須大於 0xF000。若是某個應用程序要添加系統菜單,其系統菜單的 ID 號必須小於F000。」

接下來,用 GetSystemMenu 函數獲取系統菜單指針。調用時使用參數 FALSE 獲取指針。若是用 TRUE 做爲參數,那麼該函數會將菜單重置回缺省狀態。

若是獲得的指針有效,接着調用菜單添加命令在系統菜單後面添加菜單項,傳遞菜單IDs以及菜單顯示時所用的字符串。

處理定製的菜單命令

爲了讓這些系統菜單命令工做起來,咱們不能依賴常規的菜單消息處理機制----即使菜單項相同。一般系統菜單經過WM_SYSCOMMAND 消息處理:

01.void CBabelOnDlg::OnSysCommand(UINT nID, LPARAM lParam)

02.{

03.//trap our own system menu messages

04.if ((nID & 0xFFF0) == IDM_ABOUTBOX)

05.{

06.CAboutDlg dlgAbout;

07.dlgAbout.DoModal();

08.} else if ((nID & 0xFFF0)==SC_CLOSE){

09.OnClose();

10.} else if ((nID & 0xFFF0)==IDM_EXIT) {

11.::PostQuitMessage(0);

12.}

13.else {

14.CDialog::OnSysCommand(nID, lParam);

15.}

16.}

經過比較傳入的菜單ID進行相應的處理。注意代碼中又有兩個「nID & 0xFFF0」,這主要也是解決 Windows 95 的 bug。若是選擇「退出」,那麼會嚮應用程序發送退出消息:::PostQuitMessage(0)。

注意第二個條件檢查:SC_CLOSE 是個預約義的菜單常量。通常它是由 Windows 處理的,由於在例子程序中咱們對它進行了定製,因此必需要本身處理它。原本 SC_CLOSE 是退出程序,但例子程序咱們把它的行爲改寫成隱藏對話框,也就是將應用變成一個托盤小圖標,處理例程見 OnClose() 函數。若是傳入的菜單ID不等於任何定製的菜單項,那麼就讓 Windows 對它進行默認處理:

1.CDialog::OnSysCommand(nID, lParam);

下面是幾個最經常使用的系統菜單命令:

菜單

說明

SC_CLOSE

關閉 CWnd 對象

SC_MAXIMIZE 或者 SC_ZOOM

最大化 CWnd 對象

SC_MINIMIZE 或者 SC_ICON

最小化 CWnd 對象

SC_MOVE

移動 CWnd 對象

SC_RESTORE

恢復窗口的正常位置和大小

SC_SIZE

改變 CWnd 對象大小

其它的幾個系統菜單命令通常都是在特殊狀況下才使用,有關細節請參考有關 WM_SYSCOMMAND 的文檔。

修改現有的菜單命令

咱們已經看到,系統菜單自己默認的處理行爲是能夠改變的,除此以外,系統菜單項的描述文本也是能夠改變的,甚至還能夠刪除它們。爲了修改才單命令的描述文本,咱們能夠用 pSysMenu 指針調用 ModifyMenu() 函數。例如,若是想要把「關閉」菜單項改爲「隱藏」,能夠象下面這麼作:

1.pSysMenu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND,IDM_HIDE, "隱藏(&H)");

MF_BYCOMMAND 參數告訴該函數將 SC_CLOSE 解釋爲命令 ID。IDM_HIDE 是新的菜單 ID。最後一個參數是菜單項的說明文本。還有一種調用 ModifyMenu() 的方法是使用 菜單項索引做爲參數:

1.pSysMenu->ModifyMenu(0,MF_BYPOSITION,IDM_HIDE,"隱藏(&H)");

第一個參數 0 表示菜單項的索引,指第一個菜單。

刪除菜單命令

例子程序擬將去掉系統菜單中的窗口「關閉」命令,暫且不說這樣作是否合適,可是咱們能作到這一點:

1.pSysMenu->RemoveMenu(SC_CLOSE,MF_BYCOMMMAND);

2.pSysMenu->RemoveMenu(0,MF_BYPOSITION);

第一行代碼刪除了與 SC_CLOSE 關聯的菜單命令。而第二行代碼表示刪除系統菜單命令中的第一項。

用這種方式修改系統菜單儘管限定了應用程序的某些行爲,但對於小型應用和實用程序來講有時是頗有用的,尤爲是當你想要從任務欄存取菜單命令時----也就是程序在後臺運行或者以最小化方式運行,右鍵單擊任務欄圖標將彈出系統菜單。

相關文章
相關標籤/搜索