invoke loadmenu,hinstance, idr_childmenu mov hchildmenu,eax ........ invoke destroymenu, hchildmenu
within the message loop, we call translatemdisysaccel.
.while true invoke getmessage,addr msg,null,0,0 .break .if (!eax) invoke translatemdisysaccel,hwndclient,addr msg .if !eax invoke translatemessage, addr msg invoke dispatchmessage, addr msg .endif .endw
if translatemdisysaccel returns a non-zero value, it means the message was already handled by windows itself so you don't need to do anything to the message. if it returns 0, the message is not mdi-related and thus should be handled as usual.
wndproc proc hwnd:hwnd, umsg:uint, wparam:wparam, lparam:lparam ..... .else invoke defframeproc,hwnd,hwndclient,umsg,wparam,lparam ret .endif xor eax,eax ret wndproc endp
note that within the window procedure of the frame window, we call defframeproc to handle the messages we are not interested in.
the bulk of the window procedure is the wm_command handler. when the user selects "new" from the file menu, we create a new mdi child window.
.elseif ax==idm_new invoke sendmessage,hwndclient,wm_mdicreate,0,addr mdicreate
in our example, we create the mdi child window by sending wm_mdicreate to the client window, passing the address of the mdicreatestruct structure in lparam.
childproc proc hchild:dword,umsg:dword,wparam:dword,lparam:dword .if umsg==wm_mdiactivate mov eax,lparam .if eax==hchild invoke getsubmenu,hchildmenu,1 mov edx,eax invoke sendmessage,hwndclient,wm_mdisetmenu,hchildmenu,edx .else invoke getsubmenu,hmainmenu,1 mov edx,eax invoke sendmessage,hwndclient,wm_mdisetmenu,hmainmenu,edx .endif invoke drawmenubar,hwndframe
when the mdi child window is created, it monitors wm_mdiactivate to see if it's the active window. it does this by comparing the value of the lparam which contains the handle of the active child window with its own handle. if they match, it's the active window and the next step is to replace the menu of the frame window to its own. since the original menu will be replaced, you have to tell windows again in which submenu the window list should appear. that's why we must call getsubmenu again to retrieve the handle to the submenu. we send wm_mdisetmenu message to the client window to achieve the desired result. wparam of wm_mdisetmenu contains the handle of the menu you would like to replace the original menu. lparam contains the handle of the submenu you want the window list to appear. right after sending wm_mdisetmenu, we call drawmenubar to refresh the menu else your menu will be a mess.
.else invoke defmdichildproc,hchild,umsg,wparam,lparam ret .endif
within the window procedure of the mdi child window, you must pass all unhandled messages to defmdichildproc instead of defwindowproc.
.elseif ax==idm_tilehorz invoke sendmessage,hwndclient,wm_mditile,mditile_horizontal,0 .elseif ax==idm_tilevert invoke sendmessage,hwndclient,wm_mditile,mditile_vertical,0 .elseif ax==idm_cascade invoke sendmessage,hwndclient,wm_mdicascade,mditile_skipdisabled,0
when the user selects one of the menuitems in the window submenu, we send the corresponding message to the client window. if the user chooses to tile the windows, we send wm_mditile to the client window, specifying in wparam what kind of tiling we want. wm_cascade is similar.