home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 6.ddi / CLIOLE.ZIP / CLIOLE.C next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  13.2 KB  |  552 lines

  1. // Windows 3.1 Demo Program
  2. // Copyright (c) 1992 by Borland International
  3.  
  4. // File CLIOLE.C
  5. // An example of an Ole Client.  It demonstrates
  6. // a simple use of Client Ole functions.
  7.  
  8. // Its main window allows the user to create a paint brush object, or
  9. // copy an object in from the clipboard.  Note, you do need to have
  10. // paint brush available on the system.  (It is a standard part of
  11. // Windows 3.1).
  12.  
  13. #define STRICT
  14.  
  15. #include <windows.h>
  16. #include <ole.h>
  17. #include <commdlg.h>
  18. #include <process.h>
  19. #include <alloc.h>
  20. #include <dir.h>
  21. #include <dos.h>
  22. #pragma hdrstop
  23.  
  24. #include "clioleer.h"
  25. #include "cliole.h"
  26. #include "cliolerc.h"
  27.  
  28. char szAppName[] = "ClientOleApp" ;
  29.  
  30. HINSTANCE hInst = 0;
  31.  
  32. void InitApplication(void)
  33. {
  34.     WNDCLASS wndclass;
  35.  
  36.     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  37.     wndclass.lpfnWndProc   = (WNDPROC) WndProc ;
  38.     wndclass.cbClsExtra    = 0 ;
  39.     wndclass.cbWndExtra    = 0 ;
  40.     wndclass.hInstance     = hInst ;
  41.     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  42.     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  43.     wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  44.     wndclass.lpszMenuName  = "CLIOLEMENU" ;
  45.     wndclass.lpszClassName = szAppName ;
  46.     RegisterClass (&wndclass) ;
  47. }
  48.  
  49. // These are clipboard formats that Ole
  50. // applications use to determine the type of
  51. // object on the clipboard.  This application does not
  52. // make use of them.
  53.  
  54. OLECLIPFORMAT vcfLink, vcfNative, vcfOwnerLink;
  55.  
  56. void InitInstance(void)
  57. {
  58.     vcfLink = RegisterClipboardFormat( "ObjectLink" );
  59.     vcfNative = RegisterClipboardFormat( "Native" );
  60.     vcfOwnerLink = RegisterClipboardFormat( "OwnerLink" );
  61. }
  62.  
  63. #pragma argsused
  64. int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  65.                     LPSTR lpszCommandLine, int nCmdShow)
  66.      {
  67.      HWND        hwnd ;
  68.      MSG         msg ;
  69.  
  70.      hInst = hInstance;
  71.      if (!hPrevInstance)
  72.      {
  73.         InitApplication();
  74.      }
  75.  
  76.      InitInstance();
  77.  
  78.      hwnd = CreateWindow (szAppName,
  79.             "Client OLE Program",
  80.                     WS_OVERLAPPEDWINDOW,
  81.                     CW_USEDEFAULT,
  82.                     CW_USEDEFAULT,
  83.                     CW_USEDEFAULT,
  84.                     CW_USEDEFAULT,
  85.                     NULL,
  86.                     NULL,
  87.                     hInstance,
  88.                     NULL) ;
  89.  
  90.      ShowWindow (hwnd, nCmdShow) ;
  91.      UpdateWindow (hwnd) ;
  92.  
  93.      while (GetMessage (&msg, NULL, 0, 0))
  94.      {
  95.           TranslateMessage (&msg) ;
  96.           DispatchMessage (&msg) ;
  97.      }
  98.      return msg.wParam ;
  99. }
  100.  
  101.  
  102.  
  103. int FAR PASCAL _export StdCallBack(LPOLECLIENT lpClient,
  104.     OLE_NOTIFICATION notification,
  105.     LPOLEOBJECT lpObject )
  106. {
  107.     static TOleNot OleNotStruct;
  108.     OleNotStruct.lpClient = lpClient;
  109.     OleNotStruct.not      = notification;
  110.     OleNotStruct.lpObject = lpObject;
  111.  
  112.     return (
  113.         (int)SendMessage( (( TOleClient * )lpClient)->hwnd,
  114.             WM_U_CALLBACK, 0, (DWORD)&OleNotStruct )
  115.             );
  116. }
  117.  
  118. // It should be noted that since much of the data associated with the
  119. // main window is stored globally, only one Windows class OleAppName
  120. // is supported.  Extending the program to support several windows of this
  121. // class would require that you store this data on a per window basis.
  122. // A good technique would be to use a structure which contains all
  123. // these data members, and to store a pointer to such a structure
  124. // in the extra bytes of the windows.
  125.  
  126.     OLESTATUS ret;           //last OleStatus
  127.     LHCLIENTDOC lhClientDoc;
  128.     char lpszDocName[ MAXPATH ];
  129.     BOOL bDefDocName;
  130.  
  131.     char lpszObjectName[ MAXPATH ];
  132.     char lpszLastObjectName[ MAXPATH ];
  133.     TOleClient *pOleClient;
  134.     BOOL bObjectLoaded = FALSE;
  135.     BOOL bUndoObjectLoaded = FALSE;
  136.     LPOLEOBJECT lpObject = NULL;        // actual object we are housing
  137.     LPOLEOBJECT lpUndoObject = NULL;    // last change made to object
  138.     int nNextObjectNum = 0;
  139.  
  140.  
  141. long FAR PASCAL _export WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  142. {
  143.  
  144.    HDC           hdc ;
  145.     PAINTSTRUCT   ps ;
  146.     RECT              rect ;
  147.    TOleNot far * ons ;
  148.  
  149.     switch (message)
  150.     {
  151.         case WM_U_REDRAW:
  152.             WMURedraw( hwnd );
  153.             return 0;
  154.  
  155.         case WM_COMMAND:
  156.             switch ( wParam )
  157.             {
  158.                 case CM_PBRUSH:
  159.                     CMPBrush();
  160.                     break;
  161.  
  162.                 case CM_UNDO:
  163.                     CMUndo(hwnd);
  164.                     break;
  165.  
  166.                 case CM_ACTIVATE:
  167.                     CMActivate( hwnd );
  168.                     break;
  169.  
  170.                 case CM_CLEAR:
  171.                     CMClear( hwnd );
  172.                     break;
  173.  
  174.                 case CM_CUT:
  175.                     CMCut(hwnd);
  176.                     break;
  177.  
  178.                 case CM_COPY:
  179.                     CMCopy(hwnd);
  180.                     break;
  181.  
  182.                 case CM_PASTE:
  183.                     CMPaste(hwnd);
  184.                     break;
  185.  
  186.                 case CM_ABOUT:
  187.                     CMAbout( hwnd );
  188.                     break;
  189.  
  190.                 case CM_EXIT:
  191.                     DestroyWindow( hwnd );
  192.                     break;
  193.             }
  194.             return 0;
  195.  
  196.         case WM_CREATE:
  197.             WMCreate( hwnd );
  198.             return 0;
  199.  
  200.         case WM_INITMENU:
  201.             WMInitMenu( hwnd , wParam );
  202.             return 0;
  203.  
  204.         case WM_U_CALLBACK:
  205.             (TOleNot far *)ons = (TOleNot far *)lParam;
  206.             WMUCallBack( ons->lpClient, ons->not, ons->lpObject );
  207.             return 0;
  208.  
  209.         case WM_PAINT:
  210.              hdc = BeginPaint (hwnd, &ps) ;
  211.              GetClientRect (hwnd, &rect) ;
  212.  
  213.              Paint( hwnd , hdc );
  214.  
  215.              EndPaint (hwnd, &ps) ;
  216.              return 0 ;
  217.  
  218.         case WM_DESTROY:
  219.             PostQuitMessage (0) ;
  220.             return 0 ;
  221.     }
  222.     return DefWindowProc (hwnd, message, wParam, lParam) ;
  223. }
  224.  
  225.  
  226. // Comments on MakeTOleClient:
  227. // If no vtbl has been constructed, make one.  Then initialize
  228. // the vtbl member of the struct to point to it.
  229. // To be more robust, one should always check that memory is allocated,
  230. // and MakeProcInstance succeeds.
  231.  
  232. LPOLECLIENTVTBL lpClientVtbl = NULL;
  233.  
  234. void MakeTOleClient( TOleClient *OleClient, HWND owner , HINSTANCE hInst )
  235. {
  236.     OleClient->hwnd = owner;
  237.     if ( !lpClientVtbl )
  238.     {
  239.         lpClientVtbl = (LPOLECLIENTVTBL) malloc( sizeof ( OLECLIENTVTBL ));
  240.         lpClientVtbl->CallBack = (TCallBack)MakeProcInstance( (FARPROC)StdCallBack,
  241.                     hInst );
  242.     }
  243.     OleClient->oleClient.lpvtbl = lpClientVtbl;
  244. }
  245.  
  246. void WMURedraw(HWND hwnd )
  247. {
  248.     bObjectLoaded = TRUE;
  249.     InvalidateRect( hwnd, NULL, TRUE );
  250.     UpdateWindow( hwnd );
  251. }
  252.  
  253. #pragma argsused
  254. int WMUCallBack( LPOLECLIENT lpOleClient ,
  255.                  OLE_NOTIFICATION oleNot,
  256.                  LPOLEOBJECT lpOleObject )
  257. {
  258.     switch ( oleNot ) {
  259.         case OLE_CHANGED:
  260.         case OLE_SAVED:
  261.             PostMessage( (( TOleClient *)lpOleClient)->hwnd ,
  262.                 WM_U_REDRAW, 0, 0L );
  263.             break;
  264.  
  265.         case OLE_CLOSED:
  266.             break;
  267.  
  268.         case OLE_QUERY_PAINT:
  269.             break;
  270.  
  271.         case OLE_RELEASE:
  272.             break;
  273.  
  274.         case OLE_RENAMED:
  275.             break;
  276.  
  277.         default:
  278.             break;
  279.     }
  280.     return TRUE;
  281. }
  282.  
  283. // create a new paint brush
  284. void CMPBrush(void)
  285. {
  286.     BackupObject();
  287.     bObjectLoaded = FALSE;
  288.  
  289.     lstrcpy( lpszObjectName, GetNextObjectName() );
  290.  
  291.     ret = OleCreate( "StdFileEditing",
  292.             (LPOLECLIENT)pOleClient,
  293.             "PBRUSH",
  294.             lhClientDoc,
  295.             szAppName,
  296.             &lpObject,
  297.             olerender_draw,
  298.             0 );
  299.  
  300.    // Creating an Ole Object is an asynchronous operation.  An
  301.     // interesting experiment is to use TDW to step into
  302.     // WaitOleNotBusy (which the following wait macro takes you
  303.     // to) and look at the user screen between message
  304.     // dispatching.  You should see pbrush gradually paint
  305.     // itself as it processes the messages which which Ole
  306.    // generates for it.  In general, if an Ole Server does not
  307.     // behave properly when creating an object, a likely cause is a
  308.     // problem with the message dispatch loop.
  309.  
  310.     wait( ret , lpObject );
  311.  
  312.     // OleSetHostNames sets the name in the server app.  If this
  313.     // was not called, pbrush would display a string with a bunch
  314.    // of % signs in it.
  315.  
  316.     ret = OleSetHostNames( lpObject, szAppName, lpszObjectName );
  317.     wait( ret , lpObject );
  318. }
  319.  
  320. void CMUndo( HWND hwnd )
  321. {
  322.     if ( lpUndoObject )        // we have a previous object
  323.         if ( lpUndoObject != lpObject )    // it is different then the current one
  324.         {
  325.             LPOLEOBJECT lpObjectToDelete = lpObject;
  326.             lpObject = lpUndoObject;
  327.             ret = OleDelete( lpObjectToDelete );
  328.             wait( ret , lpObjectToDelete );
  329.             bObjectLoaded = bUndoObjectLoaded;
  330.  
  331.             InvalidateRect( hwnd, NULL, TRUE );
  332.          UpdateWindow( hwnd );
  333.         }
  334. }
  335.  
  336. void CMCut(HWND hwnd )
  337. {
  338.     CMCopy(hwnd);
  339.     CloseCurrentOle(hwnd);
  340. }
  341.  
  342. void CMCopy( HWND hwnd )
  343. {
  344.     if ( OpenClipboard( hwnd ) && EmptyClipboard() )
  345.     {
  346.         ret = OleCopyToClipboard( lpObject );
  347.         check( ret );
  348.         CloseClipboard();
  349.     }
  350. }
  351.  
  352. void BackupObject(void)
  353. {
  354.     if ( lpObject )
  355.    {
  356.         ret = OleClone( lpObject, (LPOLECLIENT)pOleClient, lhClientDoc, szAppName, &lpUndoObject );
  357.         wait( ret, lpObject );
  358.         lstrcpy( lpszLastObjectName, lpszObjectName );
  359.         lstrcpy( lpszObjectName , GetNextObjectName() );
  360.         bUndoObjectLoaded = bObjectLoaded;
  361.     }
  362. }
  363.  
  364.  
  365. void CMPaste( HWND hwnd )
  366. {
  367.     if ( OpenClipboard( hwnd ) )
  368.     {
  369.         BackupObject();
  370.  
  371.         ret = OleCreateFromClip( "StdFileEditing",
  372.             (LPOLECLIENT)pOleClient,
  373.             lhClientDoc,
  374.             lpszObjectName,
  375.             &lpObject,
  376.             olerender_draw,
  377.             0 );
  378.         check( ret );
  379.  
  380.         bObjectLoaded = TRUE;
  381.  
  382.         CloseClipboard();
  383.         PostMessage( hwnd , WM_U_REDRAW, 0, 0L );
  384.     }
  385. }
  386.  
  387. LPSTR GetNextObjectName(void)
  388. {
  389.     static char buffer[ MAXPATH ];
  390.     wsprintf( buffer, "object #%03d", nNextObjectNum++ );
  391.     return buffer;
  392. }
  393.  
  394. void Paint( HWND hwnd, HDC hdc )
  395. {
  396.     LPOLEOBJECT lpObjectToDraw = NULL;
  397.  
  398.     if ( bObjectLoaded )
  399.         lpObjectToDraw = lpObject;
  400.     else if ( lpUndoObject )
  401.         lpObjectToDraw = lpUndoObject;
  402.  
  403.     if ( lpObjectToDraw ) {
  404.         RECT rect;
  405.         GetClientRect( hwnd, &rect );
  406.  
  407.         // Tips for OleDraw:
  408.         // OleDraw will return OLE_ERROR_OBJECT if the
  409.       // object to be drawn is invalid.  A case such as this,
  410.       // could happen if the Paint function does not get
  411.         // informed about the object being deleted, or not having
  412.         // yet been created.
  413.         // You can also get OLE_ERROR_BLANK if you draw an object
  414.         // which has not been stored.  A time when this could happen
  415.       // is when trying use OleDraw on the object after using OleCreate
  416.         // to make it, but not yet using the Servers update command
  417.         // to save the object with Ole.
  418.         ret = OleDraw( lpObjectToDraw , hdc, &rect , NULL, 0 );
  419.         wait( ret, lpObjectToDraw );
  420.     }
  421. }
  422.  
  423. void WMCreate( HWND hwnd )
  424. {
  425.     ret = OLE_OK;
  426.     lhClientDoc = 0;
  427.  
  428.     bObjectLoaded = FALSE;
  429.     bUndoObjectLoaded = FALSE;
  430.  
  431.     pOleClient = NULL;
  432.     lpObject = NULL;
  433.     lpUndoObject = NULL;
  434.  
  435.     lstrcpy( lpszDocName , "noname.ole" );
  436.     *lpszLastObjectName = 0;
  437.     *lpszObjectName = 0;
  438.     bDefDocName = TRUE;
  439.     RegisterClientDoc();
  440.     pOleClient = (TOleClient *) malloc( sizeof( TOleClient ));
  441.     if ( pOleClient )
  442.         MakeTOleClient( pOleClient, hwnd , hInst );
  443.     else memerror(  );
  444. }
  445.  
  446.  
  447. void RegisterClientDoc(void)
  448. {
  449.     // Tip for using OleRegisterClientDoc:
  450.    // If the lpszDoc parameter passed to
  451.     // OleRegisterClientDoc is not valid, (lpszPatnName in this case),
  452.     // one can get an OLE_ERROR_ADDRESS error, and the ClientDoc
  453.     // handle will not be valid.
  454.  
  455.     ret = OleRegisterClientDoc(
  456.             szAppName,
  457.             lpszDocName,
  458.             0,
  459.             &lhClientDoc );
  460.     check( ret );
  461. }
  462.  
  463. void RegFileName( LPSTR FileName )
  464. {
  465.     lstrcpy( lpszDocName , FileName );
  466.     ret = OleRegisterClientDoc( szAppName,
  467.             lpszDocName ,
  468.             0,
  469.             &lhClientDoc );
  470.     check ( ret );
  471. }
  472.  
  473. void CMActivate( HWND hwnd )
  474. {
  475.     RECT rect;
  476.     BackupObject();
  477.     GetClientRect( hwnd, &rect );
  478.     ret = OleActivate( lpObject , OLEVERB_PRIMARY, TRUE, TRUE ,
  479.             hwnd , &rect );
  480.     wait ( ret, lpObject );
  481.     PostMessage( hwnd , WM_U_REDRAW, 0, 0L );
  482. }
  483.  
  484. void WMInitMenu( HWND hwnd , WORD wParam )
  485. {
  486.     WORD wEnableUndo;
  487.     HMENU hMenu = (HMENU)wParam;
  488.  
  489.     if ( (lpObject != lpUndoObject) && ( lpUndoObject != NULL ))
  490.         wEnableUndo = MF_ENABLED;
  491.     else wEnableUndo = MF_GRAYED;
  492.     EnableMenuItem( hMenu, CM_UNDO     , wEnableUndo );
  493.     EnableMenuItem( hMenu, CM_COPY     , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  494.     EnableMenuItem( hMenu, CM_CUT      , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  495.     ret = OleQueryCreateFromClip( "StdFileEditing", olerender_draw, 0 );
  496.     EnableMenuItem( hMenu, CM_PASTE    , (( ret == OLE_OK ) ? MF_ENABLED : MF_GRAYED ));
  497.     EnableMenuItem( hMenu, CM_ACTIVATE , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  498.     EnableMenuItem( hMenu, CM_CLEAR    , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED ));
  499.  
  500.     DrawMenuBar( hwnd );
  501. }
  502.  
  503. void CMClear( HWND hwnd )
  504. {
  505.     CloseCurrentOle(hwnd);
  506. }
  507.  
  508. void CMAbout( HWND hwnd )
  509. {
  510.     MessageBox( hwnd , "OLE Client Example\nCopyright (c) 1992 Borland International, Inc.", szAppName, MB_OK );
  511. }
  512.  
  513. void CloseCurrentOle( HWND hwnd )
  514. {
  515.     bObjectLoaded = FALSE;
  516.  
  517.     if ( lpObject ) {
  518.         ret = OleDelete( lpObject );
  519.         wait( ret , lpObject );
  520.     }
  521.     if ( lpUndoObject ) {
  522.         ret = OleDelete( lpUndoObject );
  523.         wait( ret , lpObject );
  524.     }
  525.     lpObject = lpUndoObject = NULL;
  526.  
  527.     InvalidateRect( hwnd , NULL, TRUE );
  528.     UpdateWindow( hwnd );
  529. }
  530.  
  531. void memerror(void)
  532. {
  533.     MessageBox( GetFocus() , "error allocating memory", szAppName, MB_OK );
  534.     exit(1);
  535. }
  536.  
  537. // General Help:
  538. // Question: Right after closing down the server, the only part of the
  539. //   object repainted in my application is that portion of the window that
  540. //   was covered with the server program, what's going on?
  541. // Answer: When the server closes, Windows sends you a paint message to
  542. //     update that portion of your window which the server covered up.  It
  543. //     has a clipping region defined which keeps all the previous visible
  544. //     portions of your client window.  To repaint the whole window after
  545. //     a server closes, respond to the OLE_CHANGED notification in your
  546. //     callback, and force the whole window to be updated there.  Calling
  547. //     InvalidateRect would be appropriate.
  548.  
  549. // _lopen will not create a new file.  Use OpenFile( .. , OF_CREATE ) or
  550. // _lcreate for this.
  551.  
  552.