home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 17.ddi / SAMPLES / CLIDEMO / OBJECT.C_ / OBJECT.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  43.1 KB  |  1,171 lines

  1. /*
  2.  * object.c - OLE object support routines
  3.  *
  4.  * Created by Microsoft Corporation.
  5.  * (c) Copyright Microsoft Corp. 1990 - 1992  All Rights Reserved
  6.  */
  7.  
  8. //--- INCLUDES ----
  9. //The order of the includes matters for compile efficiency ... /YX
  10.  
  11. #include <windows.h>                   //- WINDOWS
  12. #include <ole.h>                       //- OLE
  13. #include "demorc.h"
  14. #include "global.h"                    //- global variables and structures
  15.  
  16. #include <shellapi.h>                  //- SHELL
  17. #include "register.h"
  18. #include "stream.h"                    //- application includes:
  19. #include "object.h"
  20. #include "clidemo.h"
  21. #include "utility.h"
  22. #include "dialog.h"
  23.  
  24.  
  25. #define  HIMETRIC_PER_INCH   2540      //- number HIMETRIC units per inch
  26.  
  27.  
  28. //--- VARIABLES ---
  29.  
  30. //--- Globals
  31. int     cOleWait     = 0;
  32.  
  33. int     giXppli;                       //- pixels per logical inch along width
  34. int     giYppli;                       //- pixels per logical inch along height
  35.  
  36.  
  37. /***************************************************************************
  38.  * CallBack()
  39.  *
  40.  * This routine will be called whenever an object has been changed,
  41.  * saved, renamed, is being painted, or an  asynchronous operation has
  42.  * completed. This routine is called by the OLE client DLL in the
  43.  * above situations.  A pointer to this function is kept in the client
  44.  * vtbl.  It is our obligation as a client application to insure that a
  45.  * pointer to this procedure is in the vtbl.
  46.  *
  47.  * IMMPORTANT: notice that we are posting messages here rather that doing
  48.  * the work right away.  Well, this is done to avoid any possibility of
  49.  * getting into another dispatch message loop.  A MessageBox woul do this!
  50.  *
  51.  * Returns int - see below
  52.  *
  53.  * The return value is generally ignored, except for these notifications:
  54.  * OLE_QUERY_PAINT and  OLE_QUERY_RETRY. For these two notifications,
  55.  * returning TRUE means continue the current operation(eg painting or retry)
  56.  * Returning FALSE means stop the current operation. This is useful as an
  57.  * object which takes a long time to paint can be interrupted in order to
  58.  * perform other operations.
  59.  ***************************************************************************/
  60.  
  61. int FAR PASCAL __export CallBack(      //- ENTRY:
  62.    LPOLECLIENT    lpClient,            //- client application pointer
  63.    OLE_NOTIFICATION flags,             //- notification code being sent
  64.    LPOLEOBJECT    lpObject             //- OLE object pointer
  65. ){                                     //- LOCAL:
  66.    APPITEMPTR     pItem;               //- application item pointer
  67.  
  68.  
  69.    pItem = (APPITEMPTR)LOWORD(lpClient);
  70.    switch (flags)
  71.    {
  72.       case OLE_CLOSED:                 //- server has closed
  73.          if (!pItem->fVisible)
  74.          {
  75.             PostMessage(hwndFrame, WM_DELETE,(WORD)pItem,0L);
  76.             Dirty(DOC_UNDIRTY);
  77.          }
  78.          SetFocus( hwndFrame );
  79.          break;
  80.  
  81.       case OLE_SAVED:                  //- server has saved object
  82.       case OLE_CHANGED:                //- object has changes
  83.          cOleWait++;
  84.          pItem->fServerChangedBounds = pItem->fVisible = TRUE;
  85.          PostMessage(pItem->hwnd, WM_CHANGE, NULL, 0L);
  86.          break;
  87.  
  88.       case OLE_RELEASE:                //- notification that an asynchronous
  89.          ToggleBlockTimer(FALSE,NULL); //- toggle timer off
  90.          if (hRetry)
  91.             PostMessage(hRetry,WM_COMMAND,IDCANCEL,0L);
  92.  
  93.          if (cOleWait)                 //- operation has completed
  94.          {
  95.             pItem->fRetry = TRUE;
  96.             if (!--cOleWait)
  97.                Hourglass(FALSE);
  98.             Release(pItem);
  99.          }
  100.          break;
  101.  
  102.       case OLE_QUERY_RETRY:          //- Continue retrying.
  103.          ToggleBlockTimer(FALSE,NULL);//- toggle timer off
  104.          if (!hRetry && pItem->fRetry)
  105.             PostMessage(hwndFrame,WM_RETRY,(WORD)pItem,0L);
  106.          return (pItem->fRetry);
  107.  
  108.       case OLE_QUERY_PAINT:          //- continue repainting
  109.          return TRUE;                //- a false return terminates either
  110.  
  111.         default:
  112.             break;
  113.     }
  114.     return 0;                          //- return value is ignored in
  115.                                        //- most cases, see header
  116. }
  117.  
  118. /***************************************************************************
  119.  * Release()
  120.  *
  121.  * Check for an error on the OLE_RELEASE notification.
  122.  **************************************************************************/
  123.  
  124. static void Release(                   //- ENTRY:
  125.    APPITEMPTR     pItem                //- Item pointer
  126. ){                                     //- LOCAL:
  127.    WORD           wParam;              //- error code parameter
  128.  
  129.    if ((wParam = OleQueryReleaseError(pItem->lpObject)) == OLE_OK)
  130.       return;
  131.  
  132.    switch (OleQueryReleaseMethod(pItem->lpObject))
  133.    {
  134.       case OLE_LNKPASTE:
  135.          pItem->fVisible = FALSE;
  136.          break;
  137.  
  138.       case OLE_CREATEFROMTEMPLATE:
  139.       case OLE_CREATE:
  140.          pItem->fVisible = FALSE;
  141.          cOleWait++;
  142.          PostMessage(hwndFrame, WM_DELETE,(WORD)pItem,1L);
  143.          Dirty(DOC_UNDIRTY);
  144.    }
  145.                                   //- post a message to the main window
  146.                                   //- which will display a message box
  147.    PostMessage(hwndFrame,WM_ERROR,wParam,NULL);
  148.  
  149. }
  150.  
  151. /***************************************************************************
  152.  *  Error()
  153.  *
  154.  *  This function checks for error conditions
  155.  *  generated by OLE API callsFor OLE_WAIT_FOR_RELEASE,
  156.  *  we keep track of the number of objects waiting, when
  157.  *  this count is zero, it is safe to exit the application.
  158.  *
  159.  *  Returns OLESTATUS -  0 if OLE_WAIT_FOR_RELEASE or OLE_OK
  160.  *                       otherwise the OLESTATUS returned after an action
  161.  *                       is taken.
  162.  *************************************************************************/
  163.  
  164. OLESTATUS FAR Error(                   //- ENTRY
  165.    OLESTATUS      olestat              //- OLE status
  166. ){
  167.  
  168.    switch (olestat)
  169.    {
  170.       case OLE_WAIT_FOR_RELEASE:
  171.          if (!cOleWait)
  172.             Hourglass(TRUE);
  173.          cOleWait++;                   //- increment wait count
  174.  
  175.       case OLE_OK:
  176.          return 0;
  177.  
  178.       case OLE_ERROR_STATIC:           //- static object
  179.          ErrorMessage(W_STATIC_OBJECT);
  180.          break;
  181.  
  182.       case OLE_ERROR_REQUEST_PICT:
  183.       case OLE_ERROR_ADVISE_RENAME:
  184.       case OLE_ERROR_DOVERB:
  185.       case OLE_ERROR_SHOW:
  186.       case OLE_ERROR_OPEN:
  187.       case OLE_ERROR_NETWORK:
  188.       case OLE_ERROR_ADVISE_PICT:
  189.       case OLE_ERROR_COMM:             //- Invalid links
  190.          InvalidLink();
  191.          break;
  192.  
  193.       case OLE_BUSY:
  194.          RetryMessage(NULL,RD_CANCEL);
  195.  
  196.       default:
  197.          break;
  198.     }
  199.     return olestat;
  200. }
  201.  
  202.  
  203. /****************************************************************************
  204.  * PreItemCreate()
  205.  *
  206.  * This routine allocates an application item structure. A pointer to this
  207.  * structure is passed as the client structure, therefore we need to
  208.  * have a pointer to the vtbl as the first entry. We are doing this
  209.  * to allow acess to the application item information during a OLE
  210.  * DLL callback.  This approach simplifies matters.
  211.  *
  212.  * Returns APPITEMPTR - a pointer to a new application item structure
  213.  *                      which can operate as a client structure.
  214.  ***************************************************************************/
  215.  
  216. APPITEMPTR FAR PreItemCreate(          //- ENTRY:
  217.    LPOLECLIENT    lpClient,            //- OLE client pointer
  218.    BOOL           fShow,               //- show/no-show flag
  219.    LHCLIENTDOC    lhcDoc               //- client document handle
  220. ){                                     //- LOCAL:
  221.    HANDLE         hitem;               //- temp handle for new item
  222.    APPITEMPTR     pItem;               //- application item pointer
  223.  
  224.  
  225.    if (hitem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(APPITEM)))
  226.       if (pItem = (APPITEMPTR)LocalLock(hitem))
  227.       {                                //- set the vtbl pointer
  228.          pItem->oleclient.lpvtbl     = lpClient->lpvtbl;
  229.          pItem->lpObjectUndo         = NULL;
  230.          pItem->fVisible             = fShow;
  231.          pItem->fServerChangedBounds = FALSE;
  232.          pItem->lhcDoc               = lhcDoc;
  233.  
  234.          return pItem;                 //- SUCCESS return
  235.       }
  236.  
  237.    ErrorMessage(E_FAILED_TO_ALLOC);
  238.    return NULL;                        //- ERROR return
  239.  
  240. }
  241.  
  242.  
  243. /***************************************************************************
  244.  * ItemWndProc()
  245.  *
  246.  * This function handles item window message processing.
  247.  * There is an item window for each OLE object. This was done to
  248.  * to simplify hit testing and repainting. These windows are child
  249.  * windows.
  250.  
  251.  * returns long - standard child routine
  252.  **************************************************************************/
  253.  
  254. long FAR PASCAL __export ItemWndProc(  //- ENTRY:
  255.    HWND           hwnd,                //- standard windows parameters
  256.    UINT       msg,
  257.    WPARAM        wParam,
  258.    LPARAM        lParam
  259. ){                                     //- LOCAL:
  260.    static POINT   dragPt;              //- Mouse drag point
  261.    static RECT    dragRect;            //- Mouse drag rectangle
  262.    static BOOL    fCaptured;           //- captured flag
  263.    APPITEMPTR     pItem;               //- application item pointer
  264.    PAINTSTRUCT    ps;                  //- paint structure
  265.    POINT          pt;                  //- point
  266.    RECT           rc;                  //- bounding rectangle
  267.  
  268.    switch (msg)
  269.    {
  270.       case WM_SIZE:
  271.          if (pItem = (APPITEMPTR)GetWindowWord(hwnd,0))
  272.          {
  273.             if (!pItem->fServerChangedBounds && pItem->otObject == OT_EMBEDDED)
  274.                ObjSetBounds(pItem);
  275.             else
  276.                pItem->fServerChangedBounds = FALSE;
  277.          }
  278.          break;
  279.  
  280.       case WM_CHANGE:
  281.          --cOleWait;
  282.          pItem = (APPITEMPTR)GetWindowWord(hwnd,0);
  283.          if (!Error(OleQueryBounds(pItem->lpObject, &rc)))
  284.          {
  285.             ConvertToClient(&rc);
  286.  
  287.             SetWindowPos(
  288.                hwnd,
  289.                NULL,
  290.                0,
  291.                0,
  292.                rc.right - rc.left + 2*GetSystemMetrics(SM_CXFRAME),
  293.                rc.bottom - rc.top + 2*GetSystemMetrics(SM_CYFRAME),
  294.                SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
  295.             );
  296.  
  297.             if (!pItem->fNew && !fLoadFile)
  298.                ShowNewWindow(pItem);
  299.             else
  300.                InvalidateRect(hwnd, NULL, TRUE);
  301.  
  302.             Dirty(DOC_DIRTY);
  303.          }
  304.          break;
  305.  
  306.       case WM_NCLBUTTONDOWN:
  307.          SetTopItem((APPITEMPTR)GetWindowWord(hwnd,0));
  308.          return (DefWindowProc(hwnd, msg, wParam, lParam));
  309.  
  310.       case WM_PAINT:
  311.          BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
  312.          GetClientRect(hwnd, &rc);
  313.          pItem = (APPITEMPTR)GetWindowWord(hwnd, 0);
  314.                                        //- Call OLE draw
  315.          Error(OleDraw(pItem->lpObject, ps.hdc, &rc, NULL, NULL));
  316.  
  317.          EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
  318.          break;
  319.  
  320.       case WM_LBUTTONDBLCLK:           //- execute a verb
  321.          ANY_OBJECT_BUSY;
  322.          ExecuteVerb(OLEVERB_PRIMARY,(APPITEMPTR)GetWindowWord(hwnd,0));
  323.          break;
  324.  
  325.       case WM_LBUTTONDOWN:
  326.          GetWindowRect(hwnd, (LPRECT)&dragRect);
  327.          ScreenToClient(hwndFrame, (LPPOINT)&dragRect);
  328.          ScreenToClient(hwndFrame, (LPPOINT)&dragRect.right);
  329.  
  330.          dragPt.x = LOWORD(lParam);
  331.          dragPt.y = HIWORD(lParam);
  332.  
  333.          ClientToScreen(hwnd, (LPPOINT)&dragPt);
  334.          ScreenToClient(hwndFrame, (LPPOINT)&dragPt);
  335.  
  336.          SetCapture(hwnd);
  337.          fCaptured = TRUE;
  338.          SetTopItem((APPITEMPTR)GetWindowWord(hwnd,0));
  339.          break;
  340.  
  341.       case WM_LBUTTONUP:
  342.          if (!fCaptured)
  343.                 break;
  344.          ReleaseCapture();
  345.          fCaptured = FALSE;
  346.          Dirty(DOC_DIRTY);
  347.          break;
  348.  
  349.       case WM_MOUSEMOVE:
  350.          if (!fCaptured)
  351.             break;
  352.          pt.x = LOWORD(lParam);
  353.          pt.y = HIWORD(lParam);
  354.  
  355.          ClientToScreen(hwnd, (LPPOINT)&pt);
  356.          ScreenToClient(hwndFrame, (LPPOINT)&pt);
  357.  
  358.          OffsetRect(
  359.                (LPRECT)&dragRect,
  360.                pt.x - dragPt.x,
  361.                pt.y - dragPt.y
  362.          );
  363.  
  364.          MoveWindow(
  365.             hwnd,
  366.             dragRect.left, dragRect.top,
  367.             dragRect.right - dragRect.left,
  368.             dragRect.bottom - dragRect.top, TRUE
  369.          );
  370.  
  371.          dragPt.x = pt.x;
  372.          dragPt.y = pt.y;
  373.          break;
  374.  
  375.       default:
  376.          return (DefWindowProc(hwnd, msg, wParam, lParam));
  377.    }
  378.    return 0L;
  379.  
  380. }
  381.  
  382. /****************************************************************************
  383.  * PostItemCreate()
  384.  *
  385.  * This function creates a child window which will contain the newly
  386.  * created OLE object. A pointer to our item information is stored in the
  387.  * extra bytes of this window. This is where we internally keep track
  388.  * of information related to the object as well as the
  389.  * pointer to the object for subsequent OLE API calls.  This routine is
  390.  * called after an OLE object has been created by the client library.
  391.  *
  392.  * Returns BOOL - TRUE if application item has been created.
  393.  ****************************************************************************/
  394.  
  395. BOOL FAR PostItemCreate(               //- ENTRY:
  396.    LPOLEOBJECT    lpObject,            //- OLE object pointer
  397.    long           otObject,            //- OLE object type
  398.    LPRECT         lprcObject,          //- object bounding rect
  399.    APPITEMPTR     pItem                //- application item pointer
  400. ){                                     //- LOCAL:
  401.    int            i;                   //- index
  402.    RECT           rc;                  //- bounding rectangle
  403.    char           pData[OBJECT_LINK_MAX];//- copy of link data
  404.  
  405.    if (lprcObject)                     //- if the size of the objects
  406.       rc = *lprcObject;                //- bounding rectangle is not
  407.    else if (OleQueryBounds(lpObject, &rc) == OLE_OK)
  408.       ConvertToClient(&rc);
  409.    else
  410.       SetRect(&rc, 0, 0, 0, 0);
  411.  
  412.    if (!(pItem->hwnd = CreateWindow(   //- Create the child window
  413.          szItemClass, "",
  414.          WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME,
  415.          rc.left,rc.top,
  416.          rc.right - rc.left + 2 * GetSystemMetrics(SM_CXFRAME),
  417.          rc.bottom - rc.top + 2 * GetSystemMetrics(SM_CYFRAME),
  418.          hwndFrame, NULL, hInst, NULL
  419.    ))) goto Error;
  420.  
  421.                                        //- in windows extra bytes
  422.    SetWindowWord(pItem->hwnd, 0, (WORD)pItem);
  423.  
  424.    pItem->otObject = otObject;
  425.    pItem->lpObject = lpObject;
  426.    pItem->fRetry  = TRUE;
  427.  
  428.    if( pItem->otObject == OT_EMBEDDED )//- if object is embedded tell library
  429.    {                                   //- the container name and object name.
  430.       int cb = CBOBJNAMEMAX;           //- The name will be the server window title.
  431.       char sz[CBOBJNAMEMAX];           //- when the object is edited.
  432.  
  433.       OleQueryName(lpObject, (LPSTR)sz, &cb );
  434.  
  435.       WaitForObject(pItem);
  436.       Error(OleSetHostNames(lpObject, (LPSTR)szAppName, (LPSTR)sz ));
  437.       WaitForObject(pItem);
  438.    }
  439.    else if (pItem->otObject == OT_LINK)//- if the object is linked
  440.    {                                   //- retrieve update options
  441.  
  442.       WaitForObject(pItem);
  443.       if(Error(OleGetLinkUpdateOptions(pItem->lpObject, &pItem->uoObject)))
  444.          goto Error;
  445.  
  446.       if (ObjGetData(pItem,pData))
  447.       {
  448.          for (i=0; pData[i];i++);      //- Skip past the server name
  449.          pItem->aLinkName = AddAtom(&pData[++i]);
  450.       }
  451.       else
  452.          pItem->aLinkName = AddAtom("");
  453.    }
  454.    iObjects++;
  455.    Dirty(DOC_DIRTY);
  456.                                        //- a user interface recommendations.
  457.    return TRUE;                        //- SUCCESS return
  458.  
  459. Error:                                 //- ERROR Tag
  460.  
  461.    ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
  462.    FreeAppItem(pItem);
  463.  
  464.    return FALSE;                       //- ERROR return
  465.  
  466. }
  467.  
  468. /***************************************************************************
  469.  * ConvertToClient()
  470.  *
  471.  * This function will convert to client from himetric.
  472.  **************************************************************************/
  473.  
  474. void FAR ConvertToClient(              //- ENTRY:
  475.    LPRECT         lprc                 //- pointer to bounding rectangle
  476. ){                                     //- LOCAL
  477.  
  478.    //- If we have an empty rectangle then set the default size
  479.    if (!(lprc->left || lprc->top || lprc->right || lprc->bottom))
  480.       SetRect(lprc, 0, 0, CXDEFAULT, CYDEFAULT);
  481.    else
  482.    {
  483.       //- We got the himetric units, converts them to pixels now.
  484.       lprc->right   = MulDiv (giXppli, (lprc->right - lprc->left),
  485.                           HIMETRIC_PER_INCH);
  486.  
  487.       lprc->bottom  = MulDiv (giYppli, (lprc->top - lprc->bottom),
  488.                           HIMETRIC_PER_INCH);
  489.  
  490.       lprc->left    = 0;
  491.       lprc->top     = 0;
  492.     }
  493. }
  494.  
  495. /***************************************************************************
  496.  * ObjInsert()
  497.  *
  498.  * Query the user for object type to insert and insert the new OLE object
  499.  ***************************************************************************/
  500.  
  501. void FAR ObjInsert(                    //- ENTRY:
  502.    LHCLIENTDOC    lhcDoc,              //- OLE document handle
  503.    LPOLECLIENT    lpClient             //- pointer to OLE client structure
  504. ){                                     //- LOCAL:
  505.    FARPROC        lpfnInsertNew;       //- Insert New dialog bos instance thunk
  506.    LPOLEOBJECT    lpObject;            //- pointer to OLE object
  507.    APPITEMPTR     pItem;               //- item pointer
  508.    char           szServerName[CBPATHMAX];//- Class name for OleCreate()
  509.    char           szClassName[CBPATHMAX];//- Class name for OleCreate()
  510.    char           szTmp[CBOBJNAMEMAX]; //- buffer to unique object name
  511.  
  512.    lpfnInsertNew    = MakeProcInstance(fnInsertNew, hInst);
  513.  
  514.    if (DialogBoxParam(hInst, MAKEINTRESOURCE(DTCREATE),hwndFrame,
  515.             lpfnInsertNew, (long)((LPSTR)szClassName)) != IDCANCEL)
  516.    {
  517.       if (pItem = PreItemCreate(lpClient, FALSE, lhcDoc))
  518.       {
  519.          RegGetClassId(szServerName, szClassName);
  520.          pItem->aServer = AddAtom(szServerName);
  521.          if ( Error( OleCreate(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),
  522.             (LPSTR)szClassName, lhcDoc,CreateNewUniqueName(szTmp),
  523.             &lpObject,olerender_draw, 0)))
  524.          {
  525.             ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  526.             FreeAppItem(pItem);
  527.          }
  528.          else
  529.             PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
  530.       }
  531.    }
  532.  
  533.    FreeProcInstance(lpfnInsertNew);
  534.  
  535. }
  536.  
  537. /***************************************************************************
  538.  *  ObjDelete()
  539.  *
  540.  * Delete an OLE object. For this application, all OLE objects
  541.  * are associated with a child window; therefore the window must be
  542.  * destroyed.
  543.  *
  544.  * NOTE: There is one case when we call OleRelease and the other when
  545.  * we call OleDelete.  We call OleRelease when we are deregistering
  546.  * a document and OleDelete when removing an object from a document.
  547.  **************************************************************************/
  548.  
  549. void FAR ObjDelete(                    //- ENTRY:
  550.    APPITEMPTR     pItem,               //- pointer to application item
  551.    BOOL           fDelete              //- delete or release flag
  552. ){                                     //- LOCAL:
  553.  
  554.    if (pItem->lpObjectUndo)
  555.    {
  556.       Error(OleDelete(pItem->lpObjectUndo));
  557.                                        //- wait for asynchronous operation
  558.       WaitForObject(pItem);
  559.    }
  560.  
  561.    if (fDelete ? Error(OleDelete(pItem->lpObject))
  562.                      : Error(OleRelease(pItem->lpObject)))
  563.    {
  564.       ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
  565.       return;                          //- ERROR return
  566.    }
  567.  
  568.    if (pItem->fVisible)
  569.    {
  570.       ShowWindow(pItem->hwnd, SW_HIDE);
  571.       pItem->fVisible = FALSE;
  572.    }
  573.                                        //- the operation has to complete
  574.    WaitForObject(pItem);               //- before the application structure
  575.  
  576.    FreeAppItem(pItem);
  577.    iObjects--;
  578.  
  579. }
  580.  
  581.  
  582. /***************************************************************************
  583.  *  ObjPaste()
  584.  *
  585.  *  This function obtains an object from the clipboard.
  586.  *  Handles both embedded and linked objects. An item window is
  587.  *  created for each new object.
  588.  *
  589.  *  Returns BOOL  - TRUE if object was pasted succesfully.
  590.  **************************************************************************/
  591.  
  592. void FAR ObjPaste(                     //- ENTRY:
  593.    BOOL           fPaste,              //- Paste/PasteLink flag
  594.    LHCLIENTDOC    lhcDoc,              //- client document handle
  595.    LPOLECLIENT    lpClient             //- pointer to client
  596. ){                                     //- LOCAL:
  597.    LPOLEOBJECT    lpObject;            //- object pointer
  598.    long           otObject;            //- object type
  599.    APPITEMPTR     pItem;               //- application item pointer
  600.    char           szTmp[CBOBJNAMEMAX]; //- temporary object name string
  601.  
  602.    if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
  603.       return;                          //- ERROR return
  604.  
  605.    if (!OpenClipboard(hwndFrame))
  606.       goto Error;                      //- ERROR jump
  607.  
  608.  
  609.    if (fPaste)                         //- PASTE the object.
  610.    {                                   //- Try "StdFileEditing" protocol
  611.       if (Error(OleCreateFromClip(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),lhcDoc,
  612.          CreateNewUniqueName(szTmp),&lpObject, olerender_draw,0)))
  613.       {
  614.                                        //- next try "Static" protocol
  615.          if (Error(OleCreateFromClip(
  616.                   STATICP, (LPOLECLIENT)&(pItem->oleclient), lhcDoc,
  617.                   CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  618.             goto Error;               //- ERROR jump
  619.       }
  620.    }
  621.    else
  622.    {                                   //- LINK therefore must be
  623.                                        // "STdFileEditing" protocol
  624.         if (Error(OleCreateLinkFromClip(
  625.             STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient), lhcDoc,
  626.             CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  627.             goto Error;                //- ERROR jump
  628.    }
  629.  
  630.    OleQueryType(lpObject, &otObject);
  631.    CloseClipboard();
  632.  
  633.    if (!PostItemCreate(lpObject, otObject, NULL, pItem))
  634.       return;                          //- ERROR return
  635.  
  636.    ShowNewWindow(pItem);
  637.    return;                             //- SUCCESS return
  638.  
  639.  
  640. Error:                                 //- TAG Error
  641.  
  642.    ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
  643.    CloseClipboard();
  644.    FreeAppItem(pItem);
  645.  
  646.    return;                             //- ERROR return
  647.  
  648. }
  649.  
  650. /***************************************************************************
  651.  * ObjCopy()
  652.  *
  653.  * This function places an OLE object on the clipboard via the \
  654.  * OleCopyToClipboard() function.
  655.  *
  656.  * Returns BOOL - TRUE if object successfully placed on clipboard
  657.  **************************************************************************/
  658.  
  659. BOOL FAR ObjCopy(                      //- ENTRY:
  660.    APPITEMPTR     pItem                //- pointer to app item
  661. ){                                     //- LOCAL:
  662.    BOOL           fReturn = TRUE;      //- return value
  663.  
  664.    if (!OpenClipboard(hwndFrame))
  665.       return FALSE;                    //- ERROR return
  666.  
  667.    EmptyClipboard();
  668.  
  669.    if (Error(OleCopyToClipboard(pItem->lpObject)))
  670.       fReturn = FALSE;                 //- prepare for ERROR out
  671.  
  672.    CloseClipboard();
  673.    return fReturn;                     //- ERROR or SUCCESS
  674.  
  675. }
  676.  
  677. /***************************************************************************
  678.  *  ObjCreateFromTemplate()
  679.  *
  680.  *  Creates an embedded object from file.
  681.  **************************************************************************/
  682.  
  683. void FAR ObjCreateFromTemplate(        //- ENTRY:
  684.    LHCLIENTDOC    lhcDoc,              //- client document handle
  685.    LPOLECLIENT    lpClient             //- client vtbl. pointer
  686. ){                                     //- LOCAL:
  687.    LPOLEOBJECT    lpObject;            //- OLE object pointer
  688.    APPITEMPTR     pItem;               //- application item pointer
  689.    char           szTmp[CBOBJNAMEMAX]; //- temporary object name string
  690.    char           szFileName[CBPATHMAX];//- file name string
  691.  
  692.    *szFileName = NULL;
  693.  
  694.    if (!OfnGetName(hwndFrame, szFileName, IDM_INSERTFILE))
  695.       return;                          //- ERROR operation aborted by user
  696.  
  697.    if (!(pItem = PreItemCreate(lpClient, FALSE, lhcDoc)))
  698.       return;                          //- ERROR
  699.  
  700.    if (Error(OleCreateFromTemplate(STDFILEEDITING, (LPOLECLIENT)pItem, szFileName,
  701.          lhcDoc, CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  702.    {
  703.       ErrorMessage(E_CREATE_FROM_TEMPLATE);
  704.       FreeAppItem(pItem);
  705.       return;                          //- ERROR
  706.    }
  707.  
  708.    PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
  709.  
  710. }                                      //- SUCCESS
  711.  
  712.  
  713. /****************************************************************************
  714.  * ObjGetData()
  715.  *
  716.  * Get the object link data.  The data that is retrieved from OLE is copied
  717.  * into lpLinkData if lpLinkData is not NULL.  Otherwise, space is dynamically
  718.  * allocated or reallocated; space is allocated if pItem->lpLinkData is NULL
  719.  * otherwise the pointer is reallocated. The data is returned is freed if
  720.  * there has been an OLE_WARN_DELETE_DATA error.
  721.  ***************************************************************************/
  722.  
  723. BOOL FAR ObjGetData(                   //- ENTRY:
  724.    APPITEMPTR     pItem,               //- OLE object
  725.    LPSTR          lpLinkData           //- pointer to linkdata
  726. ){                                     //- LOCAL:
  727.    HANDLE         hData;               //- handle to OLE link data
  728.    LPSTR          lpData;              //- pointer to OLE link data
  729.    LPSTR          lpWork;              //- copy of OLE link data
  730.    BOOL           fFree = FALSE;       //- free OLE memory flag
  731.    LONG           lSize;               //- size of OLE link data
  732.    int            i;
  733.  
  734.    switch (Error(OleGetData(pItem->lpObject,
  735.       (pItem->otObject == OT_LINK ? vcfLink : vcfOwnerLink), &hData)))
  736.    {
  737.       case OLE_WARN_DELETE_DATA:
  738.          fFree = TRUE;
  739.       case OLE_OK:
  740.          if(lpData = GlobalLock(hData))
  741.          {
  742.                                        //- copy the link data to new buffer
  743.             lSize=SizeOfLinkData(lpData);
  744.  
  745.             if (!lpLinkData)
  746.             {
  747.                if (!pItem->lpLinkData)  //- allocate
  748.                   AllocLinkData(pItem,lSize);
  749.                else                     //- otherwise reallocate
  750.                   ReallocLinkData(pItem,lSize);
  751.                lpWork = pItem->lpLinkData;
  752.             }
  753.             else
  754.                lpWork = lpLinkData;
  755.  
  756.             if (lpWork)
  757.                for (i=0L; i<(int)lSize; i++)
  758.                   *(lpWork+i)=*(lpData+i);
  759.  
  760.             GlobalUnlock(hData);       //- free the linked data as needed
  761.             if (fFree)
  762.                GlobalFree(hData);
  763.  
  764.             return TRUE;               //- SUCCESS
  765.          }
  766.       default:
  767.          return FALSE;                 //- FAILURE
  768.    }
  769.  
  770. }
  771.  
  772. /***************************************************************************
  773.  * ObjChangeLink()
  774.  *
  775.  * Change the linkdata.  This routine will change the document portion of
  776.  * link data to lpDoc.  The old linkdata is expected to be in
  777.  * lpaItem->lpLinkData
  778.  **************************************************************************/
  779.  
  780. void FAR ObjChangeLinkData(            //- ENTRY:
  781.    APPITEMPTR     pItem,               //- OLE object
  782.    LPSTR          lpDoc                //- document name
  783. ){                                     //- LOCAL:
  784.    LONG           lSize;               //- used to link data size
  785.    LPSTR          lpLinkData;          //- OLE link data pointer
  786.    static char    pWork[OBJECT_LINK_MAX]; //- used to construct new link data
  787.    int            i;                   //- index
  788.  
  789.    pItem->aLinkName = AddAtom(lpDoc);
  790.  
  791.    for (
  792.       lpLinkData = pItem->lpLinkData, i=0;
  793.       pWork[i] = *lpLinkData;
  794.       lpLinkData++, i++
  795.    );
  796.                                        //- into working buffer.
  797.    lstrcpy((LPSTR)&pWork[++i],lpDoc);  //- copy new document name.
  798.  
  799.    for (; pWork[i]; i++);              //- skip to end of document name
  800.    for (++lpLinkData;*lpLinkData;lpLinkData++);
  801.                                        //- copy item name.
  802.    lstrcpy((LPSTR)&pWork[++i],++lpLinkData);
  803.    for (; pWork[i]; i++);              //- skip to end of buffer
  804.                                        //- which is the end of item info.
  805.    pWork[++i] = NULL;                  //- add extra null.
  806.  
  807.    lSize = SizeOfLinkData(pWork);      //- reallocate space so there is
  808.    ReallocLinkData(pItem,lSize);       //- a properly sized block of info
  809.                                        //- to send the linked data to the
  810.    if (lpLinkData = pItem->lpLinkData) //- OLE DLL.
  811.       for (i=0; i<(int)lSize; i++)     //- copy new linkdata into this space
  812.          *lpLinkData++ = pWork[i];
  813.    else
  814.       return;                          //- ERROR return
  815.  
  816.    Error(OleSetData(pItem->lpObject, vcfLink,
  817.          (HANDLE)GlobalHandle(HIWORD(pItem->lpLinkData))));
  818.  
  819. }                                      //- SUCCESS return
  820.  
  821. /****************************************************************************
  822.  * ObjSaveUndo()
  823.  *
  824.  * Clone the OLE object so that any changes to object can be undone if the
  825.  * user choses to exit without update.
  826.  ***************************************************************************/
  827.  
  828. void FAR ObjSaveUndo(                  //- ENTRY:
  829.    APPITEMPTR     pItem                //- application item
  830. ){                                     //- LOCAL:
  831.    char           szTmp[CBOBJNAMEMAX]; //- holder of object name
  832.    LPSTR          lpClone;             //- pointer to clond object name
  833.    int            i;                   //- index
  834.  
  835.    if (!pItem->lpObjectUndo)
  836.    {
  837.       i=CBOBJNAMEMAX;
  838.       OleQueryName(pItem->lpObject, szTmp, &i);
  839.                                        //- give clone a unique name by
  840.                                        //- altering object name prefix.
  841.       for (lpClone = OBJCLONE, i=0; *lpClone; szTmp[i++] = *lpClone++);
  842.  
  843.       if (Error(OleClone(pItem->lpObject, (LPOLECLIENT)pItem,
  844.          pItem->lhcDoc, szTmp, &(pItem->lpObjectUndo))))
  845.       return;                          //- ERROR return
  846.  
  847.       pItem->otObjectUndo  = pItem->otObject;
  848.       pItem->uoObjectUndo  = pItem->uoObject;
  849.       pItem->aLinkUndo     = pItem->aLinkName;
  850.  
  851.       GetClientRect(pItem->hwnd, &pItem->rect);
  852.  
  853.       if (OleQueryOpen(pItem->lpObject) == OLE_OK)
  854.          pItem->fOpen = TRUE;
  855.  
  856.    }
  857.  
  858. }                                      //- SUCCESS return
  859.  
  860. /****************************************************************************
  861.  * ObjUndo()
  862.  *
  863.  * Restore an object to its state before changes.  The lpObject Undo is a
  864.  * clone to the original object with a different name, therefore, all we
  865.  * have to do is rename that object and ditch the changed object.
  866.  ***************************************************************************/
  867.  
  868. void FAR ObjUndo(                      //- ENTRY:
  869.    APPITEMPTR     pItem                //- application item
  870. ){                                     //- LOCAL:
  871.    char           szTmp[CBOBJNAMEMAX]; //- object name holder
  872.    int            i;                   //- index
  873.  
  874.    OleQueryName(pItem->lpObject, szTmp, &i);
  875.    if (Error(OleDelete(pItem->lpObject)))
  876.       return;                          //- ERROR return
  877.                                        //- reset app item vars
  878.    pItem->lpObject      = pItem->lpObjectUndo;
  879.    pItem->otObject      = pItem->otObjectUndo;
  880.    pItem->uoObject      = pItem->uoObjectUndo;
  881.    pItem->aLinkName     = pItem->aLinkUndo;
  882.    pItem->lpObjectUndo  = (LPOLEOBJECT)NULL;
  883.    pItem->otObjectUndo  = (LONG)NULL;
  884.  
  885.    if (Error(OleRename(pItem->lpObject,szTmp)))
  886.       return;                          //- ERROR return
  887.  
  888.    if (pItem->fOpen)
  889.    {
  890.       Error(OleReconnect(pItem->lpObject));
  891.       pItem->fOpen = FALSE;
  892.    }
  893.  
  894.    SetWindowPos(
  895.       pItem->hwnd,
  896.       NULL, 0, 0,
  897.       pItem->rect.right - pItem->rect.left + 2*GetSystemMetrics(SM_CXFRAME),
  898.       pItem->rect.bottom - pItem->rect.top + 2*GetSystemMetrics(SM_CYFRAME),
  899.       SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
  900.    );
  901.  
  902.    InvalidateRect(pItem->hwnd,NULL,TRUE);
  903.  
  904. }                                      //- SUCCESS return
  905.  
  906.  
  907. /****************************************************************************
  908.  * ObjDelUndo()
  909.  *
  910.  * Delete the undo object if the user is happy with the changes he/she made.
  911.  ***************************************************************************/
  912.  
  913. void FAR ObjDelUndo(                   //- ENTRY:
  914.    APPITEMPTR     pItem                //- application item
  915. ){
  916.  
  917.    if (Error(OleDelete(pItem->lpObjectUndo)))
  918.       return;                          //- ERROR return
  919.  
  920.    pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
  921.    pItem->otObjectUndo = (LONG)NULL;
  922.    DeleteAtom(pItem->aLinkUndo);
  923.    pItem->lpObjectUndo = NULL;
  924.  
  925. }                                      //- SUCCESS return
  926.  
  927. /****************************************************************************
  928.  * ObjFreeze()
  929.  *
  930.  * Convert an object to a static object.
  931.  ***************************************************************************/
  932.  
  933. void FAR ObjFreeze(                    //- ENTRY:
  934.    APPITEMPTR     pItem                //- application item
  935. ){                                     //- LOCAL:
  936.    char           szTmp[CBOBJNAMEMAX]; //- temporary object name
  937.    LPSTR          lpTemp;              //- temporary prefix string
  938.    LPOLEOBJECT    lpObjectTmp;         //- temporary object pointer
  939.    int            i;                   //- index
  940.  
  941.    i=CBOBJNAMEMAX;
  942.    OleQueryName(pItem->lpObject, szTmp, &i);
  943.                                        //- create a unique name by changing
  944.                                        //- the object name prefix
  945.    for (lpTemp = OBJTEMP, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
  946.  
  947.                                        //- this API creates a static object
  948.    if (Error(OleObjectConvert(pItem->lpObject, STATICP, (LPOLECLIENT)pItem,
  949.       pItem->lhcDoc, szTmp, &lpObjectTmp)))
  950.       return;
  951.                                        //- delete old object
  952.    if (Error(OleDelete(pItem->lpObject)))
  953.       return;
  954.  
  955.    WaitForObject(pItem);
  956.  
  957.    pItem->lpObject = lpObjectTmp;
  958.    pItem->otObject = OT_STATIC;
  959.    pItem->uoObject = -1L;
  960.  
  961.    for (lpTemp = OBJPREFIX, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
  962.    if (Error(OleRename(pItem->lpObject,szTmp)))
  963.       return;
  964.  
  965.  
  966. }
  967.  
  968. /***************************************************************************
  969.  *  ObjCreateWrap()
  970.  *
  971.  * Create a wrapped object from the drag and drop feature of the 3.1 shell.
  972.  * NOTE: We are assuming that only one file has been dropped.  See the SDK
  973.  * documentation for instructions on how to deal with multiple files.
  974.  ***************************************************************************/
  975.  
  976. void FAR ObjCreateWrap(                //- ENTRY:
  977.    HANDLE         hdrop,               //- handle to dropped object
  978.    LHCLIENTDOC    lhcDoc,              //- document handle
  979.    LPOLECLIENT    lpClient             //- pointer to client structure
  980. ){                                     //- LOCAL:
  981.    char           szDragDrop[CBPATHMAX];//- Drag and drop file name
  982.    LPOLEOBJECT    lpObject;            //- pointer to OLE object
  983.    POINT          pt;                  //- position of dropped object
  984.    RECT           rc;                  //- object size and position
  985.    char           szTmp[CBOBJNAMEMAX]; //- buffer for unique object name
  986.    APPITEMPTR     pItem;               //- application item pointer
  987.    int            x,y;                 //- icon sizes
  988.  
  989.    x = GetSystemMetrics(SM_CXICON) / 2;
  990.    y = GetSystemMetrics(SM_CYICON) / 2;
  991.                                        //- Get the drag and drop filename
  992.                                        //- position
  993.    DragQueryPoint(hdrop, &pt);
  994.    DragQueryFile(hdrop, 0, szDragDrop, CBPATHMAX);
  995.    DragFinish(hdrop);
  996.  
  997.    SetRect(&rc, pt.x - x, pt.y - y, pt.x + x, pt.y + y);
  998.  
  999.    if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
  1000.       return;                          //- ERROR return
  1001.                                        //- create OLE object
  1002.    if (Error(OleCreateFromFile(STDFILEEDITING, (LPOLECLIENT)pItem,
  1003.          "Package", szDragDrop, lhcDoc, CreateNewUniqueName(szTmp),
  1004.          &lpObject, olerender_draw, 0)))
  1005.    {
  1006.       ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  1007.       FreeAppItem(pItem);
  1008.       return;                          //- ERROR return
  1009.    }
  1010.  
  1011.    if (PostItemCreate(lpObject, OT_EMBEDDED, &rc, pItem))
  1012.       ShowNewWindow(pItem);
  1013.  
  1014. }                                      //- SUCCESS return
  1015.  
  1016. /***************************************************************************
  1017.  *  UpdateObjectMenuItem()
  1018.  *
  1019.  *  Add an object popup menu for the chosen object if multiple verbs exist.
  1020.  *  The registration system is used to determine which verbs exist for the
  1021.  *   given object.
  1022.  **************************************************************************/
  1023.  
  1024. void FAR UpdateObjectMenuItem(         //- ENTRY:
  1025.    HMENU       hMenu                   //- main menu
  1026. ){                                     //- LOCAL
  1027.    int         cVerbs;                 //- verb
  1028.    APPITEMPTR  pItem;                  //- application item ponter
  1029.    DWORD       dwSize = KEYNAMESIZE;
  1030.    char        szClass[KEYNAMESIZE], szBuffer[200];
  1031.    char        szVerb[KEYNAMESIZE];
  1032.    HANDLE      hPopupNew=NULL;
  1033.    HKEY        hkeyTemp;
  1034.    char        pLinkData[OBJECT_LINK_MAX];
  1035.                                        //- delete current item and submenu
  1036.    DeleteMenu(hMenu, POS_OBJECT, MF_BYPOSITION );
  1037.  
  1038.    if (!(pItem = GetTopItem()) )
  1039.       goto Error;                      //- ERROR jump
  1040.    else if (!pItem->fVisible)
  1041.       goto Error;                      //- ERROR jump
  1042.                                        //- if STATIC ?
  1043.    if ((pItem->otObject != OT_EMBEDDED) && (pItem->otObject != OT_LINK))
  1044.       goto Error;                      //- ERROR jump
  1045.  
  1046.    if (!ObjGetData(pItem, pLinkData))  //- get linkdata as key reg database
  1047.       goto Error;                      //- ERROR jump
  1048.                                        //- open reg database
  1049.    if (RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hkeyTemp))
  1050.       goto Error;                      //- ERROR jump
  1051.                                        //- check if class is reg-db
  1052.    if (RegQueryValue(HKEY_CLASSES_ROOT, pLinkData, szClass, &dwSize))
  1053.    {
  1054.       RegCloseKey(hkeyTemp);
  1055.       goto Error;                      //- ERROR jump
  1056.    }
  1057.  
  1058.    for (cVerbs=0; ;++cVerbs)           //- extract all verbs from reg-db
  1059.    {
  1060.       dwSize = KEYNAMESIZE;
  1061.       wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
  1062.                                      (LPSTR)pLinkData,cVerbs);
  1063.  
  1064.       if (RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &dwSize))
  1065.          break;
  1066.  
  1067.       if (!hPopupNew)
  1068.          hPopupNew = CreatePopupMenu();
  1069.  
  1070.       InsertMenu(hPopupNew,(UINT) -1, (UINT)MF_BYPOSITION,(UINT) IDM_VERBMIN+cVerbs, szVerb);
  1071.    }
  1072.  
  1073.    //- NOTE: For International versions the following  verb menu
  1074.    //- may need to be formatted differently.
  1075.  
  1076.    switch (cVerbs)                     //- determine how many verbs found
  1077.    {
  1078.       case 0:                          //- none
  1079.          wsprintf(szBuffer, "Edit %s %s", (LPSTR)szClass, (LPSTR)"&Object");
  1080.          InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
  1081.          break;
  1082.  
  1083.       case 1:                          //- one
  1084.          wsprintf(szBuffer, "%s %s %s", (LPSTR)szVerb, (LPSTR)szClass,
  1085.             (LPSTR)"&Object");
  1086.          DestroyMenu(hPopupNew);
  1087.          InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
  1088.          break;
  1089.  
  1090.      default:                          //- > 1
  1091.          wsprintf(szBuffer, "%s %s", (LPSTR)szClass, (LPSTR)"&Object");
  1092.          InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION | MF_POPUP, hPopupNew, szBuffer);
  1093.          EnableMenuItem(hMenu, POS_OBJECT, MF_ENABLED|MF_BYPOSITION);
  1094.          break;
  1095.    }
  1096.  
  1097.    RegCloseKey(hkeyTemp);              //- close reg-db
  1098.    return;                             //- SUCCESS return
  1099.  
  1100. Error:                                 //- ERROR tag
  1101.  
  1102.    InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, NULL, "&Object");
  1103.    EnableMenuItem(hMenu, POS_OBJECT, MF_GRAYED | MF_BYPOSITION);
  1104.  
  1105. }                                      //- ERROR return
  1106.  
  1107. /***************************************************************************
  1108.  *  ExecuteVerb()
  1109.  *
  1110.  *  Execute the verb for the given object.
  1111.  ***************************************************************************/
  1112.  
  1113. void FAR ExecuteVerb(                  //- ENTRY:
  1114.    int iVerb,                          //- verb
  1115.    APPITEMPTR pItem                    //- application item pointer
  1116. ){                                     //- LOCAL
  1117.    RECT        rc;                     //- holds client area bounding rect
  1118.  
  1119.    if (pItem->otObject == OT_STATIC)   //- if the object is static beep
  1120.    {
  1121.       ErrorMessage(W_STATIC_OBJECT);
  1122.       return;                          //- return
  1123.    }
  1124.                                        //- get cliet area rectangle
  1125.    GetClientRect(hwndFrame, (LPRECT)&rc);
  1126.                                        //- execute OLE verb
  1127.    if (Error(OleActivate(pItem->lpObject, iVerb, TRUE, TRUE, hwndFrame, &rc)))
  1128.       return;
  1129.  
  1130.    WaitForObject(pItem);               //- wait for async. operation
  1131.  
  1132.  
  1133. }                                      //- SUCCESS return
  1134.  
  1135. /****************************************************************************
  1136.  * ObjSetBounds
  1137.  *
  1138.  * Set the object bounds.  The object bounds are the child windos bounding
  1139.  * rectangle.  OLE servers recieve need the bounding rectangle in HIMETRIC
  1140.  * coordinates.  So, we convert from screen coordinates to HIMETRIC.
  1141.  *
  1142.  * Returns BOOL - TRUE if successful.
  1143.  ***************************************************************************/
  1144.  
  1145. BOOL FAR ObjSetBounds(                 //- ENTRY:
  1146.    APPITEMPTR     pItem                //- application item pointer
  1147. ){                                     //- LOCAL:
  1148.    RECT           itemRect;            //- bounding rectangle
  1149.  
  1150.    GetWindowRect(pItem->hwnd,&itemRect);//- get item window react
  1151.  
  1152.    itemRect.right -= GetSystemMetrics(SM_CXFRAME);
  1153.    itemRect.left += GetSystemMetrics(SM_CXFRAME);
  1154.    itemRect.top += GetSystemMetrics(SM_CYFRAME);
  1155.    itemRect.bottom -= GetSystemMetrics(SM_CYFRAME);
  1156.  
  1157.    itemRect.right  = MulDiv ((itemRect.right - itemRect.left),
  1158.                         HIMETRIC_PER_INCH, giXppli);
  1159.    itemRect.bottom = - MulDiv((itemRect.bottom - itemRect.top),
  1160.                         HIMETRIC_PER_INCH, giYppli);
  1161.    itemRect.top    = NULL;
  1162.    itemRect.left   = NULL;
  1163.                                        //- set the rect for the server
  1164.    if (Error(OleSetBounds(pItem->lpObject,(LPRECT)&itemRect)))
  1165.       return FALSE;                    //- ERROR return
  1166.  
  1167.    WaitForObject(pItem);               //- wait for async. operation
  1168.    return TRUE;                        //- SUCCESS return
  1169.  
  1170. }
  1171.