1. Overview The MDI window contains a frame window and a number of sub-windows. In fact, the frame window itself is an ordinary main window, but its customers are covered by a special window. This special window is a system-predefined "window class", class name: "mdiclient". It is responsible for the management of individual MDI sub-windows.
Second, the window is established 1. Register an MDI frame window class, provide the MDI Frame Wall Wall Processing Function MDI Framework window message processing function, the unprocessed message is handled by DEFFRAMEPROC
// MDI Frame Wall Message Processing Function
Lresult Callback MDIFrameWndProc (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM)
{
// ...
/ / Other messages handle the default frame processing function provided by the system DEFFRAMEPROC
// where the second parameter is the client area window handle
Return :: DefframeProc (HWND, HWndClient, Message, WPARAM, LPARAM);
} 2. Register multiple MDI sub-window classes, corresponding to the message processing function of each MDI sub-window
In the sub-window message processing function, the unopened message is handled by MDIDEFMDICHILDPROC.
// MDI sub-window message processing function
LResult Callback MdichildWndProc (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM)
{
// ...
// ...
// Other messages handle the default MDI sub-window processing function provided by the system
Return :: DefmdichildProc (HWND, Message, WPARAM, LPARAM);
}
3. Establish the MDI management sub-window in the client area of the frame window
The management of the MDI sub-window is actually done by the "MDILIENT" window of the frame window client area.
This is a system predefined window.
After receiving the WM_CREATE message at the main window:
Case WM_CREATE:
{
Hinst = ((lpcreateStruct) LParam -> Hinstance;
// Fill the ClientCreatestruct structure
ClientCreatestruct ClientCreate;
ClientCreate.hwindowMenu = HMENUINITWINDOW; / / Menu handle for adding a window list
ClientCreate.idfirstchild = 50000; // Start ID
HWndClient = CREATEWINDOWEX (0,
"Mdiclient", // class name is "mdiclient"
NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0,
0,
0,
0,
HWnd,
(HMENU) 1, // ID
Hinst, // Example handle
& clientcreate); // parameter
}
Return 0; the size of the window does not matter, the default frame window message handler is to overwrite the entire client area.
After the MDI client area window is established, the establishment, destruction, arrangement, etc. of the message management sub-window is sent to it.
4. The establishment of MDI sub-window can be added to the menu to create a sub-window. After the message processing function of the frame window receives the command, send a command to the MDI Customer Window.
Case ID_new:
{
Mdicreatestruct Mdicreate;
Mdicreate.szclass = szmdichildname; // MDI sub-window class name
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 Customer Area Handle
Wm_mdicreate, // Create a MDI sub-window
0,
(LpMdicreateStruct) & mdicreate // Create parameters
);
}
Break;
Third, the message loop is handled for the MDI hotkey
In the message loop, use TranslateMdisysAccel to process hot keys for MDI.
While (GetMessage (& MSG, NULL, 0, 0))
{
IF (! TranslateMdisysaccel (HWndClient, & MSG) &&&
TranslateAccelerator (HWndFrame, Haccel, & MSG))
{
TranslateMessage (& MSG);
DispatchMessage (& MSG);
}
}
Fourth, the flow of orders
After receiving the WM_COMMAND, the frame window should provide the currently activated MDI window to process the process.
Case WM_COMMAND:
Switch (loword (wparam))
{
// command to the framework
Case id_one:
// ...
Return 0;
/ / Direct to MDI sub-window management
Case idm_window_tile:
SendMessage (hwndclient, wm_mditile, 0, 0);
Return 0;
/ / Deal with the sub-window for the sub-window
DEFAULT:
HWNDCHILD = (hwnd) SendMessage (HWndClient,
WM_MDIGETACTIVE, 0, 0);
IF (Iswindow (HWNDPHILD))
SendMessage (HWndchild, WM_Command, WPARAM, LPARAM);
Break; //..and the to defframeproc
}
Break; // Jump out of the CASE branch for WM_Command, and defframePROC handles the remaining command
5. Management of sub-windows
1 Overview
Control the message to the MDI client area window
Such as:
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. Close up of the current sub-window
When you turn off the current activation window, first send query messages to this window: WM_QueryEndSession.
The message processing loop of the sub-window responds to this message, and some processing before turning off, if it is turned off, return true
Otherwise it will return.
In the frame window, according to this return value, decide if the window is turned off.
If the user directly presses the off button of the sub-window, the WM_CLOSE message sends directly to the sub-window message processing function.
For example: Frame window command processing:
Case IDM_FILE_CLOSE: // Get the current activation window
HWNDCHILD = (hwnd) SendMessage (HWndClient, WM_MDiGetActive, 0, 0);
// After the inspection, destroy the window
IF (SendMessage (HWndchild, WM_QueryEndSession, 0, 0))
SendMessage (HWndClient, WM_MDIDESTROY, (WPARAM) HWNDCHILD, 0);
Return 0; the message processing function of the sub-window:
LResult Callback HellownProc (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. Close all sub-windows
When you use a command mode to close all sub-windows, you need to enumerate all sub-windows to close.
example:
Frame window Response command:
Case idm_window_closeall:
// Perform CloseenumProc for all subsets
EnumchildWindows (HWndClient, CloseenumProc, 0);
Return 0; enumeration function:
Bool Callback CloseenumProc (HWND HWND, LPARAM LPARAM)
{
IF (getWindow (hwndow (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;
}
Six, menu control
In the MDI program, the menu of the frame window can be switched depending on the activated sub-window.
Also, you can add a window list to the menu. The added menu item command is completed by the default message processing function corresponding to the frame.
1. Prepare a set of menu resources for each window class
2. Load menu to get a menu handle
3. When the framework is established, use the handle of the frame menu as the parameter.
4. When the child window is activated, load your own menu to the frame window.
Restore the frame menu when you lose the focus.
Use the WM_MDisetMenu or WM_MDisetMenu message to the MDI client area window.
WPARAM is a menu handle, LParam For the child handle to add a window list
Case WM_MDIACTIVATE:
/ / When activated, set the frame menu
IF (lparam == (lparam) hWnd)
SendMessage (HWndClient, WM_MDisetMenu,
(Wparam) HMenuhello, (lParam) hmenuhellowindow);
// When you lose the focus, restore the frame menu
IF (lParam! = (lparam) hWnd) SendMessage (HWndClient, WM_MDisetMenu, (WPARAM) HMenuinit,
(LParam) HMenuinitWindow;
Drawmenubar (HWNDFrame);
// Note: How to get hwndframe:
// hWndClient = getParent (hwnd);
// hwndframe = getParent (hwndclient);
Return 0; (full text)