MDIDemo.MOD: Translation to Stony Brook Modula-2

Last updated: 4. 3.1998, 23:49

<*/NOWARN:F*>
MODULE MDIDemo;
(*--------------------------------------------------------
   MDIDEMO.C       --- Multiple Document Interface Demonstration
                   (c) Charles Petzold, 1996
   MDIDemo.mod     --- Translation to Stony Brook Modula-2
                   (c) Peter Stadler,   1998
  --------------------------------------------------------*)

%IF WIN32 %THEN
    <*/Resource:MDIDEMO.RES*>
%ELSE
%END

IMPORT WIN32;
IMPORT WINUSER;
IMPORT SYSTEM;
IMPORT h2d_mdidemo;
IMPORT WINGDI;
IMPORT COMMCTRL;
IMPORT COMMDLG;
IMPORT RandomNumbers;
IMPORT WINX;

VAR
  hPrevInstance :  WIN32.HINSTANCE;


          (* structure for storing data unique to each Hello child window      *)

TYPE
  HELLODATA = RECORD
                   iColor    :  WIN32.UINT;
                   clrText   :  WIN32.COLORREF;
                 END;

  LPHELLODATA = POINTER TO HELLODATA;

          (* structure for storing data unique to each Rect child window       *)
  RECTDATA  = RECORD
                   cxClient  :  WIN32.SHORT;
                   cyClient  :  WIN32.SHORT;
                 END;
  LPRECTDATA = POINTER TO RECTDATA;

     (* global variables                                                  *)

VAR
   szFrameClass : ARRAY[0..20] OF CHAR = "MdiFrame";
   szHelloClass : ARRAY[0..20] OF CHAR = "MdiHelloChild";
   szRectClass  : ARRAY[0..20] OF CHAR = "MdiRectChild";
VAR
   hInst        :  WIN32.HINSTANCE;
   hMenuInit    :  WIN32.HMENU;
   hMenuHello   :  WIN32.HMENU;
   hMenuRect    :  WIN32.HMENU;
   hMenuInitWindow     : WIN32.HMENU;
   hMenuHelloWindow    : WIN32.HMENU;
   hMenuRectWindow     : WIN32.HMENU;
VAR
  hAccel       :    WIN32.HACCEL;
  hwndFrame    :    WIN32.HWND;
  hwndClient   :    WIN32.HWND; 
  msg          :    WINUSER.MSG;
  wc           :    WINUSER.WNDCLASSEX;
  (* static in different WndProcs *)
  hwndClientOfRect     :  WIN32.HWND;
  hwndFrameOfRect      :  WIN32.HWND;
  hwndClientOfFrame    :  WIN32.HWND;
  hwndClientOfHello    :  WIN32.HWND;
  hwndFrameOfHello     :  WIN32.HWND;
TYPE
  COLORREFARRAY=  ARRAY[0..4] OF WIN32.COLORREF;

VAR
  clrTextArray : COLORREFARRAY;



(*++++*****************************************************************)
PROCEDURE MaxInt (a,b : INTEGER) : INTEGER;
(**********************************************************************)
BEGIN
  IF(a>b) THEN
    RETURN a;
  ELSE
    RETURN b;
  END;
END MaxInt;
(*++++*****************************************************************)
PROCEDURE MinInt (a,b : INTEGER) : INTEGER;
(**********************************************************************)
BEGIN
  IF(a>b) THEN
    RETURN b;
  ELSE
    RETURN a;
  END;
END MinInt;
<*/PUSH*>
%IF WIN32 %THEN
    <*/CALLS:WIN32SYSTEM*>
%ELSE
    <*/CALLS:WINSYSTEM*>
%END
(*++++**********************************************************************)
PROCEDURE FrameWndProc (hwnd        : WIN32.HWND;
                        iMsg        : WIN32.UINT;
                        wParam      : WIN32.WPARAM;
                        lParam      : WIN32.LPARAM) : WIN32.LRESULT [EXPORT];
