Windows SDK編程–建立MDI視窗

來源:互聯網
上載者:User

一、概述
MDI視窗包含一個架構視窗和若干子視窗。
實際上,架構視窗本身是一個普通主視窗,不過它的客戶去被一個特殊視窗覆蓋。
這個特殊視窗是系統預定義的“視窗類別”,類名稱為:"MDICLIENT"。它負責各個MDI子視窗的管理。

二、視窗建立
1.註冊一個MDI架構視窗類別,提供MDI架構視窗訊息處理函數
MDI架構視窗訊息處理函數中,將未處理訊息交由DefFrameProc處理

//MDI架構視窗訊息處理函數LRESULT CALLBACK MDIFrameWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ //...  //其他訊息交給由系統提供的預設架構處理函數DefFrameProc //其中,第二個參數是客戶區視窗控制代碼 return ::DefFrameProc (hwnd,hwndClient, message, wParam, lParam) ;}

2.註冊多個MDI子視窗類、對應提供各MDI子視窗的訊息處理函數
子視窗訊息處理函數中,將未處理訊息交由MDIDefMDIChildProc處理

//MDI子視窗訊息處理函數LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ //... //...  //其他訊息交給由系統提供的預設MDI子視窗處理函數 return ::DefMDIChildProc (hwnd, message, wParam, lParam) ;}

3.在架構視窗的客戶區建立MDI管理子視窗
MDI子視窗的管理實際上是由架構視窗客戶區的"MDILIENT"視窗完成的。
這是一個系統預定義的視窗。

在主視窗收到WM_CREATE訊息後:

