home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / MDICLIEN.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  7.7 KB  |  319 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of class TMDIClient.  This defines the basic behavior
  6. //   of all MDI client windows.
  7. //----------------------------------------------------------------------------
  8. #pragma hdrignore SECTION
  9. #include <owl/owlpch.h>
  10. #include <owl/mdi.h>
  11.  
  12. // Define to work around here in the client, the 'creating MDI child maximized
  13. // corrupts the menu bar' bug 
  14. //
  15. #define MDIMAX_WORKAROUND
  16.  
  17. #if !defined(SECTION) || SECTION == 1
  18.  
  19. DEFINE_RESPONSE_TABLE1(TMDIClient, TWindow)
  20.   EV_COMMAND(CM_CREATECHILD, CmCreateChild),
  21.   EV_COMMAND(CM_TILECHILDREN, CmTileChildren),
  22.   EV_COMMAND(CM_TILECHILDRENHORIZ, CmTileChildrenHoriz),
  23.   EV_COMMAND(CM_CASCADECHILDREN, CmCascadeChildren),
  24.   EV_COMMAND(CM_ARRANGEICONS, CmArrangeIcons),
  25.   EV_COMMAND(CM_CLOSECHILDREN, CmCloseChildren),
  26.   EV_COMMAND_ENABLE(CM_TILECHILDREN, CmChildActionEnable),
  27.   EV_COMMAND_ENABLE(CM_TILECHILDRENHORIZ, CmChildActionEnable),
  28.   EV_COMMAND_ENABLE(CM_CASCADECHILDREN, CmChildActionEnable),
  29.   EV_COMMAND_ENABLE(CM_ARRANGEICONS, CmChildActionEnable),
  30.   EV_COMMAND_ENABLE(CM_CLOSECHILDREN, CmChildActionEnable),
  31.   EV_WM_MDICREATE,
  32.   EV_WM_MDIDESTROY,
  33. END_RESPONSE_TABLE;
  34.  
  35. //
  36. // constructor for a TMDIClient
  37. //
  38. // allocates space for the CLIENTCREATESTRUCT on the heap and sets
  39. // ClientAttr to point to this space
  40. //
  41. TMDIClient::TMDIClient(TModule* module)
  42. {
  43.   // Initialize virtual base, in case the derived-most used default ctor
  44.   //
  45.   TWindow::Init(0, 0, module);
  46.  
  47.   Attr.Id = IDW_MDICLIENT;
  48.  
  49.   // allow client area to grow scroll bars if necessary
  50.   //
  51.   Attr.Style |= MDIS_ALLCHILDSTYLES | WS_GROUP | WS_TABSTOP | WS_CLIPCHILDREN|
  52.                 WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL | WS_BORDER;
  53.   ClientAttr = new CLIENTCREATESTRUCT; // far
  54.   ClientAttr->hWindowMenu = 0;
  55.   ClientAttr->idFirstChild = IDW_FIRSTMDICHILD;
  56.   Attr.Param = (LPSTR)ClientAttr;
  57.   SetFlag(wfStreamTop);
  58. }
  59.  
  60. //
  61. // constructor for a TMDIClient which is being used in a DLL as an alias
  62. // for a non-OWL window. This ctor is generally not used by derived
  63. // classes
  64. //
  65. TMDIClient::TMDIClient(HWND hWnd, TModule* module)
  66. :
  67.   TWindow(hWnd, module)
  68. {
  69.   ClientAttr = 0;
  70.   SetFlag(wfStreamTop);
  71. }
  72.  
  73. //
  74. // frees the memory associated with ClientAttr
  75. //
  76. TMDIClient::~TMDIClient()
  77. {
  78.   delete ClientAttr;
  79. }
  80.  
  81. char far*
  82. TMDIClient::GetClassName()
  83. {
  84.   return "MDICLIENT";
  85. }
  86.  
  87. TMDIChild*
  88. TMDIClient::GetActiveMDIChild()
  89. {
  90.   HWND hWnd = (HWND)HandleMessage(WM_MDIGETACTIVE);
  91.  
  92.   return TYPESAFE_DOWNCAST(GetWindowPtr(hWnd),TMDIChild);
  93. }
  94.  
  95. void
  96. TMDIClient::ArrangeIcons()
  97. {
  98.   HandleMessage(WM_MDIICONARRANGE);
  99. }
  100.  
  101. void
  102. TMDIClient::CascadeChildren()
  103. {
  104.   HandleMessage(WM_MDICASCADE);
  105. }
  106.  
  107. void
  108. TMDIClient::TileChildren(int tile)
  109. {
  110.   HandleMessage(WM_MDITILE, tile);
  111. }
  112.  
  113. bool
  114. TMDIClient::PreProcessMsg(MSG& msg)
  115. {
  116.   if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
  117.     return TranslateMDISysAccel(HWindow, &msg);
  118.  
  119.   else
  120.     return false;
  121. }
  122.  
  123. bool
  124. TMDIClient::Create()
  125. {
  126.   TMDIFrame*  frame = TYPESAFE_DOWNCAST(Parent,TMDIFrame);
  127.   
  128.   CHECK(frame);
  129.  
  130.   ClientAttr->hWindowMenu = frame->FindChildMenu(frame->GetMenu());
  131.   return TWindow::Create();
  132. }
  133.  
  134. //
  135. // creates a valid new MDI child window after calling InitChild() to construct
  136. // a new MDI child window object
  137. //
  138. TWindow*
  139. TMDIClient::CreateChild()
  140. {
  141.   TMDIChild* child = InitChild();
  142.   CHECK(child);
  143.   if (child->Create())
  144.     return child;
  145.   return 0;
  146. }
  147.  
  148. TMDIChild*
  149. TMDIClient::InitChild()
  150. {
  151.   return new TMDIChild(*this);
  152. }
  153.  
  154. static bool
  155. CannotClose(TWindow* win, void*)
  156. {
  157.   return !win->CanClose();
  158. }
  159.  
  160. static void
  161. CloseChild(TWindow* win, void*)
  162. {
  163.   win->Destroy();
  164.   delete win;
  165. }
  166.  
  167. //
  168. // closes each MDI child, after calling the child's CanClose() method to
  169. // ensure that it is Ok to do so
  170. //
  171. // returns true if all children are closed(or there were no children),
  172. // false if any child can't be closed
  173. //
  174. bool
  175. TMDIClient::CloseChildren()
  176. {
  177.   if (!FirstThat(CannotClose)) {
  178.     ForEach(CloseChild);
  179.     return true;
  180.   }
  181.   return false;
  182. }
  183.  
  184. //
  185. // Handle WM_MDICREATE to perform actual creation of MDI children.
  186. //
  187. LRESULT
  188. TMDIClient::EvMDICreate(MDICREATESTRUCT far& createStruct)
  189. {
  190.   // Fill in default child window styles if they request style 0 since this
  191.   // client by default has set allchildstyles
  192.   //
  193.   if ((Attr.Style&MDIS_ALLCHILDSTYLES) && !createStruct.style)
  194.     createStruct.style =
  195.                WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
  196.                WS_SYSMENU | WS_CAPTION | WS_THICKFRAME |
  197.                WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
  198.  
  199.   // Work around a Windows MDI bug w/ bad menus if MDI child is created
  200.   // maximized, by hiding child now & maximizing later
  201.   //
  202. #if defined(MDIMAX_WORKAROUND)
  203.   uint32 origStyle = createStruct.style;
  204.   if (createStruct.style & WS_MAXIMIZE)
  205.     createStruct.style &= ~(WS_MAXIMIZE | WS_VISIBLE);
  206. #endif
  207.  
  208.   LRESULT result = DefaultProcessing();
  209.  
  210.   // Finish up maximized MDI child workaround
  211.   //
  212. #if defined(MDIMAX_WORKAROUND)
  213.   if (HWND(result) && (origStyle & WS_MAXIMIZE)) {
  214.     HandleMessage(WM_MDIMAXIMIZE, WPARAM(result));
  215. #if defined(BI_PLAT_WIN32)
  216.     HandleMessage(WM_MDIREFRESHMENU);
  217. #else
  218.     HandleMessage(WM_MDISETMENU, true);
  219. #endif
  220.   }
  221. #endif
  222.  
  223.   return result;
  224. }
  225.  
  226. //
  227. // When an MDI child is destroyed while other children are hidden or disabled,
  228. // the Windows MDI child management gets confused causing subsequent failure.
  229. // To prevent this, we temporarily unhide and enable siblings during destroy.
  230. //
  231. static void sUnHide(TWindow* win, void* hWnd)
  232. {
  233.   if (*win == (HWND)hWnd)
  234.     return;
  235.   if (!win->IsWindowVisible()) {
  236.     win->SetWindowPos(0, 0, 0, 0, 0,
  237.                       SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOZORDER|
  238.                       SWP_NOACTIVATE|SWP_NOREDRAW);
  239.     win->SetFlag(wfUnHidden);
  240.   }
  241.   if (!win->IsWindowEnabled()) {
  242.     win->EnableWindow(true);
  243.     win->SetFlag(wfUnDisabled);
  244.   }
  245. }
  246.  
  247. static void sReHide(TWindow* win, void*)
  248. {
  249.   if (!*win)
  250.     return;
  251.   if (win->IsFlagSet(wfUnHidden)) {
  252.     win->ClearFlag(wfUnHidden);
  253.     win->ShowWindow(SW_HIDE);
  254.   }
  255.   if (win->IsFlagSet(wfUnDisabled)) {
  256.     win->ClearFlag(wfUnDisabled);
  257.     win->EnableWindow(false);
  258.   }
  259. }
  260.  
  261. void
  262. TMDIClient::EvMDIDestroy(HWND hWnd)
  263. {
  264.   ForEach(sUnHide, (void*)hWnd);
  265.   DefaultProcessing();
  266.   ForEach(sReHide);
  267. #if defined(BI_PLAT_WIN32)
  268.   HandleMessage(WM_MDIREFRESHMENU);
  269. #else
  270.   HandleMessage(WM_MDISETMENU, true);
  271. #endif
  272. }
  273.  
  274. //
  275. // Enables any of the child action menu items if any MDI children exit
  276. //
  277. void
  278. TMDIClient::CmChildActionEnable(TCommandEnabler& commandEnabler)
  279. {
  280.   commandEnabler.Enable(GetFirstChild() != 0);
  281. }
  282.  
  283.  
  284. #endif
  285. #if !defined(SECTION) || SECTION == 2
  286.  
  287. IMPLEMENT_STREAMABLE1(TMDIClient, TWindow);
  288.  
  289. //
  290. // reads an instance of TMDIClient from the passed ipstream
  291. //
  292. void*
  293. TMDIClient::Streamer::Read(ipstream& is, uint32 /*version*/) const
  294. {
  295.   ReadBaseObject((TWindow*)GetObject(), is);
  296.  
  297.   GetObject()->ClientAttr = new CLIENTCREATESTRUCT;  //far
  298.  
  299.   uint idFirstChild;  // Need temp for near data model since ClientAttr is far
  300.   is >> idFirstChild;
  301.   GetObject()->ClientAttr->idFirstChild = idFirstChild;
  302.   GetObject()->ClientAttr->hWindowMenu = (HMENU) 0;
  303.   GetObject()->Attr.Param = (LPSTR)GetObject()->ClientAttr;
  304.  
  305.   return GetObject();
  306. }
  307.  
  308. //
  309. // writes the TMDIClient to the passed opstream
  310. //
  311. void
  312. TMDIClient::Streamer::Write(opstream& os) const
  313. {
  314.   WriteBaseObject((TWindow*)GetObject(), os);
  315.   os << GetObject()->ClientAttr->idFirstChild;
  316. }
  317.  
  318. #endif
  319.