(***************************************************************************)
VAR
  clientcreate    : WINUSER.CLIENTCREATESTRUCT;
  hwndChild       : WIN32.HWND;
  mdicreate       : WINUSER.MDICREATESTRUCT;
BEGIN
     CASE (iMsg) OF
          | WINUSER.WM_CREATE :          (* Create the client window                *)

               clientcreate.hWindowMenu  := hMenuInitWindow;
               clientcreate.idFirstChild := h2d_mdidemo.IDM_FIRSTCHILD;

               hwndClientOfFrame := WINUSER.CreateWindow ("MDICLIENT", "",
                              WINUSER.WS_CHILD BOR WINUSER.WS_CLIPCHILDREN BOR WINUSER.WS_VISIBLE,
                              0, 0, 0, 0, hwnd, SYSTEM.CAST(WIN32.HMENU, 1), hInst,
                              SYSTEM.CAST(WIN32.LPSTR, SYSTEM.ADR(clientcreate)));
               RETURN 0;

          | WINUSER.WM_COMMAND :
               CASE (wParam) OF
                    | h2d_mdidemo.IDM_NEWHELLO :       (* Create a Hello child window   *)

                         mdicreate.szClass := SYSTEM.ADR(szHelloClass);
                         mdicreate.szTitle := SYSTEM.ADR("Hello");
                         mdicreate.hOwner  := hInst;
                         mdicreate.x       := WINUSER.CW_USEDEFAULT;
                         mdicreate.y       := WINUSER.CW_USEDEFAULT;
                         mdicreate.cx      := WINUSER.CW_USEDEFAULT;
                         mdicreate.cy      := WINUSER.CW_USEDEFAULT;
                         mdicreate.style   := 0;
                         mdicreate.lParam  := 0;

                         hwndChild := SYSTEM.CAST(WIN32.HWND, WINUSER.SendMessage (hwndClientOfFrame,
                                        WINUSER.WM_MDICREATE, 0,
                                        SYSTEM.CAST(WIN32.LPARAM,SYSTEM.CAST(WINUSER.LPMDICREATESTRUCT, SYSTEM.ADR(mdicreate)))));
                         RETURN 0;

                    | h2d_mdidemo.IDM_NEWRECT :        (* Create a Rect child window    *)

                         mdicreate.szClass := SYSTEM.ADR(szRectClass);
                         mdicreate.szTitle := SYSTEM.ADR("Rectangles");
                         mdicreate.hOwner  := hInst;
                         mdicreate.x       := WINUSER.CW_USEDEFAULT;
                         mdicreate.y       := WINUSER.CW_USEDEFAULT;
                         mdicreate.cx      := WINUSER.CW_USEDEFAULT;
                         mdicreate.cy      := WINUSER.CW_USEDEFAULT;
                         mdicreate.style   := 0;
                         mdicreate.lParam  := 0;

                         hwndChild := SYSTEM.CAST(WIN32.HWND, WINUSER.SendMessage (hwndClientOfFrame,
                                        WINUSER.WM_MDICREATE, 0,
                                        SYSTEM.CAST(WIN32.LPARAM,SYSTEM.CAST(WINUSER.LPMDICREATESTRUCT, SYSTEM.ADR(mdicreate)))));
                         RETURN 0;

                    | h2d_mdidemo.IDM_CLOSE :          (* Close the active window       *)

                         hwndChild := SYSTEM.CAST(WIN32.HWND, WINUSER.SendMessage (hwndClientOfFrame,
                                                  WINUSER.WM_MDIGETACTIVE, 0, 0));

                         IF (WINUSER.SendMessage (hwndChild, WINUSER.WM_QUERYENDSESSION, 0, 0)=1) THEN
                              WINUSER.SendMessage (hwndClientOfFrame, WINUSER.WM_MDIDESTROY,
                                           SYSTEM.CAST(WIN32.WPARAM, hwndChild), 0);
                         END;
                         RETURN 0;

                    | h2d_mdidemo.IDM_EXIT :           (* Exit the program              *)

                         WINUSER.SendMessage (hwnd, WINUSER.WM_CLOSE, 0, 0);
                         RETURN 0;

                                   (* messages for arranging windows           *)
                    | h2d_mdidemo.IDM_TILE :
                         WINUSER.SendMessage (hwndClientOfFrame, WINUSER.WM_MDITILE, 0, 0);
                         RETURN 0;

                    | h2d_mdidemo.IDM_CASCADE :
                         WINUSER.SendMessage (hwndClientOfFrame, WINUSER.WM_MDICASCADE, 0, 0);
                         RETURN 0;

                    | h2d_mdidemo.IDM_ARRANGE :
                         WINUSER.SendMessage (hwndClientOfFrame, WINUSER.WM_MDIICONARRANGE, 0, 0);
                         RETURN 0;

                    | h2d_mdidemo.IDM_CLOSEALL :       (* Attempt to close all children *)

                         WINUSER.EnumChildWindows (hwndClientOfFrame, CloseEnumProc, 0);
                         RETURN 0;

                    ELSE                 (* Pass to active child...            *)

                         hwndChild := SYSTEM.CAST(WIN32.HWND, WINUSER.SendMessage (hwndClientOfFrame,
                                                  WINUSER.WM_MDIGETACTIVE, 0, 0));

                        IF (WINUSER.IsWindow (hwndChild)) THEN
                             WINUSER.SendMessage (hwndChild, WINUSER.WM_COMMAND,
                                          wParam, lParam);
                        END;
                       (*break*)        (* ...and then to DefFrameProc          *)
                    END;
               (*break*)

          | WINUSER.WM_QUERYENDSESSION :
          | WINUSER.WM_CLOSE :                     (* Attempt to close all children *)

               WINUSER.SendMessage (hwnd, WINUSER.WM_COMMAND, h2d_mdidemo.IDM_CLOSEALL, 0);

               IF (NIL # WINUSER.GetWindow (hwndClientOfFrame, WINUSER.GW_CHILD)) THEN
                    RETURN 0;
               END;
               (*break*)   (* I.e., call DefFrameProc                            *)

          | WINUSER.WM_DESTROY :
               WINUSER.PostQuitMessage (0);
               RETURN 0;
               (* Pass unprocessed messages to DefFrameProc (not DefWindowProc)*)

       RETURN WINUSER.DefFrameProc (hwnd, hwndClientOfFrame, iMsg, wParam, lParam);
     ELSE
       RETURN 0;
     END;
END FrameWndProc;
<*/POP*>

<*/PUSH*>
%IF WIN32 %THEN
    <*/CALLS:WIN32SYSTEM*>
%ELSE
    <*/CALLS:WINSYSTEM*>
%END
(*++++**********************************************************************)
PROCEDURE CloseEnumProc  (hwnd        : WIN32.HWND;
                         lParam       : WIN32.LPARAM) : WIN32.BOOL [EXPORT];
(***************************************************************************)
BEGIN
     IF (WINUSER.GetWindow (hwnd, WINUSER.GW_OWNER)#NIL) THEN    (* Check for icon title           *)
          RETURN SYSTEM.CAST(WIN32.BOOL,1);
     END;
     WINUSER.SendMessage (WINUSER.GetParent (hwnd), WINUSER.WM_MDIRESTORE, SYSTEM.CAST(WIN32.WPARAM,hwnd), 0);

     IF (WINUSER.SendMessage (hwnd, WINUSER.WM_QUERYENDSESSION, 0, 0)#0) THEN
          RETURN SYSTEM.CAST(WIN32.BOOL,1);
     END;
     WINUSER.SendMessage (WINUSER.GetParent (hwnd), WINUSER.WM_MDIDESTROY, SYSTEM.CAST(WIN32.WPARAM,hwnd), 0);
     RETURN SYSTEM.CAST(WIN32.BOOL,1);
END CloseEnumProc;
<*/POP*>

<*/PUSH*>
%IF WIN32 %THEN
    <*/CALLS:WIN32SYSTEM*>
%ELSE
    <*/CALLS:WINSYSTEM*>
%END
(*++++**********************************************************************)
PROCEDURE HelloWndProc (hwnd        : WIN32.HWND;
                        iMsg        : WIN32.UINT;
                        wParam      : WIN32.WPARAM;
                        lParam      : WIN32.LPARAM) : WIN32.LRESULT [EXPORT];
(***************************************************************************)


VAR
  hdc            :  WIN32.HDC;
  hMenu          :  WIN32.HMENU;
  lpHelloData    :  LPHELLODATA;
  ps             :  WINUSER.PAINTSTRUCT;
  rect           :  WIN32.RECT;
  par            :  WIN32.LPARAM;


BEGIN
     CASE (iMsg) OF
          | WINUSER.WM_CREATE :
                         (* Allocate memory for window private data            *)

               lpHelloData := SYSTEM.CAST(LPHELLODATA, WIN32.HeapAlloc (WIN32.GetProcessHeap (),
                                                      WIN32.HEAP_ZERO_MEMORY,
                                                      SIZE(HELLODATA)));
               lpHelloData^.iColor  := h2d_mdidemo.IDM_BLACK;
               lpHelloData^.clrText := WINGDI.RGB (0, 0, 0);
               WINUSER.SetWindowLong (hwnd, 0, SYSTEM.CAST(WIN32.LONG, lpHelloData));

                         (* Save some window handles                           *)

               hwndClientOfHello := WINUSER.GetParent (hwnd);
               hwndFrameOfHello  := WINUSER.GetParent (hwndClientOfHello);
               RETURN 0;

          | WINUSER.WM_COMMAND :
               CASE (wParam) OF
                    | h2d_mdidemo.IDM_BLACK :
                         lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
                         hMenu := WINUSER.GetMenu (hwndFrameOfHello);
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_UNCHECKED);
                         lpHelloData^.iColor := wParam;
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_CHECKED);
                         lpHelloData^.clrText :=
                               clrTextArray[wParam - h2d_mdidemo.IDM_BLACK];
                         WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, FALSE);
                         RETURN 0;
                    | h2d_mdidemo.IDM_RED :
                         lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
                         hMenu := WINUSER.GetMenu (hwndFrameOfHello);
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_UNCHECKED);
                         lpHelloData^.iColor := wParam;
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_CHECKED);
                         lpHelloData^.clrText :=
                               clrTextArray[wParam - h2d_mdidemo.IDM_BLACK];
                         WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, FALSE);
                         RETURN 0;
                    | h2d_mdidemo.IDM_GREEN :
                         lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
                         hMenu := WINUSER.GetMenu (hwndFrameOfHello);
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_UNCHECKED);
                         lpHelloData^.iColor := wParam;
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_CHECKED);
                         lpHelloData^.clrText :=
                               clrTextArray[wParam - h2d_mdidemo.IDM_BLACK];
                         WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, FALSE);
                         RETURN 0;
                    | h2d_mdidemo.IDM_BLUE :
                         lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
                         hMenu := WINUSER.GetMenu (hwndFrameOfHello);
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_UNCHECKED);
                         lpHelloData^.iColor := wParam;
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_CHECKED);
                         lpHelloData^.clrText :=
                               clrTextArray[wParam - h2d_mdidemo.IDM_BLACK];
                         WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, FALSE);
                         RETURN 0;
                    | h2d_mdidemo.IDM_WHITE :
                                   (* Change the text color                    *)

                         lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
                         hMenu := WINUSER.GetMenu (hwndFrameOfHello);
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_UNCHECKED);
                         lpHelloData^.iColor := wParam;
                         WINUSER.CheckMenuItem (hMenu, lpHelloData^.iColor,
                                               WINUSER.MF_CHECKED);
                         lpHelloData^.clrText :=
                               clrTextArray[wParam - h2d_mdidemo.IDM_BLACK];
                         WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, FALSE);
                         RETURN 0;
               ELSE
                         RETURN 0;
               END;
          | WINUSER.WM_PAINT :
                         (* Paint the window                                   *)

               hdc := WINUSER.BeginPaint (hwnd, ps);

               lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
               WINGDI.SetTextColor (hdc, lpHelloData^.clrText);

               WINUSER.GetClientRect (hwnd, rect);

               WINUSER.DrawText (hdc, "Hello, World!", -1, rect,
                         WINUSER.DT_SINGLELINE BOR WINUSER.DT_CENTER BOR WINUSER.DT_VCENTER);

               WINUSER.EndPaint (hwnd, ps);
               RETURN 0;

          | WINUSER.WM_MDIACTIVATE :

                         (* Set the Hello menu if gaining focus                *)

               IF (lParam = SYSTEM.CAST(WIN32.LPARAM, hwnd)) THEN
                    WINUSER.SendMessage (hwndClientOfHello, WINUSER.WM_MDISETMENU,
                               SYSTEM.CAST(WIN32.WPARAM, hMenuHello), SYSTEM.CAST(WIN32.LPARAM, hMenuHelloWindow));
               END;
                         (* Check or uncheck menu item                         *)

               lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));

               IF(lParam = SYSTEM.CAST(WIN32.LPARAM,hwnd)) THEN
                  par := WINUSER.MF_CHECKED;
               ELSE
                  par := WINUSER.MF_UNCHECKED;
               END;
               WINUSER.CheckMenuItem (hMenuHello, lpHelloData^.iColor,par);

                         (* Set the Init menu if losing focus                  *)

               IF (lParam # SYSTEM.CAST(WIN32.LPARAM, hwnd)) THEN
                    WINUSER.SendMessage (hwndClientOfHello, WINUSER.WM_MDISETMENU, SYSTEM.CAST(WIN32.WPARAM, hMenuInit),
                                 SYSTEM.CAST(WIN32.LPARAM, hMenuInitWindow));
               END;
               WINUSER.DrawMenuBar (hwndFrameOfHello);
               RETURN 0;

          | WINUSER.WM_QUERYENDSESSION :
          | WINUSER.WM_CLOSE :
               IF (WINUSER.IDOK # WINUSER.MessageBox (hwnd, "OK to close window?", "Hello",
                                       WINUSER.MB_ICONQUESTION BOR WINUSER.MB_OKCANCEL)) THEN
                    RETURN 0;
               END;
               (*break*)   (* I.e., call DefMDIChildProc                         *)

          | WINUSER.WM_DESTROY :
               lpHelloData := SYSTEM.CAST(LPHELLODATA, WINUSER.GetWindowLong (hwnd, 0));
               WIN32.HeapFree (WIN32.GetProcessHeap (), 0, lpHelloData);
               RETURN 0;
     ELSE
               (* Pass unprocessed message to DefMDIChildProc                  *)

       RETURN WINUSER.DefMDIChildProc (hwnd, iMsg, wParam, lParam);
     END;