case WM_CREATE:{ hinst=((LPCREATESTRUCT) lParam)->hInstance;     //填充CLIENTCREATESTRUCT結構 CLIENTCREATESTRUCT clientcreate ; clientcreate.hWindowMenu    = hMenuInitWindow ;     //用於添加視窗列表的菜單控制代碼 clientcreate.idFirstChild = 50000 ; //起始ID hwndClient =CreateWindowEx(0,   "MDICLIENT", //類名稱為"MDICLIENT"   NULL,   WS_CHILD |WS_CLIPCHILDREN| WS_VISIBLE,   0,   0,   0,   0,   hwnd,   (HMENU)1,//ID   hinst, //執行個體控制代碼   &clientcreate); //參數}return 0;

視窗的大小沒有關係,預設的架構視窗訊息處理函數為讓它覆蓋整個客戶區。
MDI客戶區視窗建立後,通過向它發送訊息管理子視窗的建立、銷毀、排列等等。

4.MDI子視窗的建立
可以在菜單中添加命令項,以建立子視窗。
架構視窗的訊息處理函數收到命令後,向MDI客戶區視窗發建立命令。

case ID_NEW:{ MDICREATESTRUCT mdicreate; mdicreate.szClass = szMDIChildName ; //MDI子視窗的類名稱 mdicreate.szTitle = TEXT ("Hello") ; mdicreate.hOwner    = hinst ; mdicreate.x         = CW_USEDEFAULT ; mdicreate.y         = CW_USEDEFAULT ; mdicreate.cx        = CW_USEDEFAULT ; mdicreate.cy        = CW_USEDEFAULT ; mdicreate.style     = 0 ; mdicreate.lParam    = 0 ; SendMessage (   hwndClient, //MDI客戶區視窗控制代碼   WM_MDICREATE, //建立MDI子視窗   0,   (LPARAM) (LPMDICREATESTRUCT) &mdicreate //建立參數   ) ;}break;

三、訊息迴圈中處理針對MDI的熱鍵
在訊息迴圈中,用TranslateMDISysAccel處理針對MDI的熱鍵。

while (GetMessage (&msg, NULL, 0, 0)){       if (!TranslateMDISysAccel (hwndClient, &msg) &&           !TranslateAccelerator (hwndFrame, hAccel, &msg))       {            TranslateMessage (&msg) ;            DispatchMessage (&msg) ;       }}

四、命令的流向
架構視窗在收到WM_COMMAND等通知訊息後,應該給當前啟用的MDI視窗提供處理機會。

case WM_COMMAND:switch (LOWORD (wParam)){ //針對架構的命令 case ID_ONE:      //...   return 0; //針對MDI子視窗管理的命令    case IDM_WINDOW_TILE:    SendMessage (hwndClient, WM_MDITILE, 0, 0) ;   return 0 ;  //針對子視窗的命令又子視窗去處理                  default:   hwndChild = (HWND) SendMessage (hwndClient,                                                 WM_MDIGETACTIVE, 0, 0) ;   if (IsWindow (hwndChild))    SendMessage (hwndChild, WM_COMMAND, wParam, lParam) ;                                  break ;          //..and then to DefFrameProc}break ;    //跳出針對WM_COMMAND的case分支,又DefFrameProc處理剩下的命令

五、子視窗的管理
1.概述
給MDI客戶區視窗發控制訊息即可
如:

case WM_COMMAND:switch (LOWORD (wParam)){ case IDM_WINDOW_TILE:   SendMessage (hwndClient, WM_MDITILE, 0, 0) ;   return 0 ;                  case IDM_WINDOW_CASCADE:   SendMessage (hwndClient, WM_MDICASCADE, 0, 0) ;   return 0 ;                  case IDM_WINDOW_ARRANGE:   SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0) ;       return 0;                           //...          //...}break;

2.當前子視窗的關閉
關閉當前啟用視窗時,先向該視窗發送查詢訊息:WM_QUERYENDSESSION。
子視窗的訊息處理迴圈中響應此訊息,作關閉前的一些處理,若能關閉,返回真
否則返回假。
架構視窗中根據此傳回值決定是否關閉視窗。

如果使用者直接按下子視窗的關閉按鈕,則WM_CLOSE訊息直接發送到了子視窗訊息處理函數。

例如:
架構視窗命令處理中:

case IDM_FILE_CLOSE:            //獲得當前啟用視窗hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0);//詢問通過後,銷毀視窗if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0))       SendMessage (hwndClient, WM_MDIDESTROY, (WPARAM) hwndChild, 0);return 0;

子視窗的訊息處理函數中:

LRESULT CALLBACK HelloWndProc (HWND hwnd, UINT message,                                  WPARAM wParam, LPARAM lParam){       switch (message)       { //... //...       case WM_QUERYENDSESSION:       case WM_CLOSE:            if (IDOK != MessageBox (hwnd, TEXT ("OK to close window?"),                                    TEXT ("Hello"),                                     MB_ICONQUESTION | MB_OKCANCEL))                 return 0 ;                             break ;     // i.e., call DefMDIChildProc       }       return DefMDIChildProc (hwnd, message, wParam, lParam) ;}

3.關閉所有子視窗
當使用命令方式關閉所有子視窗時,需要枚舉所有子視窗進行關閉。
例:
架構視窗響應命令:

case IDM_WINDOW_CLOSEALL:       //針對所有子視窗執行CloseEnumProc EnumChildWindows (hwndClient, CloseEnumProc, 0) ; return 0 ;

枚舉函數:

BOOL CALLBACK CloseEnumProc (HWND hwnd, LPARAM lParam){       if (GetWindow (hwnd, GW_OWNER))           // Check for icon title            return TRUE ;              SendMessage (GetParent (hwnd), WM_MDIRESTORE, (WPARAM) hwnd, 0) ;              if (!SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0))            return TRUE ;              SendMessage (GetParent (hwnd), WM_MDIDESTROY, (WPARAM) hwnd, 0) ;       return TRUE ;}

六、菜單控制
在MDI程式中,可以根據啟用的子視窗而切換架構視窗的菜單。
並且,可以將視窗列表添加到菜單中去。所添加的功能表項目命令是又架構對應的預設訊息處理函數完成的。
1.為每種視窗類別準備一套菜單資源
2.裝載菜單,得到菜單控制代碼
3.架構在建立時,使用架構菜單的控制代碼作為參數。
4.子視窗在啟用時,載入自己菜單到架構視窗
失去焦點時,還原架構菜單。
使用向MDI客戶區視窗發送WM_MDISETMENU或WM_MDISETMENU訊息。
wParam為菜單控制代碼,lParam為欲添加視窗列表的子功能表控制代碼

case WM_MDIACTIVATE:           //啟用時,設定架構菜單           if (lParam == (LPARAM) hwnd)                 SendMessage (hwndClient, WM_MDISETMENU,                              (WPARAM) hMenuHello, (LPARAM) hMenuHelloWindow) ;                                              //失去焦點時,將架構菜單還原           if (lParam != (LPARAM) hwnd)                 SendMessage (hwndClient, WM_MDISETMENU, (WPARAM) hMenuInit,                              (LPARAM) hMenuInitWindow) ;                             DrawMenuBar (hwndFrame) ;                        //注: hwndFrame的得到方法:            //hwndClient = GetParent (hwnd) ;            //hwndFrame    = GetParent (hwndClient) ;                        return 0 ;
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.