INF: Suggested Changes to Petzold's MDIDEMO Program

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