home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / DECFRAME.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  19KB  |  622 lines

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