END HelloWndProc;
<*/POP*>

<*/PUSH*>
%IF WIN32 %THEN
    <*/CALLS:WIN32SYSTEM*>
%ELSE
    <*/CALLS:WINSYSTEM*>
%END
(*++++**********************************************************************)
PROCEDURE RectWndProc  (hwnd        : WIN32.HWND;
                        iMsg        : WIN32.UINT;
                        wParam      : WIN32.WPARAM;
                        lParam      : WIN32.LPARAM) : WIN32.LRESULT [EXPORT];
(***************************************************************************)
VAR
  hBrush         :  WIN32.HBRUSH;
  hdc            :  WIN32.HDC;
  lpRectData     :  LPRECTDATA;
  ps             :  WINUSER.PAINTSTRUCT;
  xLeft          :  INTEGER;
  xRight         :  INTEGER;
  yTop           :  INTEGER;
  yBottom        :  INTEGER;
  nRed           :  WIN32.SHORT;
  nGreen         :  WIN32.SHORT;
  nBlue          :  WIN32.SHORT;
BEGIN
     CASE (iMsg) OF
          | WINUSER.WM_CREATE :
                         (* Allocate memory for window private data            *)

               lpRectData := SYSTEM.CAST(LPRECTDATA, WIN32.HeapAlloc (WIN32.GetProcessHeap (),
                                                    WIN32.HEAP_ZERO_MEMORY,
                                                    SIZE(RECTDATA)));

               WINUSER.SetWindowLong (hwnd, 0, SYSTEM.CAST(WIN32.LONG,lpRectData));

                         (* Start the timer going                              *)

               WINUSER.SetTimer (hwnd, 1, 250, NIL);

                         (* Save some window handles                           *)

               hwndClientOfRect := WINUSER.GetParent (hwnd);
               hwndFrameOfRect  := WINUSER.GetParent (hwndClientOfRect);
               RETURN 0;

          | WINUSER.WM_SIZE :            (* If not minimized, save the window size  *)

               IF (wParam # WINUSER.SIZE_MINIMIZED) THEN
                    lpRectData := SYSTEM.CAST(LPRECTDATA, WINUSER.GetWindowLong (hwnd, 0));

                    lpRectData^.cxClient := WINUSER.LOWORD (lParam);
                    lpRectData^.cyClient := WINUSER.HIWORD (lParam);
               END;

               (*break*)                 (* WINUSER.WM_SIZE must be processed by DefMDIChildProc  *)

          | WINUSER.WM_TIMER :           (* Display a random rectangle              *)

               lpRectData := SYSTEM.CAST(LPRECTDATA, WINUSER.GetWindowLong (hwnd, 0));

               xLeft   := VAL(INTEGER,RandomNumbers.Random(0,1000) REM VAL(CARDINAL,lpRectData^.cxClient));
               xRight  := VAL(INTEGER,RandomNumbers.Random(0,1000) REM VAL(CARDINAL,lpRectData^.cxClient));
               yTop    := VAL(INTEGER,RandomNumbers.Random(0,1000) REM VAL(CARDINAL,lpRectData^.cyClient));
               yBottom := VAL(INTEGER,RandomNumbers.Random(0,1000) REM VAL(CARDINAL,lpRectData^.cyClient));
               nRed    := VAL(INTEGER,RandomNumbers.Random(0,1000) BAND 255);
               nGreen  := VAL(INTEGER,RandomNumbers.Random(0,1000) BAND 255);
               nBlue   := VAL(INTEGER,RandomNumbers.Random(0,1000) BAND 255);

               hdc := WINUSER.GetDC (hwnd);
               hBrush := WINGDI.CreateSolidBrush (WINGDI.RGB (nRed, nGreen, nBlue));
               WINGDI.SelectObject (hdc, SYSTEM.CAST(WIN32.HGDIOBJ,hBrush));

               WINGDI.Rectangle (hdc, MinInt (xLeft, xRight), MinInt (yTop, yBottom),
                               MaxInt (xLeft, xRight), MaxInt (yTop, yBottom));

               WINUSER.ReleaseDC (hwnd, hdc);
               WINGDI.DeleteObject (SYSTEM.CAST(WIN32.HGDIOBJ,hBrush));
               RETURN 0;

          | WINUSER.WM_PAINT :           (* Clear the window                        *)

               WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, TRUE);
               hdc := WINUSER.BeginPaint (hwnd, ps);
               WINUSER.EndPaint (hwnd, ps);
               RETURN 0;

          | WINUSER.WM_MDIACTIVATE :     (* Set the appropriate menu                *)
               IF (lParam = SYSTEM.CAST(WIN32.LPARAM, hwnd)) THEN
                    WINUSER.SendMessage (hwndClientOfRect, WINUSER.WM_MDISETMENU, SYSTEM.CAST(WIN32.WPARAM, hMenuRect),
                                 SYSTEM.CAST(WIN32.LPARAM,hMenuRectWindow));
               ELSE
                    WINUSER.SendMessage (hwndClientOfRect, WINUSER.WM_MDISETMENU, SYSTEM.CAST(WIN32.WPARAM, hMenuInit),
                                 SYSTEM.CAST(WIN32.LPARAM, hMenuInitWindow));
               END;

               WINUSER.DrawMenuBar (hwndFrameOfRect);
               RETURN 0;

          | WINUSER.WM_DESTROY :
               lpRectData := SYSTEM.CAST(LPRECTDATA, WINUSER.GetWindowLong (hwnd, 0));
               WIN32.HeapFree (WIN32.GetProcessHeap (), 0, lpRectData);
               WINUSER.KillTimer (hwnd, 1);
               RETURN 0;
               (* Pass unprocessed message to DefMDIChildProc                  *)

     ELSE
       RETURN WINUSER.DefMDIChildProc (hwnd, iMsg, wParam, lParam);
     END;
