|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.