home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / MDISTRM.PAK / MDISTRM.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  7KB  |  257 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1993 by Borland International
  3. //
  4. // This example shows a persistent desktop using the MDI metaphor.  It is
  5. // identical to the owlapi\mdi example, but with streaming code added to
  6. // implement persistence for the frame, parent (client) window, and children.
  7. //
  8. //----------------------------------------------------------------------------
  9. #include <owl\owlpch.h>
  10. #include <owl\applicat.h>
  11. #include <owl\mdi.h>
  12. #include <owl\mdichild.h>
  13. #include <stdio.h>
  14. #include "mdistrm.h"
  15.  
  16. const char DskFile[] = "MDISTRM.SAV";
  17. const char AppName[] = "MDI Object Streaming Example";
  18.  
  19. //----------------------------------------------------------------------------
  20.  
  21. //
  22. // Here's our client, it's fully streamable.
  23. //
  24. class TMyMDIClient : public TMDIClient {
  25.   public:
  26.     TMyMDIClient() : TMDIClient() {ChildNum = 0;}
  27.   
  28.     TMDIChild*  InitChild();
  29.     BOOL        CanClose();     //virtual from TWindow
  30.  
  31.   private:
  32.     WORD        ChildNum;
  33.     
  34.   DECLARE_STREAMABLE(, TMyMDIClient, 1);
  35. };
  36.  
  37. IMPLEMENT_CASTABLE1(TMyMDIClient, TMDIClient);
  38. IMPLEMENT_STREAMABLE1(TMyMDIClient, TMDIClient);
  39.  
  40. //
  41. // Our application object is also fully streamable and
  42. // we use it to stream out its client (which contains the
  43. // MDI child windows) to achieve a persistent desktop.
  44. //
  45. class TMDIApp : public TApplication {
  46.   public:
  47.     TMDIApp() : TApplication(AppName) {}
  48.     void InitMainWindow();
  49.     void InitInstance();
  50.     void CmSaveState();
  51.     void CmRestoreState();
  52.  
  53.   private:
  54.     TMyMDIClient* Client;
  55.  
  56.   DECLARE_RESPONSE_TABLE(TMDIApp);
  57.   DECLARE_STREAMABLE(, TMDIApp, 1);
  58. };
  59.  
  60. DEFINE_RESPONSE_TABLE1(TMDIApp, TApplication)
  61.   EV_COMMAND(CM_SAVESTATE, CmSaveState),
  62.   EV_COMMAND(CM_RESTORESTATE, CmRestoreState),
  63. END_RESPONSE_TABLE;
  64.  
  65. IMPLEMENT_CASTABLE1(TMDIApp, TApplication);
  66. IMPLEMENT_STREAMABLE1(TMDIApp, TApplication);
  67.  
  68.  
  69. //----------------------------------------------------------------------------
  70.  
  71. TMDIChild*
  72. TMyMDIClient::InitChild()
  73. {
  74.   char childName[15];
  75.  
  76.   // Create a unique (numbered) caption for our MDI child
  77.   sprintf(childName, "MDI Child %d", ChildNum++);
  78.  
  79.   // and then create that child.
  80.   return new TMDIChild(*this, childName);
  81. }
  82.  
  83. BOOL
  84. TMyMDIClient::CanClose()
  85. {
  86.   // Save our persistent desktop, before closing down the client.
  87.   // We have to (safely and dynamically) cast to our application
  88.   // object type so that we can call our save state routine.
  89.   //
  90.   TMDIApp *app = TYPESAFE_DOWNCAST(GetApplication(),TMDIApp);
  91.   if (app)
  92.     app->CmSaveState();
  93.  
  94.   return TMDIClient::CanClose();
  95. }
  96.  
  97. //
  98. // Writes the TMyMDIClient instance to the passed opstream.
  99. //
  100. void
  101. TMyMDIClient::Streamer::Write(opstream& os) const
  102. {
  103.   WriteBaseObject((TMDIClient*)GetObject(), os);
  104.   
  105.   // Write out the member data for our MDI Client.
  106.   os << GetObject()->ChildNum;
  107. }
  108.  
  109. //
  110. // Reads an instance of TMyMDIClient from the passed ipstream.
  111. //
  112. void *
  113. TMyMDIClient::Streamer::Read(ipstream& is, uint32 /*version*/) const
  114. {
  115.   ReadBaseObject((TMDIClient*)GetObject(), is);
  116.  
  117.   // Read in the member data for our MDI Client.
  118.   is >> GetObject()->ChildNum;
  119.  
  120.   return GetObject();
  121. }
  122.  
  123.  
  124. //----------------------------------------------------------------------------
  125.  
  126. //
  127. // Construct the TMDIApp's MainWindow (frame) object and save
  128. // a pointer to its client window in the Client data member.
  129. // Restore the desktop if we've got one already streamed.
  130. //
  131. void
  132. TMDIApp::InitMainWindow()
  133. {
  134.   // Create MDI frame window, load its menu, and create its client.
  135.   MainWindow = new TMDIFrame(GetName(), "MDIMenu", *(Client=new TMyMDIClient));
  136. }
  137.  
  138. void
  139. TMDIApp::InitInstance()
  140. {
  141.   TApplication::InitInstance();
  142.  
  143.   // Restore our persistent desktop, if there's a stream that already exists.
  144.   ifpstream is(DskFile);
  145.   if (!is.bad())
  146.   {
  147.     is.close();
  148.     CmRestoreState();
  149.   }
  150. }
  151.  
  152. //
  153. // Save the the position and contents of the windows to the "desktop" file.
  154. //
  155. void
  156. TMDIApp::CmSaveState()
  157. {
  158.   ofpstream os(DskFile);
  159.  
  160.   // Stream out 'this' object (our MDI application and children).
  161.   os << *this;
  162.  
  163.   os.close();
  164.  
  165.   if (os.bad()) {
  166.     unlink(DskFile);
  167.     MainWindow->MessageBox("Unable to write desktop file.", "Disk error",
  168.                            MB_OK | MB_ICONEXCLAMATION);
  169.   }
  170. }
  171.  
  172. //
  173. // Read windows' positions and contents from the "desktop" file.
  174. //
  175. void
  176. TMDIApp::CmRestoreState()
  177. {
  178.   char* errorMsg = 0;
  179.  
  180.   ifpstream is(DskFile);
  181.   if (is.bad())
  182.     errorMsg = "Unable to open desktop file.";
  183.  
  184.   else {
  185.     // Close any MDI children we may have.
  186.     Client->CloseChildren();
  187.     try {
  188.       // Stream into 'this' object our (new) MDI application and children.
  189.       is >> *this;
  190.       if (is.bad())
  191.         errorMsg = "Error reading desktop file.";
  192.     }
  193.     catch (xalloc) {
  194.       if (Client->HWindow)
  195.         Client->CloseChildren();
  196.       errorMsg = "Not enough memory to open file.";
  197.     }
  198.     is.close();
  199.   }
  200.   if (errorMsg)
  201.     MainWindow->MessageBox(errorMsg, "Error", MB_OK | MB_ICONEXCLAMATION);
  202. }
  203.  
  204. void 
  205. TMDIApp::Streamer::Write(opstream& os) const
  206. {
  207.   // Stream out our app's mainwindow size/coordinates and our client
  208.   // window (the client will stream any child windows it may contain).
  209.   WriteBaseObject((TApplication*)GetObject(), os);
  210.   os << GetObject()->MainWindow->Attr.X;
  211.   os << GetObject()->MainWindow->Attr.Y;
  212.   os << GetObject()->MainWindow->Attr.W;
  213.   os << GetObject()->MainWindow->Attr.H;
  214.  
  215.   os << *( GetObject()->Client );
  216.   os << GetObject()->Client->GetActiveMDIChild();
  217. }
  218.  
  219. void *
  220. TMDIApp::Streamer::Read(ipstream& is, uint32 /*version*/ ) const
  221. {
  222.   // Stream in our app's mainwindow frame coordinates, updating its frame
  223.   // size, and stream in its client window.
  224.   ReadBaseObject((TApplication*)GetObject(), is);
  225.   is >> GetObject()->MainWindow->Attr.X;
  226.   is >> GetObject()->MainWindow->Attr.Y;
  227.   is >> GetObject()->MainWindow->Attr.W;
  228.   is >> GetObject()->MainWindow->Attr.H;
  229.  
  230.   is >> *( GetObject()->Client );
  231.   TMDIChild* active;
  232.   is >> active;
  233.  
  234.   // If our mainwindow already exists (i.e., we're restoring from the menu)
  235.   // then make sure it's redrawn correctly, with the 'new' extent attributes
  236.   // (what they were when they were last streamed to file).
  237.   if (GetObject()->MainWindow->HWindow)
  238.     GetObject()->MainWindow->MoveWindow(GetObject()->MainWindow->Attr.X,
  239.                                         GetObject()->MainWindow->Attr.Y,
  240.                                         GetObject()->MainWindow->Attr.W,
  241.                                         GetObject()->MainWindow->Attr.H,
  242.                                         TRUE);
  243.  
  244.   // Finally, create the interface objects for our children,
  245.   // restoring the active window.
  246.   GetObject()->Client->CreateChildren();
  247.   if (active)
  248.     GetObject()->Client->HandleMessage(WM_MDIACTIVATE,(UINT)active->HWindow);
  249.   return GetObject();
  250. }
  251.  
  252. int
  253. OwlMain(int /*argc*/, char* /*argv*/ [])
  254. {
  255.   return TMDIApp().Run();
  256. }
  257.