home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 9.ddi / OLE.ZIP / OLECLNT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  10.8 KB  |  418 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2. //
  3. // oleclnt.cpp
  4.  
  5. // An example of an Ole Client program using OWL.  It demonstrates
  6. // a simple use of Client Ole functions, and using C++ classes to
  7. // wrap around the Ole structures.
  8.  
  9. // Its main window allows the user to create a paint brush object, or
  10. // copy an object in from the clipboard.  Note, you do need to have
  11. // paint brush available on the system.  (It is a standard part of
  12. // Windows 3.0 or 3.1).
  13.  
  14. #include <owl.h>
  15. #include <listbox.h>
  16. #include <string.h>
  17. #include <edit.h>
  18. #include <bwcc.h>
  19. #include <filedial.h>
  20. #include <ole.h>
  21. #include <shellapi.h>
  22. #pragma hdrstop
  23.  
  24. #include "oleclnte.h"
  25. #include "oleclntr.h"
  26. #include "oleclnt.h"
  27.  
  28. // static class data members.
  29. LPOLECLIENTVTBL TOwlClient::lpClientVtbl = NULL;
  30. int             TOleDocWindow::nNextObjectNum = 0;
  31.  
  32. void TOleApp::InitInstance()
  33. {
  34.     TApplication::InitInstance();
  35.  
  36.     vcfLink = RegisterClipboardFormat( "ObjectLink" );
  37.     vcfNative = RegisterClipboardFormat( "Native" );
  38.     vcfOwnerLink = RegisterClipboardFormat( "OwnerLink" );
  39.     // comments in owlole.h mention these ole clipboard formats
  40. }
  41.  
  42.  
  43. // passes the notification on to the OWL Object which
  44. // is keeping track of this Ole Object
  45.  
  46. int FAR PASCAL _export StdCallBack(LPOLECLIENT lpClient,
  47.     OLE_NOTIFICATION notification,
  48.     LPOLEOBJECT lpObject )
  49. {
  50.     return (( PTOwlClient )lpClient)->TOleDocWindowThis->
  51.         CallBack( lpClient ,
  52.         notification,
  53.         lpObject );
  54. }
  55.  
  56. // if no vtbl has been constructed, make one.  Then initialize
  57. // the vtbl class instance member to point to it.  When smart
  58. // call backs are used for the compiler entry/exit code,
  59. // MakeProcInstance is not needed.  This code will not call
  60. // MakeProcInstance when the default value of hInst is used (it
  61. // defaults to being 0).  If you want to use Procedure instances
  62. // for the callbacks, construct a TOwlClient with a valid hInst.
  63.  
  64. TOwlClient::TOwlClient( PTOleDocWindow owner , HINSTANCE hInst )
  65. {
  66.     TOleDocWindowThis = owner;
  67.     if ( !lpClientVtbl )
  68.     {
  69.         lpClientVtbl = new OLECLIENTVTBL;
  70.         if (  hInst == 0 ) {
  71.             lpClientVtbl->CallBack = StdCallBack;
  72.         } else {
  73.             lpClientVtbl->CallBack = (TCallBack)MakeProcInstance( (FARPROC)StdCallBack,
  74.                     hInst );
  75.         }
  76.     }
  77.     lpvtbl = lpClientVtbl;
  78. }
  79.  
  80. void TOleDocWindow::WMURedraw( RTMessage )
  81. {
  82.     bObjectLoaded = TRUE;
  83.     InvalidateRect( HWindow, NULL, TRUE );
  84.     UpdateWindow( HWindow );
  85. }
  86.  
  87. #pragma argsused
  88. int TOleDocWindow::CallBack( LPOLECLIENT      lpOleClient ,
  89.                              OLE_NOTIFICATION oleNot,
  90.                              LPOLEOBJECT lpOleObject )
  91. {
  92.     switch ( oleNot ) {
  93.         case OLE_CHANGED:
  94.         case OLE_SAVED:
  95.             PostMessage( HWindow , WM_U_REDRAW, 0, 0L );
  96.             break;
  97.         case OLE_CLOSED:
  98.             break;
  99.         case OLE_QUERY_PAINT:
  100.             break;
  101.         case OLE_RELEASE:
  102.             break;
  103.         case OLE_RENAMED:
  104.             break;
  105.         default:
  106.             break;
  107.     }
  108.     return TRUE;
  109. }
  110.  
  111. void TOleDocWindow::CMAbout( RTMessage )
  112. {
  113.  
  114.     MessageBox( HWindow , "OLE Client Program\nWritten using ObjectWindows\nCopyright (c) 1992 Borland",
  115.             GetApplication()->Name, MB_OK );
  116. }
  117.  
  118. // create a new paint brush
  119. void TOleDocWindow::CMPBrush( RTMessage )
  120. {
  121.     BackupObject();
  122.     bObjectLoaded = FALSE;
  123.  
  124.     lstrcpy( lpszObjectName, GetNextObjectName() );
  125.  
  126.     ret = OleCreate( "StdFileEditing",
  127.             (LPOLECLIENT)pOwlClient,
  128.             "PBRUSH",
  129.             lhClientDoc,
  130.             GetApplication()->Name,
  131.             &lpObject,
  132.             olerender_draw,
  133.             0 );
  134.  
  135.     // Creating an Ole Object is a asynchronous operation.  An
  136.     // interesting experiment is to use TDW to step into
  137.     // WaitOleNotBusy (which the following wait macro takes you
  138.     // to) and look at the user screen between message
  139.     // dispatching.  You should see pbrush gradually paint
  140.     // itself as it processes the messages which which Ole
  141.     // generates for it.  In general, if a Ole Server does not
  142.     // behave properly when creating an object, a likely cause is a
  143.     // problem with the message dispatch loop.
  144.  
  145.     wait( ret , lpObject );
  146.  
  147.     // OleSetHostNames sets the name in the server app.  If this
  148.     // was not called, pbrush would display a string with a bunch
  149.     // of % sings in it.
  150.  
  151.     ret = OleSetHostNames( lpObject, GetApplication()->Name, lpszObjectName );
  152.     wait( ret , lpObject );
  153. }
  154.  
  155. void TOleDocWindow::CMUndo( RTMessage msg)
  156. {
  157.     if ( lpUndoObject )        // we have a previous object
  158.         if ( lpUndoObject != lpObject )    // it is different then the current one
  159.         {
  160.             LPOLEOBJECT lpObjectToDelete = lpObject;
  161.             lpObject = lpUndoObject;
  162.             lpUndoObject = NULL;
  163.             ret = OleDelete( lpObjectToDelete );
  164.             wait( ret , lpObjectToDelete );
  165.             bObjectLoaded = bUndoObjectLoaded;
  166.             WMURedraw( msg );
  167.         }
  168.  
  169. }
  170.  
  171. void TOleDocWindow::CMCut( RTMessage msg)
  172. {
  173.     CMCopy( msg );
  174.     CloseCurrentOle();
  175. }
  176.  
  177. void TOleDocWindow::CMCopy( RTMessage )
  178. {
  179.     if ( OpenClipboard( HWindow ) && EmptyClipboard() )
  180.     {
  181.         ret = OleCopyToClipboard( lpObject );
  182.         check( ret );
  183.         CloseClipboard();
  184.     }
  185. }
  186.  
  187. void TOleDocWindow::BackupObject()
  188. {
  189.     if ( lpObject )
  190.     {
  191.         ret = OleClone( lpObject, (LPOLECLIENT)pOwlClient,
  192.                 lhClientDoc, GetApplication()->Name, &lpUndoObject );
  193.         wait( ret, lpObject );
  194.         lstrcpy( lpszLastObjectName, lpszObjectName );
  195.         lstrcpy( lpszObjectName , GetNextObjectName() );
  196.         bUndoObjectLoaded = bObjectLoaded;
  197.     }
  198. }
  199.  
  200.  
  201. void TOleDocWindow::CMPaste( RTMessage )
  202. {
  203.     if ( OpenClipboard( HWindow ) )
  204.     {
  205.         BackupObject();
  206.  
  207.         lstrcpy( lpszObjectName, GetNextObjectName() );
  208.  
  209.         ret = OleCreateFromClip( "StdFileEditing",
  210.             (LPOLECLIENT)pOwlClient,
  211.             lhClientDoc,
  212.             lpszObjectName,
  213.             &lpObject,
  214.             olerender_draw,
  215.             0 );
  216.         check( ret );
  217.  
  218.         ret = OleSetHostNames( lpObject, GetApplication()->Name, lpszObjectName );
  219.         wait( ret , lpObject );
  220.  
  221.         bObjectLoaded = TRUE;
  222.  
  223.         CloseClipboard();
  224.         PostMessage( HWindow , WM_U_REDRAW, 0, 0L );
  225.     }
  226.  
  227. }
  228.  
  229. LPSTR TOleDocWindow::GetNextObjectName()
  230. {
  231.     static char buffer[ MAXPATH ];
  232.     wsprintf( buffer, "object #%03d", nNextObjectNum++ );
  233.     return buffer;
  234. }
  235.  
  236. void TOleDocWindow::Paint( HDC hdc, PAINTSTRUCT _FAR &)
  237. {
  238.     LPOLEOBJECT lpObjectToDraw = NULL;
  239.  
  240.     if ( bObjectLoaded )
  241.         lpObjectToDraw = lpObject;
  242.     else if ( lpUndoObject )
  243.         lpObjectToDraw = lpUndoObject;
  244.  
  245.     if ( lpObjectToDraw ) {
  246.         RECT rect;
  247.         GetClientRect( HWindow, &rect );
  248.  
  249.         // Tips for OleDraw:
  250.         // OleDraw will return OLE_ERROR_OBJECT if the
  251.         // object to be drawn is invalid.  In a case like this,
  252.         // that could happen if the Paint function does not get
  253.         // informed about the object being deleted, or not having
  254.         // yet been created.
  255.         // You can also get OLE_ERROR_BLANK if you draw an object
  256.         // which has not been stored.  A time when this could happen
  257.         // is trying use OleDraw on the object after using OleCreate
  258.         // to make it, but not yet using the Servers update command
  259.         // to save the object with Ole.
  260.         ret = OleDraw( lpObjectToDraw , hdc, &rect , NULL, 0 );
  261.         wait( ret, lpObjectToDraw );
  262.     }
  263. }
  264.  
  265. TOleDocWindow::TOleDocWindow( PTWindowsObject parent, LPSTR title )
  266.     : TWindow( parent, title )
  267. {
  268.     ret = OLE_OK;
  269.     lhClientDoc = 0;
  270.  
  271.     bObjectLoaded = FALSE;
  272.     bUndoObjectLoaded = FALSE;
  273.     bUndoObjectLoaded = FALSE;
  274.  
  275.     pOwlClient = NULL;
  276.     lpObject = NULL;
  277.     lpUndoObject = NULL;
  278.  
  279.     strcpy( lpszDocName , "noname.ole" );
  280.     *lpszLastObjectName = 0;
  281.     *lpszObjectName = 0;
  282.     bDefDocName = TRUE;
  283. }
  284.  
  285. void TOleDocWindow::SetupWindow() {
  286.     TWindow::SetupWindow();
  287.     RegisterClientDoc();
  288.     pOwlClient = new TOwlClient( this );
  289.  
  290. }
  291.  
  292.  
  293. void TOleDocWindow::RegisterClientDoc() {
  294.     // Tip for using OleRegisterClientDoc:
  295.     // if the lpszDoc parameter passed to
  296.     // OleRegisterClientDoc is not valid, (lpszPatnName in this case),
  297.     // one can get an OLE_ERROR_ADDRESS error, and the ClientDoc
  298.     // handle will not be valid.
  299.  
  300.     ret = OleRegisterClientDoc(
  301.             GetApplication()->Name,
  302.             lpszDocName,
  303.             0,
  304.             &lhClientDoc );
  305.     check( ret );
  306. }
  307.  
  308.  
  309. void TOleDocWindow::ShutDownWindow()
  310. {
  311.     CloseCurrentOle();
  312.     if ( pOwlClient ) delete pOwlClient;
  313.     TWindow::ShutDownWindow();
  314. }
  315.  
  316.  
  317. void TOleDocWindow::RegFileName( LPSTR FileName )
  318. {
  319.     lstrcpy( lpszDocName , FileName );
  320.     ret = OleRegisterClientDoc( GetApplication()->Name,
  321.             lpszDocName ,
  322.             0,
  323.             &lhClientDoc );
  324.     check ( ret );
  325. }
  326.  
  327. void TOleDocWindow::CMActivate( RTMessage )
  328. {
  329.     BackupObject();
  330.     RECT rect;
  331.     GetClientRect( HWindow, &rect );
  332.     ret = OleActivate( lpObject , OLEVERB_PRIMARY, TRUE, TRUE ,
  333.             HWindow , &rect );
  334.     wait ( ret, lpObject );
  335.     PostMessage( HWindow , WM_U_REDRAW, 0, 0L );
  336. }
  337.  
  338. void TOleDocWindow::WMInitMenu( RTMessage msg )
  339. {
  340.     HMENU hMenu = (HMENU)msg.WParam;
  341.     WORD wEnableUndo;
  342.  
  343.     if ( (lpObject != lpUndoObject) && ( lpUndoObject != NULL ))
  344.         wEnableUndo = MF_ENABLED;
  345.     else wEnableUndo = MF_GRAYED;
  346.     EnableMenuItem( hMenu, CM_UNDO     , wEnableUndo );
  347.     EnableMenuItem( hMenu, CM_COPY     , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  348.     EnableMenuItem( hMenu, CM_CUT      , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  349.     ret = OleQueryCreateFromClip( "StdFileEditing", olerender_draw, 0 );
  350.     EnableMenuItem( hMenu, CM_PASTE    , (( ret == OLE_OK ) ? MF_ENABLED : MF_GRAYED ));
  351.     EnableMenuItem( hMenu, CM_ACTIVATE , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  352.     EnableMenuItem( hMenu, CM_CLEAR    , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  353.  
  354.     DrawMenuBar( HWindow );
  355. }
  356.  
  357. LPSTR TOleDocWindow::GetClassName() { return "OLEDOCWINDOW"; }
  358.  
  359. void TOleDocWindow::GetWindowClass(WNDCLASS _FAR &wc )
  360. {
  361.     TWindow::GetWindowClass( wc );
  362.     wc.lpszMenuName = "MENU_DOCWINDOW";
  363. }
  364.  
  365. void TOleDocWindow::CMClear( RTMessage )
  366. {
  367.     CloseCurrentOle();
  368. }
  369.  
  370. void TOleDocWindow::CloseCurrentOle()
  371. {
  372.     // assume saved
  373.     if ( lpObject ) {
  374.         ret = OleDelete( lpObject );
  375.         wait( ret , lpObject );
  376.     }
  377.     if ( lpUndoObject ) {
  378.         ret = OleDelete( lpUndoObject );
  379.         wait( ret , lpObject );
  380.     }
  381.     lpObject = lpUndoObject = NULL;
  382.  
  383.     bObjectLoaded = FALSE;
  384.  
  385.     InvalidateRect( HWindow , NULL, TRUE );
  386.     UpdateWindow( HWindow );
  387. }
  388.  
  389.  
  390. void TOleApp::InitMainWindow()
  391. {
  392.   MainWindow = new TOleDocWindow(NULL, "OWL OLE Application" );
  393. }
  394.  
  395.  
  396.  
  397. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  398.            LPSTR lpCmd, int nCmdShow)
  399. {
  400.     TOleApp OleApp ("OleApp", hInstance, hPrevInstance,
  401.         lpCmd, nCmdShow);
  402.     OleApp.Run();
  403.     return (OleApp.Status);
  404. }
  405.  
  406. // General Help:
  407. // Question: Right after closing down the server, the only part of the
  408. //   object repainted in my application is that portion of the window that
  409. //   was covered with the server program, whats going on?
  410. // Answer: When the server closes, Windows sends you a paint message to
  411. //     update that portion of your window which the server covered up.  It
  412. //     has a clipping region defined which keeps all the previous visible
  413. //     portions of your client window.  To repaint the whole window after
  414. //     a server closes, respond to the OLE_CHANGED notification in your
  415. //     callback, and force the whole window to be updated there.  Calling
  416. //     InvalidateRect would be appropiate.
  417.  
  418.