上一篇我們學習了利用windows API創建工具欄和狀態欄,與上一篇緊密聯系的就是菜單欄,菜單欄是一個大多數復雜一些的Windows應用程序不可或缺的部分。比如下圖就是Windows自帶的記事本的菜單欄:
菜單一般都是在標題欄下,工具欄以上,常常叫主菜單或頂級菜單(top-level menu),頂級菜單可能還會有彈出菜單(popup menu)或子菜單(submenu)。彈出菜單還有被“選中”(checked)狀態,各菜單還有啟用、禁用狀態。
每一個菜單都有一個ID與之對應,當某個菜單被點擊是,程序在WM_COMMAND消息中把菜單ID傳給應該消息處理函數,就能知道哪個菜單被按下。
菜單欄的創建最常見是利用VS的菜單資源編輯器,然后加載該資源。比如下面的代碼片段在創建主窗體時使用了LoadMenu函數加載菜單資源編輯的菜單:
hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(ID_MENU));hWnd = CreateWindow(TEXT(“myclass”), TEXT(“mytitle”), WS_OVERLAPPENDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, hMenu, hInstance, NULL);
另外一種辦法是在處理WM_CREATE消息是調用SetMenu函數來設置菜單:
SetMenu(hWnd, hMenu);
本文一直秉承一個原則,就是采用API的方式來創建而不是資源。因為用API來創建雖然麻煩一點,但是更加獨立,比如如果不是用VS環境,那就可能沒有資源編輯了,要是把我們的源程序在非VS的環境下編譯就能顯示出通用性和可移植性了。
當用戶選擇一個菜單時,會產生WM_INITMENU消息和WM_MENUSELECT,WM_INITMENU消息使得我們有機會在菜單的選中之前做一些事情,而WM_MENUSELECT消息是在菜單被選中或者光標移到該菜單時被發送,我們可以利用這個消息進行菜單選中時的處理。
WM_INITMENUPOPUP消息在一個彈出菜單顯示前發送,可以用來修改一些菜單顯示。
最重要、最常用的就是上面我們提到的WM_COMMAND消息,當菜單被點擊時就會產生這個消息。上面的消息對應的參數意義請參考MSDN。
菜單相關的API有好幾十個,我們這里只用一些常用的API函數,這幾個函數基本可以完成菜單的基本功能,更多的菜單函數和功能的請參考MSDN。
函數CreateMenu可以創建一個菜單,CreatePopupMenu創建一個下拉式或彈出是菜單。函數AppendMenu可以追加一個菜單項,函數InsertMenu可以插入一個菜單項,TrackPopupMenu函數將在指定的位置顯示一個彈出菜單。這幾個菜單原型如下:
HMENU CreateMenu(VOID);HMENU CreatePopupMenu(VOID);BOOL AppendMenu(HMENU hMenu, UINT uFlags, UINT_PTR uIDNewItem, LPCTSTR lpNewItem);BOOL InsertMenu(HMENU hMenu, UINT uPosition, UINT uFlags, PTR uIDNewItem, LPCTSTR lpNewItem);BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, HWND prcRect);
其實菜單的常用部分大都是用這幾個函數完成的,并不復雜。不說了,直接一邊上代碼一邊解釋更直接,由于篇幅,這里僅僅給出關鍵代碼,完整的demo請查看文章底部的原文鏈接:
HMENU CreateMenuBar(void){ //總菜單 HMENU hMenu = CreateMenu(); //文件菜單 HMENU hFileMenu = CreateMenu(); AppendMenu(hFileMenu, MF_STRING, IDM_FILE_NEW, TEXT("&New")); AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL); //插入一條橫條,請看運行效果 AppendMenu(hFileMenu, MF_STRING, IDM_FILE_SAVE, TEXT("&Save")); AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, TEXT("File(&F)")); //文件的二級子菜單 HMENU hSubMenu = CreateMenu(); AppendMenu(hSubMenu, MF_STRING, IDM_FILE_OPEN_SOLUTION, TEXT("So&lution")); AppendMenu(hSubMenu, MF_STRING, IDM_FILE_OPEN_PROJECT, TEXT("Pro&ject")); //將該二級菜單插入到第二條的位置 InsertMenu(hFileMenu, 1, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hSubMenu, TEXT("Open")); //編輯菜單 hFileMenu = CreateMenu(); AppendMenu(hFileMenu, MF_STRING, IDM_EDIT_COPY, TEXT("&Copy")); AppendMenu(hFileMenu, MF_STRING, IDM_EDIT_PASTE, TEXT("&Paste")); AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL); AppendMenu(hFileMenu, MF_STRING|MF_CHECKED, IDM_EDIT_HL, TEXT("&update"));//增加一個check選項 AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, TEXT("Edit(&E)")); //縮放菜單 hFileMenu = CreateMenu(); AppendMenu(hFileMenu, MF_STRING, IDM_VIEW_HALF, TEXT("&Half")); AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL); //設置一個灰色不可選的菜單,該菜單可以用EnableMenuItem函數修改可選狀態 AppendMenu(hFileMenu, MF_STRING|MF_GRAYED, IDM_VIEW_PART, TEXT("P&art")); AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, TEXT("Zoom(&Z)")); return hMenu;}static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hDC; PAINTSTRUCT ps; switch (message) { case WM_CREATE: { HMENU hMenu = CreateMenuBar(); SetMenu(hWnd, hMenu); //以上只是創建了菜單,需要設置 } return 0; case WM_RBUTTONUP: { POINT point; point.x = LOWORD(lParam); point.y = HIWORD(lParam); ClientToScreen(hWnd, &point); //這里的坐標是相對于屏幕的,需要轉換為客戶坐標 HMENU hSubMenu = GetSubMenu(GetMenu(hWnd), 0); //獲取菜單的第0個子菜單,用這個菜單來演示彈出菜單 TrackPopupMenu(hSubMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL); } return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_FILE_NEW: MessageBox(hWnd, TEXT("you click new file button"), TEXT("hint"), MB_OK); break; default: break; } return 0; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); ; EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0 ; } return DefWindowProc (hWnd, message, wParam, lParam);}
本demo運行后點擊“文件”菜單如下:
點擊“編輯”菜單如下:
鼠標右鍵彈出快捷菜單:
文篇只演示了常用的菜單,其他比如位圖菜單、非客戶區彈出菜單等更多內容有興趣在討論,也可以參考MSDN的相關函數自己進行測試。本文的菜單欄編程結合上一篇的創建工具欄和狀態欄內容以及第二篇的創建常用控件部分,基本可以完成窗口應用程序的界面編程了。當然再次強調,我們這些都是基于Windows API函數完成的,可能很多人會說,我用MFC,資源編輯器,對話框下的控件面板、甚至VB、C#都可以很快編寫出這些界面。沒錯,但是隱藏在這些的下面還是會回到我們這些基本的API上,這個才是根。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
北京到莫斯科的火車票價?北京到莫斯科有兩趟車,分別是K3和K19。K3的火車票價格為2911元,與蒙古國過境,由承運。列車乘務員都來自,所以溝通方便。K19的價格是4122元,從北京到莫斯科是直達,比K3用的時間長。因為K3要經過兩個國家,所以要辦理兩個簽證,簽證的價格在1500左右。從北京到莫斯科的火車票要多少錢?截至2020年1月17日,K3次列車無軟臥,高鋪6080元,硬臥3793元,手續費...
北華大學北校區怎么樣?北校區是北華三個校區中最老的,但北校區的宿舍條件是三個校區中最好的。今年9月,學校只剩下少量的六人宿舍,大部分都是四人宿舍。學校周邊屬于吉林偏遠地區,環境比較混亂,但是北校區還是可以滿足你正常的學習和生活的??傊?,北華完全有資格為你的成功。北華大學北校區多少人?北校區有16300多名學生。北華大學,簡稱北華,位于吉林省吉林市。是吉林省規模最大的綜合性重點大學,“卓越博士教育培...
QQ群禁止瀏覽如何解散群~或刪除群?如果是自己創建的群,可以解散: 在面板的群欄目里找到該群右鍵單擊群圖標“解散該群”進入解散頁面后按提示操作即可。 注意:該操作不可逆,將解除群內所有成員的群友關系,同時刪除群空間的所有資料。 如果是別人的群,直接退出就可以了:右鍵單擊群圖標退出該群。群解散怎么解?可以先發個公告,告訴大家由于某某理由,這個群要解散了。然后再發一段表示謝意的話,也表示一下歉意。然后...