The example above is a single-document interface framework, which means that the client area inside the window is a document interface that can be programmed to input or draw text and graphics output, but not multiple documents. For example, the following ultraedit is a typical multi-document interface, he can edit multiple documents at the same time, each document can also be maximized, minimized, and so on, we are today to see how the basic framework of multi-document implementation.
The frame creation of the multiple file interface takes a few steps.
The creation of the main frame window is no different from the normal window, it is to register a class and create an overlapping window with the class, this can be done with the CREATEWINDOW/CREATEWINDOWEX function, the main frame window can use its own menu and the status bar.
The creation of the client area is also used in your CreateWindow, but you need to specify the class as "mdiclient", and this class will create a multi-document client Area window. Alternatively, use the CreateWindowEx function to specify an extension style of ws_ex_mdichild. The customer area does not require menus and status bars.
Creating a work or view window as the actual document window, this also requires registering the class yourself and creating the view window that you need. The view window can have its own menu, which generally does not require a status bar. When the view window is active, the menu of the main window needs to be replaced with the menu of the view window, as it is often the case that the window is being manipulated and the menu substitution is taken for granted. Menu settings are completed by Wm_mdisetmenu message. The message is defined as follows:
SendMessage (Hwndcontrol, Wm_mdisetmenu, WParam, LParam) WParam represents the New frame Window menu, LParam represents the menu handle to set
OK, the basic API is these, the following we directly on the demo program to demonstrate, because the view is generally a multi-document instance, so the demo code with the class to store the view, each view is an instance of a class:
The main file, which includes the main frame window, the client window has been called by the view window:
#include <windows.h> #define client_wnd_bground#define idm_firstchild 1001#define IDM_FILE_NEW 1002HINSTANCE g_hInst; Tchar szmdimainframe[]= text ("Mdi main frame"); Tchar gszappname[] = text ("MDI Demo"); hwnd ghwndmdiclient; hwnd ghwndmainframe; Hmenu ghmainframemenu;void createchildwndmenu (void); Hwnd createdocview (hwnd hparentwnd, hinstance hinstance); static lresult callback mainframeproc (Hwnd hwnd, uint message, wparam wparam, lparam lparam); #ifdef CLIENT_WND_BGROUNDstatic WNDPROC pfOrigClientWndProc; Lresult callback clientwndsubclassproc (Hwnd hwnd, uint umsg, wparam wparam, lparam lparam) { &Nbsp; switch (umsg) { case WM_ERASEBKGND: { rect rect; hdc hdc = (HDC) Wparam; getclientrect (hwnd, &rect); hbrush hbr = createsolidbrush (RGB (125, 150, 125)); HBRUSH holdbr = (Hbrush) SelectObject (HDC,&NBSP;HBR); fillrect (HDC,&NBSP;&RECT,&NBSP;HBR); selectobject (HDC,&NBSP;HOLDBR); &nBsp; deleteobject (HBR); } return TRUE; default: break; } return callwindowproc ( Pforigclientwndproc, hwnd, umsg, wparam, lparam);   #endifHMENU Createmainframemenu (void) { //Main frame menu HMENU hMenu = CreateMenu (); //File menu hmenu hfilemenu = createmenu (); appendmenu (Hfilemenu, mf_string, idm_file_new, text ("&New")); appendmenu (hmenu, mf_popup, (uint_ptr) hfilemenu, text ("&File")); return hmenu;} Int winapi winmain (hinstance hinstance, hinstance hprevinstance, lpstr LpcmdlinE, int nshowcmd) { msg msg; wndclassex Wndclass = {0}; wndclass.cbsize= sizeof (WNDCLASSEX); wndclass.style= cs_hredraw | cs_vredraw; wndclass.lpfnwndproc= MainFrameProc; wndclass.hInstance= hInstance; Wndclass.hicon= null; wndclass.hcursor= loadcursor (NULL, IDC_ARROW); wndclass.hbrBackground= (Hbrush) getstockobject (White_brush); wndclass.lpszclassname= szmdimainframe; if (! RegisterClassEx (&wndclass)) { MessageBox (Null, text ("this program requires windows nt!"), gszappname, mb_ Iconerror); return 0; } g_hinst = hinstance; Ghmainframemenu = createmainframemenu (); createchildwndmenu (); //create the main mdi frame window ghwndmainframe = createwindow (szmdimainframe, gszAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT,// allows system choose an x position cw_usedefault,// allows system choose a y position 400, 300, null,// handle to parent window ghmainframemenu,// handle to menu hinstance,// handle to the instance of module null);// long pointer to a value to be passed to the window through the showwindow (ghwndmainframe, sw_show); updatewindow (GhWndMainFrame); while (GetMessage (&msg, null, 0, 0)) { TranslateMessage (&msg) ; dispatchmessage (&msg) ; } return msg.wparam ;} Lresult callback mainframeproc (Hwnd hwnd, uint message, wparam wparam, lparam lparam) { switch (message) { case WM_CREATE: { CLIENTCREATESTRUCT ccs; ccs.hWindowMenu = NULL; ccs.idFirstChild = IDM_FIRSTCHILD; ghwndmdiclient&nbSp;= createwindow (TEXT ("Mdiclient"), null, ws_child | ws_ clipchildren | ws_visible, 0, 0, 0, 0, hwnd, null, g_hInst, (void *) &ccs); #ifdef CLIENT_WND_BGROUND pforigclientwndproc = (WNDPROC) SetWindowLong (Ghwndmdiclient, gwl_wndproc, (LONG) clientwndsubclassproc); #endif } return 0; case WM_COMMAND: switch (LoWord (wParam)) { case IDM_FILE_NEW: createdocview (Ghwndmdiclient, g_hinst); return 0; } break; case WM_DESTROY: postquitmessage (0); return 0; }&nBsp; return defframeproc (hwnd, ghwndmdiclient, message, wparam, LParam);}
Below is the view window, each view window is described by a class, this article is just a demo, only to instantiate a view window as a demonstration:
#include <windows.h> #define idm_edit_copy 1003#define idm_edit_paste 1004class cviewinfo{public: cviewinfo (hinstance hinst); ~ Cviewinfo (); hwnd createviewwindow (Hwnd hparentwnd);p rivate: HINSTANCE m_hInst; HWND m_hWndView;}; Static tchar szviewwndname[] = text ("View window"); static cviewinfo *g_ psysteminfo;static hmenu ghchildwndmenu;extern hmenu ghMainFrameMenu; Cviewinfo::cviewinfo (Hinstance hinst) { m_hwndview = null; m_hinst = hinst;} Cviewinfo::~cviewinfo () { m_hwndview = null;} Lresult callback viewwindowproc (Hwnd hwnd, uint message, wparam wparam, lparam&nbsP;lparam) { switch (message) &NBSP;&NBSP;&NBSP;&NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;CASE&NBSP;WM _mdiactivate: { hwnd hwndclient = getparent (HWND); hwnd hwndframe = getparent (hWndClient); hmenu hmenu = getsubmenu ( ghchildwndmenu, 0); if ( lparam == (LParam) hWnd) { sendmessage ( hwndclient, wm_mdisetmenu, (WPARAM) ghchildwndmenu, (LPARAM) hMenu); &nbSp; enablemenuitem (ghchildwndmenu, idm_edit_copy, mf_grayed); } // set the framewindow menu if losing focus if (lparam != (LParam) HWND) { sendmessage (HWndClient, WM_MDISETMENU, (WPARAM) ghmainframemenu, (LPARAM) NULL); } // call drawmenubar after the menu items are set &nBsp;drawmenubar (hwndframe); return 0 ; } case wm_close: delete g_pSystemInfo; break; case WM_DESTROY: return 0; } return defmdichildproc (hWnd, Message, wparam, lparam); //frame window calls defframeproc rather Than defwindowproc}hwnd cviewinfo::createviewwindow (Hwnd hparentwnd) { Wndclassex wcdoc; wcdoc.cbsize= sizeof (wndclassex); wcdoc.style= cs_hredraw | cs_vredraw; wcdoc.lpfnwndproc= Viewwindowproc; wcdoC.cbclsextra= 0; wcdoc.cbwndextra= 0; wcdoc.hinstance= m_hInst; wcDoc.hIcon= NULL; wcDoc.hCursor= LoadCursor (Null, idc_arrow); wcdoc.hbrbackground= (HBRUSH) Getstockobject (White_brush); wcdoc.lpszmenuname= null; wcdoc.lpszclassname= szviewwndname; wcdoc.hiconsm= null; if (! RegisterClassEx (&wcdoc)) { dword dw_lasterror = getlasterror (); if (ERROR_CLASS_ Already_exists != dw_lasterror) { return 0; } } m_hwndview = createwindowex (ws_ex_mdichild, szviewwndname, text ("New view"), 0, CW_USEDEFAULT, cw_ usedefault, 300, 200, hparentwnd, null, m_hinst, null); return m_hwndview;} Hwnd createdocview (hwnd hparentwnd, hinstance hinstance) { hwnd hView; G_psysteminfo = new cviewinfo (HINSTANCE); hview = g_ Psysteminfo->createviewwindow (Hparentwnd); if (HView == NULL) { delete g_pSystemInfo; g_pSystemInfo = NULL; } return hview;} Void createchildwndmenu (void) { //view menu ghchildwndmenu = createmenu (); //Edit Menu hmenu heditmenu = createmenu (); appendmenu (Heditmenu, mf_string, idm_edit_copy, text ("©")); appendmenu (Heditmenu, mf_string, idm_edit_paste, text ("&Paste")); appendmenu (ghchildwndmenu, mf_popup, (uint_ptr) HEditMenu, TEXT ("& Edit "));
After running this instance, the interface is as follows:
Select File->new Create a new view after the demo program below, you can see the menu programming View menu:
When maximized, you can see the View window and fill the client window:
Although this program implements only one instance of a view, it is easy to add one, just try to call the Createdocview function in the menu and handle the object pointer correctly. The instance does not add a status bar because this is not required for multiple documents, and the additional reader can refer to the previous Create toolbar and StatusBar article.
This example realizes a basic multi-document window frame, the reader friend can add the toolbar, the status bar, the view window to create the processing of the class, the multi-instance and the concrete demand, completes the practical multi-document interface.
More experience Exchange can join the Windows programming discussion QQ Group :454398517.
Focus on the public platform: The programmer Interaction Alliance (coder_online), you can get the first original technical articles, and (java/c/c++/android/windows/ Linux) Technology Daniel is a friend, online communication programming experience, get programming basics, solve programming problems. Programmer Interactive Alliance , Developer's own home.
Reprint Please specify the source http://www.coderonline.net/?p=2052 , thank you for your cooperation!
"Windows Programming" series 11th: Multi-Document Interface framework