OWLWindows' Multiple Document Interface (MDI) offers programmers a powerful way to control the objects - especially the document windows - that make up an application. An MDI application not only creates a sort of mini-desktop on which user can organize related windows and icons, but also provides the programmer with many easy-to-implement functions that automatically handle those windows. MDI application require a little more effort to programmer, but their advantages far outweigh any extra labor involved.
Thanks to OWL, however, creating an MDI application is amazing easy. You need only to use the special OWL classes for MDI applications - including TMDIFrame(or TDecoratedMDIFrame), TMDIClient, and TMDIChild - and supply an appropriate Window menu. The rest is almost automatic.
What exactly makes up an MDI application? Here's a list of the most important characteristics:
In your InitMainWindow() function, first construct the application's client window:
<pre> TMDIClient* clientWnd = new TMDIClientWnd;
</pre>
Every OWL MDI aplication must have a client window derived from the TMDIClient class (which means you must include the header file <owl/mdichild.h>, as well as <owl/mdi.h>, in your program ). This program has it's own client window class, which of course, derives from OWL's TMDIClient class:
<pre> class TMDIClientWnd: public TMDIClient{ public: TMDIClientWnd(); protected: TMdiChild* InitChild(); };
</pre>
TMDIClient is, in turn, derived from TWindow and provides message-response functions for the MDI commands in the Window menu, including CmCreateChild(), CmCloseChildrens(), CmCascadeChildren(), and CmTileChildren(). TMDIClient also features command enablers for the Window menu, so you don't need to fuss over enabling and disabling items in the Window menu. Finally, TMDIChild's member functions GetActiveMDIChild() and InitChild() enable you to get a pointer to the active child window and create custom child windows.
<pre> TMDIChild* TMDIClientWnd::InitChild() { return new TMDIChild(*this, "An MDI Child"); }
</pre>
After constructing the client window, construct the application's main window, which must be of the TMDIFrame class (or class derived from TMDIFrame):
<pre> TMDIFrame* frame = new TMDIFrame("MDI App",MENU_1, *clientWnd);
</pre>
TMDIFrame's constructor takes as parameter a title string, a menu resource ID, and a reference to a client window. The TMDIFrame class is derived from TFrameWindow and handles such task as finding and storing the position of the application's Window menu. In addition, this class provides the member functions GetClientWindow(), which returns a pointer to the frame window's client window, and SetMenu(), which you can call to update the position of the Window menu after you install a new menu bar.
Finally, when you create the menu IDs for your Window menu, you must use the values defined by OWL for the WIndow menu. The resource header file
<owl/mdi.rh>
, defines a set constants that you can use for this purpose. This constants are
CM_CASCADECHILDREN
(24361),
CM_TILECHILDREN
(24362),
CM_TILECHILDRENHORIZ
(24363),
CM_ARANGEICONS
(24364),
CM_CLOSECHILDREN
(24365), and
CM_CREATECHILD
(24366). An OWL client window already has message-response functions that respond to these menu item IDs.
Sample program:
<pre> // sample.cpp #include <owl\applicat.h> #include <owl\mdi.h> #include <owl\mdichild.h> #include "mdiapp.rc" ////////////////////////////////// // The application class. class TMDIApp : public TApplication{ public: TMDIApp() : TApplication() {} void InitMainWindow(); }; ////////////////////////////////// // The client window class. class TMDIClientWnd : public TMDIClient{ protected: int childNum; public: TMDIClientWnd(); protected: TMDIChild *InitChild(); }; /////////////////////////////////////////////////////////// // TMDIClientWnd::TMDIClientWnd() TMDIClientWnd::TMDIClientWnd() : TMDIClient() { childNum = 1; } /////////////////////////////////////////////////////////// // TMDIClientWnd::InitChild() TMDIChild* TMDIClientWnd::InitChild() { // Create a new child window caption. char s[20]; wsprintf(s, "Child Window #%d", childNum); // Increment the MDI child window number. ++childNum; // Create and return a pointer to // a new MDI child window. return new TMDIChild(*this, s); } /////////////////////////////////////////////////////////// // TMDIApp::InitMainWindow() void TMDIApp::InitMainWindow() { // Create an MDI client window. TMDIClient *clientWnd = new TMDIClientWnd; // Create the MDI frame window. TMDIFrame *wndw = new TMDIFrame("MDI App", MENU_1, *clientWnd); SetMainWindow(wndw); } /////////////////////////////////////////////////////////// // OwlMain() /////////////////////////////////////////////////////////// int OwlMain(int, char*[]) { return TMDIApp().Run(); } //////////////////////////////////////////////////////// // sample.rc #ifndef WORKSHOP_INVOKED #include "windows.h" #endif #include <owl\mdi.rh> #include <owl\window.rh> #define MENU_1 100 #ifdef RC_INVOKED MENU_1 MENU { POPUP "&File" { MENUITEM "E&xit", CM_EXIT } POPUP "&Window" { MENUITEM "C&reate", CM_CREATECHILD MENUITEM "&Cascade", CM_CASCADECHILDREN MENUITEM "&Tile", CM_TILECHILDREN MENUITEM "Arrange &Icons", CM_ARRANGEICONS MENUITEM "C&lose All", CM_CLOSECHILDREN } } #endif //////
</pre>