Annotation of mstools/samples/ole/clidemo/object.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.