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

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1992, 1993 by Borland International
  3. //   source\owl\decframe.cpp
  4. //   Implementation of class TDecoratedFrame
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\decframe.h>
  9. #include <owl\messageb.h>
  10.  
  11. DIAG_DECLARE_GROUP(OwlWin);  // diagnostic group for windows
  12.  
  13. #if !defined(SECTION) || SECTION == 1
  14.  
  15. DEFINE_RESPONSE_TABLE2(TDecoratedFrame, TFrameWindow, TLayoutWindow)
  16.   EV_WM_ENTERIDLE,
  17.   EV_WM_MENUSELECT,
  18.   EV_WM_SIZE,           // inline in decframe.h
  19. END_RESPONSE_TABLE;
  20.  
  21. const UINT  BLANK_HELP = UINT_MAX;
  22.  
  23. TDecoratedFrame::TDecoratedFrame(TWindow*        parent,
  24.                                  const char far* title,
  25.                                  TWindow*        clientWnd,
  26.                                  BOOL            trackMenuSelection,
  27.                                  TModule*        module)
  28.   : TLayoutWindow(parent, title, module)
  29. {
  30.   //
  31.   // Initialize virtual bases, in case the derived-most used default ctor
  32.   //
  33.   TWindow::Init(parent, title, module);
  34.   TFrameWindow::Init(clientWnd, FALSE);
  35.  
  36.   TLayoutMetrics  metrics;
  37.  
  38.   TrackMenuSelection = trackMenuSelection;
  39.   MenuItemId = 0;
  40.  
  41.   if (!ClientWnd)
  42.     ClientWnd = new TWindow(this, "\007");  // create dummy placeholder
  43.  
  44.   if (ClientWnd->Attr.Style & WS_BORDER) {
  45.     metrics.X.SameAs(lmParent, lmLeft);
  46.     metrics.Y.SameAs(lmParent, lmTop);
  47.     metrics.Width.SameAs(lmParent, lmRight);
  48.     metrics.Height.SameAs(lmParent, lmBottom);
  49.  
  50.   } else {
  51.     metrics.X.Set(lmLeft, lmRightOf, lmParent, lmLeft);
  52.     metrics.Y.Set(lmTop, lmBelow, lmParent, lmTop);
  53.     metrics.Width.Set(lmRight, lmLeftOf, lmParent, lmRight);
  54.     metrics.Height.Set(lmBottom, lmAbove, lmParent, lmBottom);
  55.   }
  56.  
  57.   SetChildLayoutMetrics(*ClientWnd, metrics);
  58. }
  59.  
  60. void
  61. TDecoratedFrame::SetupWindow()
  62. {
  63.   TRect  clientRect = GetClientRect();
  64.  
  65.   TFrameWindow::SetupWindow();
  66.  
  67.   //
  68.   // size/position child windows. don't wait until we get the WM_SIZE event
  69.   // because by then the windows will have been displayed on the screen
  70.   //
  71.   ClientSize.cx = clientRect.right;
  72.   ClientSize.cy = clientRect.bottom;
  73.   Layout();
  74. }
  75.  
  76. TWindow*
  77. TDecoratedFrame::SetClientWindow(TWindow* clientWnd)
  78. {
  79.   TLayoutMetrics metrics;
  80.   GetChildLayoutMetrics(*ClientWnd, metrics);
  81.   if (!clientWnd)
  82.     clientWnd = new TWindow(this, "\007");  // create dummy placeholder
  83.  
  84.   TWindow* oldWnd = TFrameWindow::SetClientWindow(clientWnd);
  85.   SetChildLayoutMetrics(*clientWnd, metrics);
  86.   Layout();
  87.   if (oldWnd->Title[0] == 007) {
  88.     oldWnd->Destroy();
  89.     delete oldWnd;
  90.     oldWnd = 0;
  91.   }
  92.   return oldWnd;
  93. }
  94.  
  95. BOOL
  96. TDecoratedFrame::PreProcessMsg(MSG& msg)
  97. {
  98.   //
  99.   // give the decorations an opportunity to do pre-processing. don't bother
  100.   // checking the client window since it is typically in the focus chain and
  101.   // will be given an opportunity to do pre-processing
  102.   //
  103.   TWindow*  firstChild = GetFirstChild();
  104.  
  105.   if (firstChild) {
  106.     TWindow*  child = firstChild;
  107.  
  108.     do {
  109.       if (child != ClientWnd && child->HWindow &&
  110.          (child->GetWindowLong(GWL_STYLE) & WS_VISIBLE) &&
  111.           child->PreProcessMsg(msg))
  112.         return TRUE;
  113.  
  114.       child = child->Next();
  115.     } while (child != firstChild);
  116.   }
  117.  
  118.   return TFrameWindow::PreProcessMsg(msg);
  119. }
  120.  
  121. void
  122. TDecoratedFrame::EvMenuSelect(UINT menuItemId, UINT flags, HMENU hMenu)
  123. {
  124.   if (TrackMenuSelection)
  125.     if (flags == 0xFFFF && hMenu == 0) {  // menu closing
  126.       TMessageBar*  messageBar = (TMessageBar*)ChildWithId(IDW_STATUSBAR);
  127.       CHECK(messageBar);
  128.  
  129.       messageBar->SetHintText(0);
  130.       MenuItemId = 0;           // restore status bar to normal look
  131.  
  132.     } else if (flags & (MF_SEPARATOR | MF_POPUP | MF_MENUBREAK | MF_MENUBARBREAK)
  133.       || (menuItemId >= IDW_FIRSTMDICHILD && menuItemId < IDW_FIRSTMDICHILD+9)) {
  134.       MenuItemId = BLANK_HELP;  // display an empty help message
  135.                                 // could also restore bar at this point too
  136.  
  137.     } else {
  138.       MenuItemId = menuItemId;  // display a help message with this string Id
  139.     }
  140. }
  141.  
  142. void
  143. TDecoratedFrame::EvEnterIdle(UINT source, HWND /*hWndDlg*/)
  144. {
  145.   if (source == MSGF_MENU && MenuItemId) {
  146.     char          buf[128];
  147.     TMessageBar*  messageBar = (TMessageBar*)ChildWithId(IDW_STATUSBAR);
  148.     CHECK(messageBar);
  149.  
  150.     if (MenuItemId != BLANK_HELP) {
  151.       int numBytes = GetModule()->LoadString(MenuItemId, buf, sizeof(buf));
  152.       if (numBytes == 0 && MergeModule != 0)
  153.           numBytes = MergeModule->LoadString(MenuItemId, buf, sizeof(buf));
  154.  
  155.       WARNX(OwlWin, numBytes == 0, 0,
  156.            "TDecoratedFrame::EvEnterIdle LoadString("
  157.            << *GetModule() << "," << MenuItemId << ") Failed");
  158.     } else
  159.       *buf = 0;
  160.     messageBar->SetHintText(buf);
  161.     MenuItemId = 0;             // Don't repaint on subsequent EvEnterIdle's
  162.   }
  163. }
  164.  
  165. //
  166. // Get or set location codes stashed in the style long for a decoration
  167. //
  168. inline TDecoratedFrame::TLocation
  169. GetLocation(TWindow& w) {
  170.   return TDecoratedFrame::TLocation(WORD(w.Attr.Style) & 0x0F00);
  171. }
  172.  
  173. inline void
  174. SetLocation(TWindow& w, TDecoratedFrame::TLocation loc) {
  175.   w.Attr.Style = (w.Attr.Style&~0x0F00) | loc;
  176. }
  177.  
  178. //
  179. // Find first sibling of a decoration in the same location
  180. //
  181. struct TSiblingSearch {
  182.   TWindow*                   Decoration;
  183.   TDecoratedFrame::TLocation Location;
  184.   TWindow*                   Sibling;
  185.  
  186.   TSiblingSearch(TWindow* decoration, TDecoratedFrame::TLocation location)
  187.   {
  188.     Decoration = decoration;
  189.     Sibling = 0;
  190.     Location = location;
  191.   }
  192. };
  193.  
  194. static BOOL
  195. FindSibling(TWindow* win, void* param)
  196. {
  197.   TSiblingSearch*  search = (TSiblingSearch*)param;
  198.  
  199.   if (win == search->Decoration)
  200.     return TRUE;
  201.  
  202.   else if (GetLocation(*win) == search->Location && win->IsWindowVisible())
  203.     search->Sibling = win;
  204.  
  205.   return FALSE;
  206. }
  207.  
  208. LRESULT
  209. TDecoratedFrame::EvCommand(UINT id, HWND hWndCtl, UINT notifyCode)
  210. {
  211.   if (hWndCtl == 0) {
  212.     TWindow*  decoration = ChildWithId(id);
  213.  
  214.     if (decoration) {
  215.       BOOL            visible = decoration->IsWindowVisible();
  216.       TLocation       location = GetLocation(*decoration);
  217.  
  218.       TSiblingSearch  search(decoration, location);
  219.       FirstThat(FindSibling, &search);
  220.       if (!search.Sibling)
  221.         search.Sibling = ClientWnd;
  222.  
  223.       //
  224.       // toggle the window's visibility
  225.       //
  226.       if (visible)
  227.         RemoveChildLayoutMetrics(*decoration);
  228.  
  229.       else
  230.         switch (location) {
  231.           case Top:
  232.             InsertAtTop(*decoration, search.Sibling);
  233.             break;
  234.  
  235.           case Bottom:
  236.             InsertAtBottom(*decoration, search.Sibling);
  237.             break;
  238.  
  239.           case Left:
  240.             InsertAtLeft(*decoration, search.Sibling);
  241.             break;
  242.  
  243.           case Right:
  244.             InsertAtRight(*decoration, search.Sibling);
  245.             break;
  246.         }
  247.  
  248.       Layout();
  249.       decoration->ShowWindow(visible ? SW_HIDE : SW_SHOW);
  250.       return 0;
  251.     }
  252.   }
  253.  
  254.   return TFrameWindow::EvCommand(id, hWndCtl, notifyCode);
  255. }
  256.  
  257. void
  258. TDecoratedFrame::EvCommandEnable(TCommandEnabler& commandEnabler)
  259. {
  260.   TWindow*  decoration = ChildWithId(commandEnabler.Id);
  261.  
  262.   if (!decoration)
  263.     TFrameWindow::EvCommandEnable(commandEnabler);
  264.  
  265.   else {
  266.     commandEnabler.Enable();
  267.     commandEnabler.SetCheck(decoration->IsWindowVisible() ?
  268.                             TCommandEnabler::Checked :
  269.                             TCommandEnabler::Unchecked);
  270.   }
  271. }
  272.  
  273. void
  274. TDecoratedFrame::InsertAtTop(TWindow& decoration, TWindow* insertAbove)
  275. {
  276.   TLayoutMetrics   metrics;
  277.   TWindow*         insertBelow;
  278.  
  279.   //
  280.   // get the layout metrics for "insertAbove" (the window the decoration is
  281.   // going to be inserted above)
  282.   //
  283.   GetChildLayoutMetrics(*insertAbove, metrics);
  284.  
  285.   insertBelow = metrics.Y.RelWin;
  286.  
  287.   //
  288.   // if "insertAbove" has a border then set its top edge to be the same as
  289.   // the decoration's bottom edge; otherwise place its top edge below the
  290.   // decoration's bottom edge
  291.   //
  292.   metrics.Y.Set(lmTop,
  293.                 insertAbove->Attr.Style & WS_BORDER ? lmSameAs : lmBelow,
  294.                 &decoration, lmBottom);
  295.   SetChildLayoutMetrics(*insertAbove, metrics);
  296.  
  297.   //
  298.   // now set the layout metrics for the decoration so its top edge is the same
  299.   // as the bottom edge of "insertBelow"(i.e. they overlap)
  300.   //
  301.   if (!insertBelow)
  302.     metrics.Y.SameAs(lmParent, lmTop);
  303.  
  304.   else
  305.     metrics.Y.Set(lmTop, lmSameAs, insertBelow, lmBottom);
  306.  
  307.   metrics.Height.MyEdge = lmHeight;
  308.   metrics.Height.Relationship = lmAsIs;
  309.   metrics.X.Set(lmLeft, lmSameAs, lmParent, lmLeft);
  310.   metrics.Width.Set(lmRight, lmSameAs, lmParent, lmRight);
  311.  
  312.   SetChildLayoutMetrics(decoration, metrics);
  313. }
  314.  
  315. void
  316. TDecoratedFrame::InsertAtBottom(TWindow& decoration, TWindow* insertBelow)
  317. {
  318.   TLayoutMetrics  metrics;
  319.   TWindow*        insertAbove;
  320.  
  321.   //
  322.   // get the layout metrics for "insertBelow"(the window the decoration is
  323.   // going to be inserted below)
  324.   //
  325.   GetChildLayoutMetrics(*insertBelow, metrics);
  326.  
  327.   if (insertBelow == ClientWnd) {
  328.     insertAbove = metrics.Height.RelWin;
  329.     //
  330.     // if the client window has a border then set the client window's bottom
  331.     // to be the same as the top edge of the decoration; otherwise set the
  332.     // client window's bottom edge to be above the decoration's top edge
  333.     //
  334.     metrics.Height.Set(lmBottom,
  335.                        ClientWnd->Attr.Style & WS_BORDER ? lmSameAs : lmAbove,
  336.                        &decoration, lmTop);
  337.  
  338.   } else {
  339.     insertAbove = metrics.Y.RelWin;
  340.     //
  341.     // set the bottom edge of "insertBelow" to be the same as the top edge of
  342.     // the decoration
  343.     //
  344.     metrics.Y.Set(lmBottom, lmSameAs, &decoration, lmTop);
  345.   }
  346.   SetChildLayoutMetrics(*insertBelow, metrics);
  347.  
  348.   //
  349.   // now set the layout metrics for the decoration so its bottom edge is the
  350.   // same as the top edge of "insertAbove"
  351.   //
  352.   if (!insertAbove)
  353.     metrics.Y.SameAs(lmParent, lmBottom);
  354.  
  355.   else
  356.     metrics.Y.Set(lmBottom, lmSameAs, insertAbove, lmTop);
  357.  
  358.   metrics.Height.MyEdge = lmHeight;
  359.   metrics.Height.Relationship = lmAsIs;
  360.   metrics.X.Set(lmLeft, lmSameAs, lmParent, lmLeft);
  361.   metrics.Width.Set(lmRight, lmSameAs, lmParent, lmRight);
  362.  
  363.   SetChildLayoutMetrics(decoration, metrics);
  364. }
  365.  
  366. void
  367. TDecoratedFrame::InsertAtLeft(TWindow& decoration, TWindow* insertLeftOf)
  368. {
  369.   TLayoutMetrics  metrics;
  370.   TWindow*        insertRightOf;
  371.  
  372.   //
  373.   // get the layout metrics for "insertLeftOf"(the window the decoration is
  374.   // going to be inserted to the left of)
  375.   //
  376.   GetChildLayoutMetrics(*insertLeftOf, metrics);
  377.  
  378.   insertRightOf = metrics.X.RelWin;
  379.  
  380.   //
  381.   // if "insertLeftOf" has a border then set its left edge to be the same as
  382.   // the decoration's right edge; otherwise place its left edge one pixel to
  383.   // the right of the decoration's right edge
  384.   //
  385.   metrics.X.Set(lmLeft,
  386.                 insertLeftOf->Attr.Style & WS_BORDER ? lmSameAs : lmRightOf,
  387.                 &decoration, lmRight);
  388.   SetChildLayoutMetrics(*insertLeftOf, metrics);
  389.  
  390.   //
  391.   // now set the layout metrics for the decoration so it's left edge is the
  392.   // same as the right edge of "insertRightOf"
  393.   //
  394.   if (!insertRightOf)
  395.     metrics.X.SameAs(lmParent, lmLeft);
  396.  
  397.   else
  398.     metrics.X.Set(lmLeft, lmSameAs, insertRightOf, lmRight);
  399.  
  400.   metrics.Width.MyEdge = lmWidth;
  401.   metrics.Width.Relationship = lmAsIs;
  402.   //
  403.   // if the client window has a border then place the decoration so its
  404.   // "y" and "bottom" are the same as the client windows; otherwise place
  405.   // its "y" above the client window's "y" and its "bottom" below the client
  406.   // window's "bottom"
  407.   //
  408.   // this way if there are top or bottom decorations they will be tiled
  409.   // over/under the left/right decorations
  410.   //
  411.   if (ClientWnd->Attr.Style & WS_BORDER) {
  412.     metrics.Y.SameAs(ClientWnd, lmTop);
  413.     metrics.Height.SameAs(ClientWnd, lmBottom);
  414.  
  415.   } else {
  416.     metrics.Y.Set(lmTop, lmAbove, ClientWnd, lmTop);
  417.     metrics.Height.Set(lmBottom, lmBelow, ClientWnd, lmBottom);
  418.   }
  419.   SetChildLayoutMetrics(decoration, metrics);
  420. }
  421.  
  422. void
  423. TDecoratedFrame::InsertAtRight(TWindow& decoration, TWindow* insertRightOf)
  424. {
  425.   TLayoutMetrics  metrics;
  426.   TWindow*        insertLeftOf;
  427.  
  428.   //
  429.   // get the layout metrics for "insertRightOf"(the window the decoration is
  430.   // going to be inserted to the right of)
  431.   //
  432.   GetChildLayoutMetrics(*insertRightOf, metrics);
  433.  
  434.   if (insertRightOf == ClientWnd) {
  435.     insertLeftOf = metrics.Width.RelWin;
  436.     //
  437.     // if the client window has a border then set the client window's right
  438.     // edge to be the same as the left edge of the decoration; otherwise set
  439.     // the client window's right edge to be one pixel to the left of the
  440.     // decoration's left edge
  441.     //
  442.     metrics.Width.Set(lmRight,
  443.                       ClientWnd->Attr.Style & WS_BORDER ? lmSameAs : lmLeftOf,
  444.                       &decoration, lmLeft);
  445.  
  446.   } else {
  447.     insertLeftOf = metrics.X.RelWin;
  448.     //
  449.     // set the right edge of "insertRightOf" to be the same as the left edge of
  450.     // the decoration
  451.     //
  452.     metrics.X.Set(lmRight, lmSameAs, &decoration, lmLeft);
  453.   }
  454.   SetChildLayoutMetrics(*insertRightOf, metrics);
  455.  
  456.   //
  457.   // now set the layout metrics for the decoration so its right edge is the
  458.   // same as the left edge of "insertLeftOf"
  459.   //
  460.   if (!insertLeftOf)
  461.     metrics.X.Set(lmRight, lmSameAs, lmParent, lmRight);
  462.  
  463.   else
  464.     metrics.X.Set(lmRight, lmSameAs, insertLeftOf, lmLeft);
  465.  
  466.   metrics.Width.MyEdge = lmWidth;
  467.   metrics.Width.Relationship = lmAsIs;
  468.   //
  469.   // if the client window has a border then place the decoration so its
  470.   // "y" and "bottom" are the same as the client windows; otherwise place
  471.   // its "y" above the client window's "y" and its "bottom" below the client
  472.   // window's "bottom"
  473.   //
  474.   // this way if there are top or bottom decorations they will be tiled
  475.   // over/under the left/right decorations
  476.   //
  477.   if (ClientWnd->Attr.Style & WS_BORDER) {
  478.     metrics.Y.SameAs(ClientWnd, lmTop);
  479.     metrics.Height.SameAs(ClientWnd, lmBottom);
  480.  
  481.   } else {
  482.     metrics.Y.Set(lmTop, lmAbove, ClientWnd, lmTop);
  483.     metrics.Height.Set(lmBottom, lmBelow, ClientWnd, lmBottom);
  484.   }
  485.   SetChildLayoutMetrics(decoration, metrics);
  486. }
  487.  
  488. void
  489. TDecoratedFrame::Insert(TWindow& decoration, TLocation location)
  490. {
  491.   SetLocation(decoration, location);  // keep loc for removal & sibling inserts
  492.  
  493.   decoration.SetParent(this);
  494.   RemoveChildLayoutMetrics(decoration); // in case this is a re-insert
  495.  
  496.   if (decoration.Attr.Style & WS_VISIBLE)
  497.     switch (location) {
  498.       case Top:
  499.         InsertAtTop(decoration, ClientWnd);
  500.         break;
  501.  
  502.       case Bottom:
  503.         InsertAtBottom(decoration, ClientWnd);
  504.         break;
  505.  
  506.       case Left:
  507.         InsertAtLeft(decoration, ClientWnd);
  508.         break;
  509.  
  510.       case Right:
  511.         InsertAtRight(decoration, ClientWnd);
  512.         break;
  513.     }
  514. }
  515.  
  516. #endif
  517. #if !defined(SECTION) || SECTION == 2
  518.  
  519. IMPLEMENT_STREAMABLE3(TDecoratedFrame, TFrameWindow, TLayoutWindow, TWindow);
  520.  
  521. void*
  522. TDecoratedFrame::Streamer::Read(ipstream& is, uint32 /*version*/) const
  523. {
  524.   ReadVirtualBase((TFrameWindow*)GetObject(), is);
  525.   ReadBaseObject((TLayoutWindow*)GetObject(), is);
  526.   return GetObject();
  527. }
  528.  
  529. void
  530. TDecoratedFrame::Streamer::Write(opstream& os) const
  531. {
  532.   WriteVirtualBase((TFrameWindow*)GetObject(), os);
  533.   WriteBaseObject((TLayoutWindow*)GetObject(), os);
  534. }
  535.  
  536. #endif
  537.