home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / FRAMEWIN.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  22.8 KB  |  919 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   source\owl\framewin.cpp
  4. //   Implementation of class TFrameWindow
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\framewin.h>
  9. #include <owl\applicat.h>
  10. #include <owl\menu.h>
  11.  
  12. #if !defined(SECTION) || SECTION == 1
  13.  
  14. DEFINE_RESPONSE_TABLE1(TFrameWindow, TWindow)
  15.   EV_WM_PAINT,
  16.   EV_WM_ERASEBKGND,
  17.   EV_WM_QUERYDRAGICON,
  18.   EV_WM_INITMENUPOPUP,
  19.   EV_WM_SETFOCUS,
  20.   EV_WM_SIZE,
  21.   EV_WM_PARENTNOTIFY,
  22. END_RESPONSE_TABLE;
  23.  
  24. //
  25. // command enabler for menu items
  26. //
  27. class _OWLCLASS TMenuItemEnabler : public TCommandEnabler {
  28.   public:
  29.     TMenuItemEnabler(HMENU hMenu, UINT id, HWND hWndReceiver, int position)
  30.       : TCommandEnabler(id, hWndReceiver) {HMenu = hMenu; Position = position;}
  31.  
  32.     //
  33.     // override member functions of TCommandEnabler
  34.     //
  35.     void  Enable(BOOL);
  36.     void  SetText(LPCSTR);
  37.     void  SetCheck(int);
  38.  
  39.   protected:
  40.     HMENU  HMenu;
  41.     int    Position;
  42. };
  43.  
  44. void
  45. TMenuItemEnabler::Enable(BOOL enable)
  46. {
  47.   TCommandEnabler::Enable(enable);
  48.   ::EnableMenuItem(HMenu, Position,
  49.                    MF_BYPOSITION | (enable ? MF_ENABLED : MF_GRAYED));
  50. }
  51.  
  52. void
  53. TMenuItemEnabler::SetText(LPCSTR str)
  54. {
  55.   ::ModifyMenu(HMenu, Position, MF_BYPOSITION | MF_STRING, Id, str);
  56. }
  57.  
  58. void
  59. TMenuItemEnabler::SetCheck(int state)
  60. {
  61.   ::CheckMenuItem(HMenu, Position,
  62.                   MF_BYPOSITION | (state == Checked ? MF_CHECKED : MF_UNCHECKED));
  63. }
  64.  
  65. //----------------------------------------------------------------------------
  66.  
  67. //
  68. // constructor for a TFrameWindow
  69. //
  70. TFrameWindow::TFrameWindow(TWindow*        parent,
  71.                            const char far* title,
  72.                            TWindow*        clientWnd,
  73.                            BOOL            shrinkToClient,
  74.                            TModule*        module)
  75. {
  76.   //
  77.   // Initialize virtual base, in case the derived-most used default ctor
  78.   //
  79.   TWindow::Init(parent, title, module);
  80.  
  81.  
  82.   IconResId = 0;  // remember that we still need to init
  83.   Init(clientWnd, shrinkToClient);
  84. }
  85.  
  86. //
  87. // constructor for a TFrameWindow. This ctor is generally not used by derived
  88. // classes
  89. //
  90. TFrameWindow::TFrameWindow(HWND hWnd, TModule* module)
  91.   : TWindow(hWnd, module)
  92. {
  93.   Init(0);
  94. }
  95.  
  96. //
  97. // Protected constructor for use by immediate virtually derived classes.
  98. // Immediate derivitives must call Init() before constructions are done.
  99. //
  100. TFrameWindow::TFrameWindow()
  101. {
  102.   IconResId = 0;  // remember that we still need to init
  103.                   // (may want to use a specific member flag)
  104. }
  105.  
  106. //
  107. // Normal initialization of a default constructed TFrameWindow. Is ignored
  108. // if called more than once.
  109. //
  110. void
  111. TFrameWindow::Init(TWindow* clientWnd, BOOL shrinkToClient)
  112. {
  113.   if (!IconResId) {
  114.     Attr.Style = WS_OVERLAPPEDWINDOW;
  115.     Attr.X = Attr.W = CW_USEDEFAULT;
  116.  
  117.     if (clientWnd)
  118.       Attr.Style |= WS_CLIPCHILDREN;
  119.  
  120.     if (shrinkToClient)
  121.       SetFlag(wfShrinkToClient);
  122.  
  123.     Init(clientWnd);
  124.   }
  125. }
  126.  
  127. //
  128. // Private initializer does a bulk of the common frame window initialization
  129. //
  130. void
  131. TFrameWindow::Init(TWindow* clientWnd)
  132. {
  133.   HWndRestoreFocus = 0;
  134.   KeyboardHandling = FALSE;
  135.   ClientWnd = clientWnd;
  136.  
  137.   MenuDescr = 0;
  138.   MergeModule = 0;
  139.  
  140.   IconModule = ::Module;
  141.   IconResId = IDI_OWLAPP;
  142.  
  143.   MinimizedPos = TPoint(-1,-1);  // Windows convention for never minimized
  144.  
  145.   if (ClientWnd) {
  146.     ClientWnd->SetParent(this);
  147.     ClientWnd->EnableAutoCreate();  // in case client is a dialog
  148.   }
  149. }
  150.  
  151. TFrameWindow::~TFrameWindow()
  152. {
  153.   delete MenuDescr;
  154. }
  155.  
  156. void
  157. TFrameWindow::EvInitMenuPopup(HMENU hPopupMenu, UINT /*index*/, BOOL sysMenu)
  158. {
  159.   if (!sysMenu && hPopupMenu) {
  160.     int  count = ::GetMenuItemCount(hPopupMenu);
  161.  
  162.     for (int pos = 0; pos < count; pos++) {
  163.       UINT  id = ::GetMenuItemID(hPopupMenu, pos);
  164.  
  165.       //
  166.       // ignore sub-menus and separators
  167.       //
  168.       if (id == 0 || id == (UINT)-1)
  169.         continue;
  170.  
  171.       //
  172.       // Skip the rest if it is the mdi child list, or system commands
  173.       //
  174.       if (id == IDW_FIRSTMDICHILD || id > 0xF000)
  175.         break;
  176.  
  177.       EvCommandEnable(TMenuItemEnabler(hPopupMenu, id, HWindow, pos));
  178.     }
  179.   }
  180. }
  181.  
  182. static void
  183. DoIdleAction(TWindow* win, void* idleCount)
  184. {
  185.   win->IdleAction(*(long*)idleCount);
  186. }
  187.  
  188. //
  189. // TFrameWindow processes idle action occurs once per block of messages
  190. //
  191. BOOL
  192. TFrameWindow::IdleAction(long idleCount)
  193. {
  194.   if (idleCount == 0) {
  195.     //
  196.     // do command enabling for the menu bar if this is the active task
  197.     //
  198.   #if defined(__WIN32__)
  199.     if (GetFocus())
  200.   #else
  201.     HWND focus = GetFocus();
  202.     if (focus && ::GetWindowTask(focus) == GetCurrentTask())
  203.   #endif
  204.       HandleMessage(WM_INITMENUPOPUP, WPARAM(::GetMenu(HWindow)));
  205.  
  206.     //
  207.     // give child windows an opportunity to do any idle processing
  208.     //
  209.     ForEach(DoIdleAction, &idleCount);
  210.   }
  211.   return FALSE;  // we don't need any more time for now
  212. }
  213.  
  214. LRESULT
  215. TFrameWindow::EvCommand(UINT id, HWND hWndCtl, UINT notifyCode)
  216. {
  217.   //
  218.   // extra processing for commands: send the command down the command chain
  219.   //
  220.   if (hWndCtl == 0) {
  221.     HWND  hFocus = ::GetFocus();
  222.  
  223.     if (IsChild(hFocus))
  224.       while (hFocus != HWindow) {
  225.         TWindow*  focusWindow = GetWindowPtr(hFocus);
  226.  
  227.         if (focusWindow)
  228.           return focusWindow->EvCommand(id, hWndCtl, notifyCode);
  229.  
  230.         hFocus = ::GetParent(hFocus);
  231.       }
  232.   }
  233.  
  234.   return TWindow::EvCommand(id, hWndCtl, notifyCode);
  235. }
  236.  
  237. void
  238. TFrameWindow::EvCommandEnable(TCommandEnabler& commandEnabler)
  239. {
  240.   //
  241.   // Dont process for windows out of our window tree (esp. other apps)
  242.   //
  243.   HWND  hFocus = ::GetFocus();
  244.   if (hFocus != HWindow && !IsChild(hFocus))
  245.     return;
  246.  
  247.   //
  248.   // extra processing for commands: send the command down the command chain
  249.   // if we are the original receiver
  250.   //
  251.   if (commandEnabler.IsReceiver(*this)) {
  252.     while (hFocus != HWindow) {
  253.       TWindow*  focusWindow = GetWindowPtr(hFocus);
  254.  
  255.       if (focusWindow) {
  256.         focusWindow->EvCommandEnable(commandEnabler);
  257.  
  258.         if (commandEnabler.GetHandled())
  259.           return;
  260.       }
  261.  
  262.       hFocus = ::GetParent(hFocus);
  263.     }
  264.   }
  265.  
  266.   TWindow::EvCommandEnable(commandEnabler);
  267.  
  268.   if (commandEnabler.IsReceiver(*this) && !commandEnabler.GetHandled()) {
  269.     //
  270.     // no one explicitly enabled/disabled the command
  271.     //
  272.     // now run up the command chain checking for if any one is going to
  273.     // handle the command; if not then disable it...
  274.     //
  275.     BOOL        enable = FALSE;
  276.     TEventInfo  eventInfo(0, commandEnabler.Id);
  277.  
  278.     hFocus = ::GetFocus();
  279.     while (TRUE) {
  280.       TWindow*  focusWindow = GetWindowPtr(hFocus);
  281.  
  282.       if (focusWindow && focusWindow->Find(eventInfo)) {
  283.         enable = TRUE;  // will be handled
  284.         break;
  285.       }
  286.  
  287.       if (hFocus == HWindow)
  288.         break;
  289.  
  290.       hFocus = ::GetParent(hFocus);
  291.     }
  292.  
  293.     if (!enable) {
  294.       //
  295.       // check if the app wants to handle it
  296.       //
  297.       TEventInfo enableInfo(WM_COMMAND_ENABLE, commandEnabler.Id);
  298.       TApplication* app = GetApplication();
  299.       if (app->Find(enableInfo)) {
  300.         app->Dispatch(enableInfo, 0, (LPARAM)&commandEnabler);
  301.         if (commandEnabler.GetHandled())
  302.           return;
  303.       }
  304.       enable = GetApplication()->Find(eventInfo);
  305.     }
  306.  
  307.     commandEnabler.Enable(enable);
  308.   }
  309. }
  310.  
  311. BOOL
  312. TFrameWindow::PreProcessMsg(MSG& msg)
  313. {
  314.   if (TWindow::PreProcessMsg(msg))
  315.     return TRUE;  // process accelerators
  316.  
  317.   else if (KeyboardHandling) {
  318.     HWND parent = ::GetParent(msg.hwnd);
  319.  
  320.     return parent && ::IsDialogMessage(parent, &msg);
  321.   }
  322.  
  323.   return FALSE;
  324. }
  325.  
  326. BOOL
  327. TFrameWindow::SetMenu(HMENU hMenu)
  328. {
  329.   return TWindow::SetMenu(hMenu);
  330. }
  331.  
  332. //
  333. // returns TRUE if successful; FALSE otherwise
  334. //
  335. // NOTE: this function is declared virtual, but may be called from constructors
  336. // of classes derived from TFrameWindow. in C++, virtual functions called from
  337. // constructors are called as though they are non-virtual
  338. //
  339. BOOL
  340. TFrameWindow::AssignMenu(TResId menuResId)
  341. {
  342.   if (menuResId != Attr.Menu) {
  343.     if (Attr.Menu.IsString())
  344.       delete (char far*)Attr.Menu;
  345.  
  346.     Attr.Menu = menuResId.IsString() ? strnewdup(menuResId) : (char far*)menuResId;
  347.   }
  348.  
  349.   //
  350.   // if the window has been created then load and set the new menu and destroy
  351.   // the old menu
  352.   //
  353.   if (!HWindow)
  354.     return TRUE;
  355.  
  356.   HMENU oldMenu = GetMenu();
  357.   HMENU newMenu = GetModule()->LoadMenu(Attr.Menu);
  358.  
  359.   if (IsFlagSet(wfMainWindow))
  360.     GetApplication()->PreProcessMenu(newMenu);
  361.  
  362.   if (!SetMenu(newMenu))
  363.     return FALSE;
  364.  
  365.   if (oldMenu)
  366.     ::DestroyMenu(oldMenu);
  367.  
  368.   return TRUE;
  369. }
  370.  
  371. //
  372. //
  373. //
  374. BOOL
  375. TFrameWindow::SetIcon(TModule* module, TResId resId)
  376. {
  377.   IconModule = module;
  378.   IconResId = resId;
  379.   return TRUE;
  380. }
  381.  
  382. TWindow*
  383. TFrameWindow::GetClientWindow()
  384. {
  385.   return ClientWnd;
  386. }
  387.  
  388. //
  389. // Removes the current client (if any) and sets a new one.
  390. // Assumes clientWnd was parented to us.
  391. //
  392. TWindow*
  393. TFrameWindow::SetClientWindow(TWindow* clientWnd)
  394. {
  395.   TWindow* oldClientWnd = ClientWnd;
  396.   HWND oldHWnd = oldClientWnd ? oldClientWnd->HWindow : (HWND)0;
  397.   RemoveChild(ClientWnd);
  398.  
  399.   if (HWndRestoreFocus == oldHWnd)
  400.     HWndRestoreFocus = 0;
  401.  
  402.   ClientWnd = clientWnd;
  403.  
  404.   if (ClientWnd) {
  405.     ClientWnd->SetParent(this);
  406.     if (!ClientWnd->HWindow)
  407.       ClientWnd->Create();
  408.     ClientWnd->Show(SW_NORMAL);
  409.     ResizeClientWindow();
  410.   }
  411.   if (ClientWnd && ClientWnd->HWindow)
  412.     ClientWnd->SetFocus();
  413.   else
  414.     SetFocus();
  415.  
  416.   return oldClientWnd;
  417. }
  418.  
  419. BOOL
  420. TFrameWindow::SetDocTitle(LPCSTR docname, int index)
  421. {
  422.   if (index == 0)
  423.     SetCaption(docname);
  424.   else if (index > 0) {
  425.     char buf[280];
  426.     wsprintf(buf, "%s:%d", docname, index);
  427.     SetCaption(buf);
  428.   } // else if index is negative, simply acknowledge that title will display
  429.   return TRUE;
  430. }
  431.  
  432. //
  433. // Obtain the real windows application icon. The IDI_APPLICATION icon is an
  434. // ugly black & white box, but when a class is registered with this icon it
  435. // gets substituted with a better windows icon. Worse case we end up with the
  436. // ugly box icon.
  437. //
  438. static HICON
  439. getAppIcon()
  440. {
  441.   static HICON hRealAppIcon = 0;
  442.   if (!hRealAppIcon) {
  443.     WNDCLASS wndClass;
  444.     static char className[] = "OwlIconSnarfer";
  445.     memset(&wndClass, 0, sizeof wndClass);
  446.     wndClass.hInstance = *::Module;
  447.     wndClass.hIcon = ::LoadIcon(0, IDI_APPLICATION);
  448.     wndClass.lpszClassName = className;
  449.     wndClass.lpfnWndProc = ::DefWindowProc;
  450.     ::RegisterClass(&wndClass);
  451.     ::GetClassInfo(*::Module, className, &wndClass);
  452.     hRealAppIcon = wndClass.hIcon;
  453.     ::UnregisterClass(className, *::Module);
  454.   }
  455.   return hRealAppIcon ? hRealAppIcon : ::LoadIcon(0, IDI_APPLICATION);
  456. }  
  457.  
  458. //
  459. // response method for an incoming WM_PAINT message
  460. //
  461. // if iconic, and an icon has been defined then draws that,
  462. // or if iconic & there is a client window, then calls its paint function.
  463. //
  464. // if not iconic, forwards to TWindow for normal paint processing
  465. //
  466. void
  467. TFrameWindow::EvPaint()
  468. {
  469.   if (IsIconic() && (IconResId || ClientWnd)) {
  470.     TPaintDC  dc(HWindow);
  471.  
  472.     if (IconResId) {
  473.       HINSTANCE hInstance = IconModule ? HINSTANCE(*IconModule) : HINSTANCE(0);
  474.       HICON hIcon = ::LoadIcon(hInstance, IconResId);
  475.       ::DrawIcon(dc, 0, 0, hIcon ? hIcon : getAppIcon());
  476.  
  477.     } else
  478.         ClientWnd->Paint(dc, dc.Ps.fErase, *(TRect*)&dc.Ps.rcPaint);
  479.  
  480.   } else
  481.     TWindow::EvPaint();
  482. }
  483.  
  484. //
  485. //
  486. //
  487. BOOL
  488. TFrameWindow::EvEraseBkgnd(HDC hDC)
  489. {
  490.   if (IsIconic()) {
  491.     if (!IconResId && ClientWnd)
  492.       return (BOOL)ClientWnd->HandleMessage(WM_ERASEBKGND, WPARAM(hDC));
  493.  
  494.     HandleMessage(WM_ICONERASEBKGND, WPARAM(hDC));
  495.     return TRUE;
  496.  
  497.   } else
  498.     return (BOOL)DefaultProcessing();
  499. }
  500.  
  501. //
  502. //
  503. //
  504. HANDLE
  505. TFrameWindow::EvQueryDragIcon()
  506. {
  507.   if (IconResId) {
  508.     HINSTANCE hInstance = IconModule ? HINSTANCE(*IconModule) : HINSTANCE(0);
  509.     HICON hIcon = ::LoadIcon(hInstance, IconResId);
  510.     return hIcon ? hIcon : getAppIcon();
  511.  
  512.   } else
  513.     return (HANDLE)DefaultProcessing();
  514. }
  515.  
  516. static inline BOOL
  517. IsEnabledVisibleChild(long style)
  518. {
  519.   return (style & (WS_CHILD | WS_VISIBLE | WS_DISABLED)) == (WS_CHILD | WS_VISIBLE);
  520. }
  521.  
  522. static
  523. TWindow*
  524. SearchForChildWithTab(TWindow* win)
  525. {
  526.   TWindow*  firstChild = win->GetFirstChild();
  527.  
  528.   if (firstChild) {
  529.     TWindow*  child = firstChild;
  530.  
  531.     do {
  532.       if (child->HWindow) {
  533.         long  style = child->GetWindowLong(GWL_STYLE);
  534.  
  535.         if (IsEnabledVisibleChild(style)) {
  536.           if (style & WS_TABSTOP)
  537.             return child;
  538.  
  539.           else {
  540.             TWindow*  result = SearchForChildWithTab(child);
  541.             if (result)
  542.               return result;
  543.           }
  544.         }
  545.       }
  546.       child = child->Next();
  547.     } while (child != firstChild);
  548.   }
  549.  
  550.   return 0;
  551. }
  552.  
  553. static BOOL
  554. EnabledVisibleChild(TWindow* win, void*)
  555. {
  556.   return win->HWindow ? IsEnabledVisibleChild(win->GetWindowLong(GWL_STYLE)) :
  557.                         FALSE;
  558. }
  559.  
  560. //
  561. // if the receiver doesn't have any children then returns 0. otherwise
  562. // we search for the first child with WS_TABSTOP; if no child has WS_TABSTOP
  563. // then we return the first enabled visible child
  564. //
  565. // does a depth-first search of nested child windows
  566. //
  567. // NOTE: we stop at the first child with WS_TABSTOP and do not search its
  568. //       children...
  569. //
  570. TWindow*
  571. TFrameWindow::FirstChildWithTab()
  572. {
  573.   TWindow*  win = SearchForChildWithTab(this);
  574.  
  575.   return win ? win : FirstThat(EnabledVisibleChild);
  576. }
  577.  
  578. //
  579. // Respond to a request to hold on to the handle of a child window that is
  580. // losing focus, so that we can restore it again later.
  581. //
  582. // return true if caller can stop searching for a window to hold its handle.
  583. //
  584. BOOL
  585. TFrameWindow::HoldFocusHWnd(HWND hWndLose, HWND hWndGain)
  586. {
  587.   if (IsChild(hWndLose)) {
  588.     if (!hWndGain || !IsChild(hWndGain))
  589.       HWndRestoreFocus = hWndLose;
  590.     return TRUE;
  591.   }
  592.   return hWndLose == HWindow;
  593. }
  594.  
  595. //
  596. //
  597. //
  598. void
  599. TFrameWindow::EvSetFocus(HWND hWndLostFocus)
  600. {
  601.   TWindow::EvSetFocus(hWndLostFocus);
  602.  
  603.   if (HWndRestoreFocus) {
  604.     //
  605.     // The child could have been destroyed at this point; ensure focus
  606.     // doesn't get set to a deleted window when backing out KILLFOCUSes
  607.     // during a window takedown.
  608.     //
  609.     if (::IsWindow(HWndRestoreFocus))
  610.       ::SetFocus(HWndRestoreFocus);
  611.  
  612.     HWndRestoreFocus = 0;
  613.  
  614.   } else {
  615.     TWindow*  win = FirstChildWithTab();
  616.  
  617.     if (win && win->HWindow != hWndLostFocus)
  618.       win->SetFocus();
  619.   }
  620. }
  621.  
  622. //
  623. // Close this window if the client is destroyed, or resize frame if indicated
  624. //
  625. void
  626. TFrameWindow::EvParentNotify(UINT event,
  627.                              UINT childHandleOrX, UINT /*childIDOrY*/)
  628. {
  629.   if (event == WM_DESTROY) {
  630.     if (ClientWnd && ClientWnd->HWindow == HWND(childHandleOrX))
  631.       PostMessage(WM_CLOSE);  // using ShutdownWindow() has side effects
  632.  
  633.   } else if (event == WM_SIZE) {
  634.     if (IsFlagSet(wfShrinkToClient)
  635.     && ClientWnd
  636.     && ClientWnd->HWindow == HWND(childHandleOrX)
  637.     && !IsIconic())
  638.       ResizeClientWindow();
  639.   }
  640. }
  641.  
  642. //
  643. // Resize & reposition the client window to fit in this frames client area
  644. // or resize the frame to fit on the client's client area if wfShrinkToClient
  645. // Return TRUE if a client was actualy resized.
  646. // Adjust clients styles & make sure they get set.
  647. //
  648. BOOL
  649. TFrameWindow::ResizeClientWindow(BOOL redraw)
  650. {
  651.   if (!ClientWnd)
  652.     return FALSE;
  653.   if (ClientWnd->IsFlagSet(wfShrinkToClient))// prevent recursion during resize  
  654.     return TRUE;               // ignore calls from EvParentNotify and EvSize
  655.  
  656.   BOOL clientResized = FALSE;
  657.   ClientWnd->SetFlag(wfShrinkToClient);  // disable notifications while resizing
  658.  
  659.   TSize frameSize = GetClientRect().Size();
  660.   TSize childSize = ClientWnd->GetWindowRect().Size();
  661.   //
  662.   // first time through, strip client window of borders and caption
  663.   // and set style bits to be a compatible child window
  664.   // if shrink-to-client, then must measure the client size first
  665.   // if the client has scrolls bars, we must hide to obtain the correct size
  666.   //
  667.   if (ClientWnd->Attr.Style & (WS_BORDER | WS_DLGFRAME)) {
  668.     if (IsFlagSet(wfShrinkToClient)) {
  669.       TSize tstSize = ClientWnd->GetClientRect().Size();
  670.       ClientWnd->ShowScrollBar(SB_BOTH, FALSE);
  671.       childSize = ClientWnd->GetClientRect().Size();
  672.       if (childSize != tstSize) {
  673.         int restore = SB_BOTH;
  674.         if (childSize.cx == tstSize.cx)
  675.           restore = SB_HORZ;
  676.         if (childSize.cy == tstSize.cy)
  677.           restore = SB_VERT;
  678.         ClientWnd->ShowScrollBar(restore, TRUE);
  679.       }
  680.     } 
  681.     ClientWnd->Attr.Style &= ~(WS_CAPTION|WS_BORDER|WS_DLGFRAME|
  682.                                WS_SYSMENU|WS_THICKFRAME|WS_POPUP|
  683.                                WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
  684.     ClientWnd->Attr.Style |= WS_CHILD;
  685.     ClientWnd->Attr.ExStyle &= ~(WS_EX_DLGMODALFRAME);
  686.     ClientWnd->SetWindowLong(GWL_STYLE, ClientWnd->Attr.Style);
  687.     ClientWnd->SetWindowLong(GWL_EXSTYLE, ClientWnd->Attr.ExStyle);
  688.   }
  689.   if (childSize != frameSize) {
  690.     if (IsFlagSet(wfShrinkToClient)) {
  691.       TRect outside = GetWindowRect();
  692.       TPoint outsideOrg(0, 0);
  693.       if (Parent) {
  694.         Parent->ClientToScreen(outsideOrg); // adjust our rect by our parent's
  695.       }
  696.       TSize border = outside.Size() - frameSize;
  697.       MoveWindow(outside.left - outsideOrg.x, outside.top - outsideOrg.y,
  698.                  childSize.cx + border.cx, childSize.cy + border.cy, redraw);
  699.       frameSize = childSize;     // must move client, will not cause an EvSize
  700.     } else {
  701.       clientResized = TRUE;
  702.     }
  703.   }
  704.   // if frame is sizeable, turn off flag so that user can then resize
  705.   // after initial setup
  706.   if (Attr.Style & WS_THICKFRAME)
  707.     ClearFlag(wfShrinkToClient);
  708.  
  709.   ClientWnd->MoveWindow(0, 0, frameSize.cx, frameSize.cy, redraw);
  710.   ClientWnd->ClearFlag(wfShrinkToClient);
  711.   return clientResized;
  712. }
  713.  
  714. //
  715. // called following a successful association between an MS-Windows interface
  716. // element and a TWindow
  717. //
  718. void
  719. TFrameWindow::SetupWindow()
  720. {
  721.   //
  722.   // create windows in child list (this includes the client window)
  723.   //
  724.   TWindow::SetupWindow();
  725.  
  726.   ResizeClientWindow();
  727.  
  728.   if (MinimizedPos != TPoint(-1,-1)) {
  729.     WINDOWPLACEMENT windata;
  730.     windata.length = sizeof(WINDOWPLACEMENT);
  731.     GetWindowPlacement(&windata);
  732.     windata.flags = WPF_SETMINPOSITION;
  733.     windata.showCmd = SW_SHOWNA;
  734.     windata.ptMinPosition = MinimizedPos;
  735.     SetWindowPlacement(&windata);
  736.   }
  737.   //
  738.   // if SetMenuDescr() called before window created, update the menu
  739.   //
  740.   if (IsFlagSet(wfMainWindow) && MenuDescr && MenuDescr->Id != Attr.Menu)
  741.     AssignMenu(MenuDescr->Id);
  742.  
  743.   //
  744.   // if we haven't set HWndRestoreFocus then pick the first child with tabstop
  745.   //
  746.   if (!HWndRestoreFocus) {
  747.     TWindow*  win = FirstChildWithTab();
  748.  
  749.     HWndRestoreFocus = win ? win->HWindow : HWindow;
  750.   }
  751. }
  752.  
  753. //
  754. // response method for an incoming WM_SIZE message
  755. //
  756. // if not minimizing resizes the client window to be the same size as the
  757. // client rectangle,
  758. // if no WM_SIZE sent, forwards WM_SIZE message to client so it can recalc.
  759. //
  760. void
  761. TFrameWindow::EvSize(UINT sizeType, TSize& size)
  762. {
  763.   TWindow::EvSize(sizeType, size);
  764.  
  765.   if (ClientWnd) {
  766.     BOOL sizeSent = FALSE;
  767.     if (sizeType != SIZE_MINIMIZED) {
  768.       sizeSent = ResizeClientWindow();
  769.       size = ClientWnd->GetClientRect().Size();
  770.     }
  771.     if (!sizeSent)
  772.       ClientWnd->ForwardMessage();
  773.   }
  774. }
  775.  
  776. #endif
  777. #if !defined(SECTION) || SECTION == 2
  778.  
  779. static void
  780. DeleteSubMenus(TMenu& fromMenu, int count)
  781. {
  782.   for (int j = 0; j < count; j++)
  783.     fromMenu.DeleteMenu(0, MF_BYPOSITION);
  784. }
  785.  
  786. //
  787. //
  788. //
  789. static void
  790. MoveSubMenus(TMenu& fromMenu, TMenu& toMenu, int count)
  791. {
  792.   char   str[256];
  793.   for (int j = 0; j < count; j++) {
  794.     fromMenu.GetMenuString(0, str, sizeof(str), MF_BYPOSITION);
  795.     HMENU subMenu = fromMenu.GetSubMenu(0);
  796.     if (subMenu)
  797.       toMenu.AppendMenu(MF_POPUP, UINT(subMenu), str);
  798.     else
  799.       toMenu.AppendMenu(0, fromMenu.GetMenuItemID(0), str);
  800.     fromMenu.RemoveMenu(0, MF_BYPOSITION);
  801.   }
  802. }
  803.  
  804. //
  805. //
  806. //
  807. void
  808. TFrameWindow::SetMenuDescr(const TMenuDescr& menuDescr)
  809. {
  810.   delete MenuDescr;
  811.   MenuDescr = new TMenuDescr(menuDescr);
  812.   if (IsFlagSet(wfMainWindow))
  813.     AssignMenu(MenuDescr->Id);
  814. }
  815.  
  816. BOOL
  817. TFrameWindow::MergeMenu(const TMenuDescr& childMenuDescr)
  818. {
  819.   if (!MenuDescr || !HWindow)
  820.     return FALSE;
  821.  
  822.   MergeModule = childMenuDescr.Module;
  823.   TMenu  oldMenu(*this, NoAutoDelete);
  824.   TMenu  newMenu(NoAutoDelete);
  825.   TMenu  resMenu(*MenuDescr->Module, MenuDescr->Id);
  826.   TMenu  childMenu(*MergeModule, childMenuDescr.Id);
  827.  
  828.   for (int i = 0; i < TMenuDescr::NumGroups; i++) {
  829.     if (childMenuDescr.GroupCount[i] != 0) {
  830.       MoveSubMenus(childMenu, newMenu, childMenuDescr.GroupCount[i]);
  831.       DeleteSubMenus(resMenu, MenuDescr->GroupCount[i]);
  832.     } else {
  833.       MoveSubMenus(resMenu, newMenu, MenuDescr->GroupCount[i]);
  834.     }
  835.   }
  836.   if (IsFlagSet(wfMainWindow))
  837.     GetApplication()->PreProcessMenu(newMenu);
  838.  
  839.   if (!SetMenu(newMenu)) {
  840.     ::DestroyMenu(newMenu);
  841.     return FALSE;
  842.   }
  843.  
  844.   ::DestroyMenu(oldMenu);
  845.   return TRUE;
  846. }
  847.  
  848. BOOL
  849. TFrameWindow::RestoreMenu()
  850. {
  851.   if (!MenuDescr)
  852.     return FALSE;
  853.  
  854.   AssignMenu(Attr.Menu);
  855.   MergeModule = 0;
  856.   return TRUE;
  857. }
  858.  
  859. #endif
  860. #if !defined(SECTION) || SECTION == 3
  861.  
  862. IMPLEMENT_STREAMABLE1(TFrameWindow, TWindow);
  863.  
  864. void*
  865. TFrameWindow::Streamer::Read(ipstream& is, uint32 /*version*/) const
  866. {
  867.   TFrameWindow* o = GetObject();
  868.   ReadVirtualBase((TWindow*)o, is);
  869.   if (o->IsFlagSet(wfMainWindow))
  870.     return o;
  871.  
  872.   is >> o->ClientWnd;
  873.   is >> o->KeyboardHandling;
  874.   o->HWndRestoreFocus = 0;
  875.  
  876.   BOOL hasMenuDescr = is.readByte();
  877.   if (hasMenuDescr) {
  878.     o->MenuDescr = new TMenuDescr;
  879.     is >> *o->MenuDescr;
  880.   } else
  881.     o->MenuDescr = 0;
  882.  
  883.   is >> o->IconModule;
  884.   is >> o->IconResId;
  885.   is >> o->MergeModule;
  886.   is >> o->MinimizedPos;
  887.  
  888.   return o;
  889. }
  890.  
  891. //
  892. // writes data of the TFrameWindow to the passed opstream
  893. //
  894. void
  895. TFrameWindow::Streamer::Write(opstream& os) const
  896. {
  897.   TFrameWindow* o = GetObject();
  898.   WriteVirtualBase((TWindow*)o, os);
  899.   if (o->IsFlagSet(wfMainWindow))
  900.     return;
  901.  
  902.   os << o->ClientWnd;
  903.   os << o->KeyboardHandling;
  904.  
  905.   os.writeByte(BYTE(o->MenuDescr ? 1 : 0));
  906.   if (o->MenuDescr)
  907.     os << *o->MenuDescr;
  908.  
  909.   os << o->IconModule;
  910.   os << o->IconResId;
  911.   os << o->MergeModule;
  912.   WINDOWPLACEMENT windata;
  913.   windata.length = sizeof(WINDOWPLACEMENT);
  914.   o->GetWindowPlacement(&windata);
  915.   os << TPoint(windata.ptMinPosition);
  916. }
  917.  
  918. #endif  // SECTION
  919.