ID Number: Q68119
3.00
WINDOWS
Summary:
MDIDEMO is the title of a sample Windows program that Charles Petzold
introduces in the Windows 3.0 version of his book, "Programming
Windows" (Microsoft Press). This article describes three changes that
should be made to the code in MDIDEMO, and also to any MDI
applications based on MDIDEMO. These changes work around potential
problems in the MDIDEMO application.
More Information:
PROBLEM 1
=========
Symptoms
--------
If the user closes a minimized MDI child window, it becomes impossible
to close MDIDEMO itself, or to exit the Windows session by closing the
Program Manager.
Cause
-----
MDIDEMO will not close until all children of the MDI client window
have closed. However, when a minimized MDI child window is closed, the
accompanying small title window is hidden but not destroyed. Because
this window remains, MDIDEMO is prevented from closing.
Resolution 1
------------
Modify the code to add a line such as the following to the WM_CLOSE
case of each child window procedure [in MDIDEMO, the child window
procedures are RectWndProc() and HelloWndProc()]:
if (IsIconic(hwnd))
SendMessage(GetParent(hwnd), WM_MDIRESTORE, hwnd, 0L);
This call restores the child window before it is destroyed, and the
icon title window is destroyed correctly. MDIDEMO will now close
correctly.
Resolution 2
------------
As an alternative, an MDI application's closing procedure can be
modeled on the MULTIPAD sample program included with the Windows 3.0
Software Development Kit (SDK). MULTIPAD, with its locally defined
CloseAllChildren(), QueryCloseAllChildren(), and QueryCloseChild()
procedures, avoids the closing problem.
PROBLEM 2
=========
Symptoms
--------
In MDIDEMO, the MDI child windows do not have any children. If the MDI
child windows in an application based on MDIDEMO do have any children,
a NULL window handle can be passed to CloseEnumProc(). The application
must check to make sure that this NULL window handle is not passed as
a parameter to any Windows calls.
Cause
-----
A NULL window handle can be passed to CloseEnumProc() due to an
interaction between the order in which EnumChildWindows() enumerates
the children of the MDI Client window and the order in which the
Client window destroys windows in response to a WM_MDIDESTROY message.
Resolution
----------
Add the following code before the first line in CloseEnumProc():
if (!IsWindow(hwnd))
return TRUE;
PROBLEM 3
=========
Symptoms
--------
The amount of free system resources available after the MDI
application is loaded and terminated is lower than the amount of free
system resources available before the application is loaded.
Cause
-----
MDIDEMO loads three menus from its resources: hMenuInit, hMenuHello,
and hMenuRect. When MDIDEMO exits, the two menus that are not active
are not destroyed and the memory occupied by these menus is lost to
the system.
Resolution
----------
Add the following code to the FrameWndProc() function:
case WM_DESTROY:
{
HMENU hCurrentMenu = GetMenu(hwnd);
if (hMenuInit != hCurrentMenu)
DestroyMenu(hMenuInit);
if (hMenuHello != hCurrentMenu)
DestroyMenu(hMenuHello);
if (hMenuRect != hCurrentMenu)
DestroyMenu(hMenuRect);
PostQuitMessage(0);
return 0;
}
Note that DestroyMenu() must NOT be called on the menu that is
currently in use, or the program will crash.
For more information on general issues with the Windows 3.0
implementation of MDI, query this knowledge base on the following
words:
prod(winsdk) and 3.00 and MDI
Additional reference words: 3.00 MICS3 R1.2