/* MDIFRAME.CLS - This is a class that can be used for
  the creation of an MDI Frame Window.  It has
  redirected all necessary messages to it's default
  window procedure and contains a list of child
  windows that it contains.  In order to create an
  application specific MDI Frame window one should
  only need to create a descendant of this class that
  contains a command method.  Whenever processing a
  message that will create a new MDI Child window the
  processMenu method should be called with the correct
  caption so that the "Windows" menu in your frame
  window will have a correct list of it's children. */!!

inherit(Window, #MDIFrame, #(clientWindow  /* point to client window space */), 2, nil)!!

now(class(MDIFrame))!!

/* Return the default window style. */
Def style(self)
{ ^WS_OVERLAPPEDWINDOW bitOr WS_CLIPCHILDREN;
}!!

now(MDIFrame)!!

/* Enable all items on the menu that can be used if a child window
  is present */
Def enableMenus(self)
{ do(tuple(IDM_CASCADE, IDM_TILE, IDM_ARRANGEICONS),
  {using(menuItem) Call EnableMenuItem(hMenu, menuItem, MF_ENABLED bitOr MF_BYCOMMAND)
  });
}!!

/* Disable all items on the menu that can't be used if a child window
  is not present */
Def disableMenus(self)
{ do(tuple(IDM_CASCADE, IDM_TILE, IDM_ARRANGEICONS),
  {using(menuItem) Call EnableMenuItem(hMenu, menuItem, MF_GRAYED bitOr MF_BYCOMMAND)
  });
}!!

/* Default for dialogs is to do nothing. Return 0
  to let Windows do normal processing.
  WARNING: Do not remove this method! May be redefined
  in descendants if they register a private window
  class with Windows for their dialogs. */
Def defWndProc(self, msgNum, wP, lP)
{ ^if clientWindow
   then Call DefFrameProc(getHWnd(self), getHWnd(clientWindow), msgNum, wP, lP);
   else Call DefWindowProc(getHWnd(self), msgNum, wP, lP);
   endif;
}!!

/* Step through all of the applications child windows and make sure that
  they are ready to be closed, before closing the MDI Frame Window. */
Def close(self)
{ if closeAllMDIChildren(clientWindow)
  then close(self:ancestor);
  endif;
}!!

/* Process all MDI Frame Window specific command messages. */
Def command(self, wP, lP)
{ select
    case wP == IDM_CASCADE
    is Call SendMessage(getHWnd(clientWindow),
      messageID(#WM_MDICASCADE), 0, 0L);
    endCase
    case wP == IDM_TILE
    is Call SendMessage(getHWnd(clientWindow),
      messageID(#WM_MDITILE), 0, 0L);
    endCase
    case wP == IDM_ARRANGEICONS
    is Call SendMessage(getHWnd(clientWindow),
      messageID(#WM_MDIICONARRANGE), 0, 0L);
    endCase
  endSelect;
  execWindowProc(self, #WM_COMMAND, wP, lP);
}!!

/* Process a WM_SIZE message and then pass it on to the default window
  procedure so that Windows knows how to handle it.
  NOTE: This message must be passed on to the default frame procedure */
Def WM_SIZE(self, wP, lP)
{ WM_SIZE(self:ancestor, wP, lP);
  execWindowProc(self, #WM_SIZE, wP, lP);
}!!

/* Make sure that any messages not processed by an Actor method are passed
  on to the DefFrameProc in Windows, so that the frame window is managed
  properly. */
Def execWindowProc(self, windMsg, wP, lP)
{ ^Call DefFrameProc(getHWnd(self), getHWnd(clientWindow),
    messageID(windMsg), wP, lP);
}!!

/* Set up the Frame Window so that it creates an MDIClient to go with it.
  Also, dynamically create a "Windows" menu that is initialized with the
  "Cascade", "Tile", and "Arrange Icons" menu choices, for MDI Child
  management. */
Def init(self)
{ show(clientWindow := newMDIClient(MDIClient, self, 1000), SW_SHOW);
  disableMenus(self);
}!!