END RectWndProc;
<*/POP*>
(*+++***********************************************************************)
PROCEDURE InitApplication () : BOOLEAN;
(***************************************************************************)

VAR
  rc : CARDINAL;
BEGIN
  hInst := WINX.Instance;
  hPrevInstance := WINX.PrevInstance;

  IF (hPrevInstance=NIL) THEN
                 (* Register the frame window class                         *)

    wc.cbSize        := SIZE(WINUSER.WNDCLASSEX);
    wc.style         := WINUSER.CS_HREDRAW BOR WINUSER.CS_VREDRAW;
    wc.lpfnWndProc   := FrameWndProc;
    wc.cbClsExtra    := 0;
    wc.cbWndExtra    := 0;
    wc.hInstance     := WINX.Instance;
    wc.hIcon         := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);
    wc.hCursor       := WINUSER.LoadCursor (NIL, WINUSER.IDC_ARROW^);
    wc.hbrBackground := SYSTEM.CAST(WIN32.HBRUSH,WINUSER.COLOR_APPWORKSPACE + 1);
    wc.lpszMenuName  := NIL;
    wc.lpszClassName := SYSTEM.ADR(szFrameClass);
    wc.hIconSm       := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);

    rc := WINUSER.RegisterClassEx (wc);

              (* Register the Hello child window class                   *)

    wc.cbSize        := SIZE(WINUSER.WNDCLASSEX);
    wc.style         := WINUSER.CS_HREDRAW BOR WINUSER.CS_VREDRAW;
    wc.lpfnWndProc   := HelloWndProc;
    wc.cbClsExtra    := 0;
    wc.cbWndExtra    := SIZE(WIN32.HANDLE);
    wc.hInstance     := WINX.Instance;
    wc.hIcon         := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);
    wc.hCursor       := WINUSER.LoadCursor (NIL, WINUSER.IDC_ARROW^);
    wc.hbrBackground := SYSTEM.CAST(WIN32.HBRUSH, WINGDI.GetStockObject (WINGDI.WHITE_BRUSH));
    wc.lpszMenuName  := NIL;
    wc.lpszClassName := SYSTEM.ADR(szHelloClass);
    wc.hIconSm       := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);

    rc := WINUSER.RegisterClassEx (wc);

              (* Register the Rect child window class                    *)

    wc.cbSize        := SIZE(WINUSER.WNDCLASSEX);
    wc.style         := WINUSER.CS_HREDRAW BOR  WINUSER.CS_VREDRAW;
    wc.lpfnWndProc   := RectWndProc;
    wc.cbClsExtra    := 0;
    wc.cbWndExtra    := SIZE(WIN32.HANDLE);
    wc.hInstance     := WINX.Instance;
    wc.hIcon         := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);
    wc.hCursor       := WINUSER.LoadCursor (NIL, WINUSER.IDC_ARROW^);
    wc.hbrBackground := SYSTEM.CAST(WIN32.HBRUSH, WINGDI.GetStockObject (WINGDI.WHITE_BRUSH));
    wc.lpszMenuName  := NIL;
    wc.lpszClassName := SYSTEM.ADR(szRectClass);
    wc.hIconSm       := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);

    rc := WINUSER.RegisterClassEx (wc);
    RETURN rc #0;
  END;
