PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 1/8 TITLE : Streaming OWL Objects to disk. Creating persistent OWL Objects. =============================== Borland's Object Windows Library provides a stream manager which can be use to create persistent objects. This document provides an example of streaming a TDialog to disk. Other examples of persistent OWL objects are included in the examples shipping with the product ( eg. the STEP9, STEP10 and MFILAPP projects ). The code provided below contains a comment section for each of the fundamemtal steps involved in creating persistent objects. The comment includes the word 'STEP xx' when xx is a number. Therefore, you can search for the word 'STEP' to quickly locate the necessary steps required to included persistency in your own application. // ---------- // // STRMDL.CPP // // ---------- // #include #include #include "strmdg.h" // ----------------------------------------------------- // // // // ----------------------------------------------------- // class TTestWindow : public TWindow { PTDialog dlgPtr; public: TTestWindow(PTWindowsObject AParent, LPSTR ATitle); virtual void CMTest(RTMessage Msg) = [CM_FIRST + CM_TEST]; virtual void CMRead( RTMessage ) = [ CM_FIRST + CM_READ ]; virtual void CMWrite( RTMessage ) = [ CM_FIRST + CM_WRITE ]; BOOL IsPointerChild( void * ); PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 2/8 TITLE : Streaming OWL Objects to disk. }; // ----------------------------------------------------- // // // // ----------------------------------------------------- // class TTestApp : public TApplication { public: TTestApp( LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) : TApplication( AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {}; virtual void InitMainWindow(); }; // ----------------------------------------------------- // // // // ----------------------------------------------------- // TTestWindow::TTestWindow( PTWindowsObject AParent, LPSTR ATitle ) : TWindow( AParent, ATitle ) { AssignMenu( "COMMANDS" ); dlgPtr = NULL; } // ----------------------------------------------------- // // // // ----------------------------------------------------- // void TTestWindow::CMTest( RTMessage ) { /* --------------- [ STEP 1 ] ------------------ *\ Construct an actual TDialog to stream out \* ----------------------------------------------- */ dlgPtr = new TDialog( this , "TESTDIALOG" ); GetApplication()->MakeWindow( dlgPtr ); PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 3/8 TITLE : Streaming OWL Objects to disk. } // ----------------------------------------------------- // // // // ----------------------------------------------------- // static int Test( void *child , void *test_child ) { return( test_child == child ); } // ----------------------------------------------------- // // // // ----------------------------------------------------- // BOOL TTestWindow::IsPointerChild( void * child ) { if ( FirstThat( Test , child ) ) return TRUE; else return FALSE; } // ----------------------------------------------------- // // // // ----------------------------------------------------- // void TTestWindow::CMWrite( RTMessage) { /* ---------------------------------- *\ Test to see if the dialog pointer currently represents a real window \* ---------------------------------- */ if ( IsPointerChild( dlgPtr ) ) { /* --------------- [ STEP 2 ] ------------------ *\ PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 4/8 TITLE : Streaming OWL Objects to disk. Open up a opstream, in this case we are using a ofpstream to write the dialog data to a file. \* ----------------------------------------------- */ ofpstream ofp( "file.dia" ); if ( ofp ) { /* ----------------- [ STEP 3 ] -------------------- *\ Here we are writing a pointer out. We are using the << operator which takes a opstream& and a TStreamble*. Common errors include not using the correct << operator by either writing ones one which explicitly takes a TDialog *, etc. \* --------------------------------------------------- */ ofp << ( TStreamable* )dlgPtr; ofp.close(); } else MessageBox( HWindow , "Opening ofpstream failed", "Error", MB_OK ); } else MessageBox( HWindow , "Choose Test to bring up the dialog first", "Error", MB_OK ); } // ----------------------------------------------------- // // // // ----------------------------------------------------- // void TTestWindow::CMRead( RTMessage ) { /* ----------------- [ STEP 4 ] -------------------- *\ Open an ipstream to read the object back from. \* --------------------------------------------------- */ ifpstream ifp( "file.dia" ); if ( ifp ) { PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 5/8 TITLE : Streaming OWL Objects to disk. PTDialog new_dialog = 0; /* ----------------- [ STEP 5 ] -------------------- *\ Read the object back from the ipstream. It is important to use the >> operator which takes a ipstream & and void * & as parameters. If you get warnings about temporary objects here, something is probably wrong!. Notice how we have not called a constructor for new_dialog. The stream manager is going to call new TDialog( streamableInit ) for us. It knows to do this because the ifpstream has the class name for TDialog in it. The stream manager can look up that class name in a database and find the build function. The build function constructs our object for us. TDialog gave the stream manger this information by constructing a TStreamableClass object. Since we are passing a reference to our pointer, the stream manager will be able to modify our pointer to point to the newly allocated object. Common errors are using the wrong operator here, or typecasting to a TStreamable*. \* --------------------------------------------------- */ ifp >> ( void * & ) new_dialog; /* ----------------- [ STEP 6 ] -------------------- *\ TWindowsObject::write does not save the Parent pointer, it will be set to NULL after reading back from the ipstream. This will cause the dialog to appear in the wrong place. We are explicitly setting the parent again here. \* --------------------------------------------------- */ new_dialog->Parent = this; if ( new_dialog ) { /* ----------------- [ STEP 7 ] -------------------- *\ Now that the object is constructed, you can do a MakeWindow on it. \* --------------------------------------------------- */ GetApplication()->MakeWindow( new_dialog ); } else MessageBox( HWindow , PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 6/8 TITLE : Streaming OWL Objects to disk. "Bad dialog pointer", "Error" , MB_OK ); } else MessageBox( HWindow , "Bad ifpstream", "Error", MB_OK ); } // ----------------------------------------------------- // // // // ----------------------------------------------------- // void TTestApp::InitMainWindow() { MainWindow = new TTestWindow( NULL, Name ); } // ----------------------------------------------------- // // // // ----------------------------------------------------- // int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { TTestApp TestApp( "Streaming Dialog Tester", hInstance, hPrevInstance, lpCmdLine, nCmdShow ); TestApp.Run(); return( TestApp.Status ); } // -------- // // STRMDG.H // // -------- // #ifndef __STRMDG_H PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 7/8 TITLE : Streaming OWL Objects to disk. #define __STRMDG_H #define ID_LISTBOX 101 #define ID_BUTTON 102 #define CM_TEST 201 #define CM_READ 202 #define CM_WRITE 203 #endif // __STRMDG_H // ---------- // // STRMDG.DEF // // ---------- // NAME OWL_Sample_Application DESCRIPTION 'Sample OWL Dialog Streaming' EXETYPE WINDOWS CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 5120 // --------- // // STRMDG.RC // // --------- // #include #include "strmdg.h" COMMANDS MENU LOADONCALL MOVEABLE PURE DISCARDABLE BEGIN MENUITEM "&Dialog", CM_TEST MENUITEM "&Write", CM_WRITE MENUITEM "&Read" , CM_READ PRODUCT : Borland C++ NUMBER : 1163 VERSION : 3.1 OS : WIN DATE : October 20, 1993 PAGE : 8/8 TITLE : Streaming OWL Objects to disk. END TESTDIALOG DIALOG DISCARDABLE LOADONCALL PURE MOVEABLE 30, 49, 188, 100 STYLE WS_POPUP | WS_DLGFRAME | WS_VISIBLE BEGIN CONTROL "&Fill List Box" ID_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 111, 13, 68, 12 CONTROL "&Cancel" IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 112, 66, 68, 12 CONTROL "COMBOBOX" ID_LISTBOX, "COMBOBOX", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_BORDER | WS_VSCROLL | 0x3L, 8, 8, 83, 73 END DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.