END InitApplication;

(*+++***********************************************************************)
PROCEDURE InitMainWindow () : BOOLEAN;
(***************************************************************************)
BEGIN
     hMenuInit  := WINUSER.LoadMenu (hInst, "MdiMenuInit");
     hMenuHello := WINUSER.LoadMenu (hInst, "MdiMenuHello");
     hMenuRect  := WINUSER.LoadMenu (hInst, "MdiMenuRect");

     hMenuInitWindow  := WINUSER.GetSubMenu (hMenuInit,   h2d_mdidemo.INIT_MENU_POS);
     hMenuHelloWindow := WINUSER.GetSubMenu (hMenuHello, h2d_mdidemo.HELLO_MENU_POS);
     hMenuRectWindow  := WINUSER.GetSubMenu (hMenuRect,   h2d_mdidemo.RECT_MENU_POS);

               (* Load accelerator table                                       *)

     hAccel := WINUSER.LoadAccelerators (hInst, "MdiAccel");

               (* Obtain handles to three possible menus & submenus            *)


     hwndFrame := WINUSER.CreateWindow (szFrameClass, "MDI Demonstration : Stony Brook Modula-2",
                               WINUSER.WS_OVERLAPPEDWINDOW BOR WINUSER.WS_CLIPCHILDREN,
                               WINUSER.CW_USEDEFAULT, WINUSER.CW_USEDEFAULT,
                               WINUSER.CW_USEDEFAULT, WINUSER.CW_USEDEFAULT,
                               NIL, hMenuInit, WINX.Instance, NIL);

     hwndClient := WINUSER.GetWindow (hwndFrame, WINUSER.GW_CHILD);

  IF hwndFrame = NIL THEN
     RETURN FALSE;
  END;
  WINUSER.ShowWindow (hwndFrame, WINUSER.SW_SHOWDEFAULT);
  WINUSER.UpdateWindow (hwndFrame);
  RETURN TRUE;
END InitMainWindow;
BEGIN
  clrTextArray := COLORREFARRAY
                             { WINGDI.RGB (0,   0, 0), WINGDI.RGB (255, 0,   0),
                               WINGDI.RGB (0, 255, 0), WINGDI.RGB (  0, 0, 255),
                               WINGDI.RGB (255, 255, 255) } ;
  IF InitApplication() AND InitMainWindow() THEN
               (* Enter the modified message loop                              *)
    WHILE (WINUSER.GetMessage (msg, NIL, 0, 0)) DO
          IF ( WINUSER.TranslateMDISysAccel (hwndClient, msg)=SYSTEM.CAST(WIN32.BOOL,0)) AND
              (WINUSER.TranslateAccelerator (hwndFrame, hAccel, msg)=0) THEN
            WINUSER.TranslateMessage (msg);
            WINUSER.DispatchMessage (msg);
          END;
    END;

               (* Clean up by deleting unattached menus                        *)
     WINUSER.DestroyMenu (hMenuHello);
     WINUSER.DestroyMenu (hMenuRect);
  END;
END MDIDemo.