|
|
1.1 ! root 1: /* ! 2: OLE SERVER DEMO ! 3: Obj.c ! 4: ! 5: This file contains object methods and various object-related support ! 6: functions. ! 7: ! 8: (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved ! 9: */ ! 10: ! 11: /* ! 12: Important Note: ! 13: ! 14: No method should ever dispatch a DDE message or allow a DDE message to ! 15: be dispatched. ! 16: Therefore, no method should ever enter a message dispatch loop. ! 17: Also, a method should not show a dialog or message box, because the ! 18: processing of the dialog box messages will allow DDE messages to be ! 19: dispatched. ! 20: */ ! 21: ! 22: ! 23: #define SERVERONLY ! 24: #include <windows.h> ! 25: #include <ole.h> ! 26: ! 27: #include "srvrdemo.h" ! 28: ! 29: ! 30: ! 31: // Static functions. ! 32: static HBITMAP GetBitmap (LPOBJ lpobj); ! 33: static HANDLE GetLink (LPOBJ lpobj); ! 34: static HANDLE GetMetafilePict (LPOBJ lpobj); ! 35: static HANDLE GetEnhMetafile (LPOBJ lpobj); ! 36: static HANDLE GetNative (LPOBJ lpobj); ! 37: static INT GetObjNum (LPOBJ lpobj); ! 38: static HANDLE GetText (LPOBJ lpobj); ! 39: static VOID DrawObj (HDC hdc, LPOBJ lpobj, RECT rc, INT dctype); ! 40: ! 41: ! 42: ! 43: /* CreateNewObj ! 44: * ------------ ! 45: * ! 46: * BOOL fDoc_Changed - The new value for the global variable fDocChanged. ! 47: * When initializing a new document, we need to create ! 48: * a new object without the creation counting as a ! 49: * change to the document. ! 50: * ! 51: * RETURNS: A pointer to the new object ! 52: * ! 53: * ! 54: * CUSTOMIZATION: Re-implement ! 55: * Some applications (like Server Demo) have a finite number of ! 56: * fixed, distinct, non-overlapping objects. Other applications ! 57: * allow the user to create an object from any section of the ! 58: * document. For example, the user might select a portion of ! 59: * a bitmap from a paint program, or a few lines of text from ! 60: * a word processor. This latter type of application probably ! 61: * will not have a function like CreateNewObj. ! 62: * ! 63: */ ! 64: LPOBJ CreateNewObj (BOOL fDoc_Changed) ! 65: { ! 66: HANDLE hObj = NULL; ! 67: LPOBJ lpobj = NULL; ! 68: // index into an array of flags indicating if that object number is used. ! 69: INT ifObj = 0; ! 70: ! 71: if ((hObj = LocalAlloc (LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof (OBJ))) == NULL) ! 72: return NULL; ! 73: ! 74: if ((lpobj = (LPOBJ) LocalLock (hObj)) == NULL) ! 75: { ! 76: LocalFree (hObj); ! 77: return NULL; ! 78: } ! 79: ! 80: // Fill the fields in the object structure. ! 81: ! 82: // Find an unused number. ! 83: for (ifObj=1; ifObj <= cfObjNums; ifObj++) ! 84: { ! 85: if (docMain.rgfObjNums[ifObj]==FALSE) ! 86: { ! 87: docMain.rgfObjNums[ifObj]=TRUE; ! 88: break; ! 89: } ! 90: } ! 91: ! 92: if (ifObj==cfObjNums+1) ! 93: { ! 94: // Cannot create any more objects. ! 95: MessageBeep(0); ! 96: return NULL; ! 97: } ! 98: ! 99: wsprintf (lpobj->native.szName, "Object %d", ifObj); ! 100: ! 101: lpobj->aName = GlobalAddAtom (lpobj->native.szName); ! 102: lpobj->hObj = hObj; ! 103: lpobj->oleobject.lpvtbl = &objvtbl; ! 104: lpobj->native.idmColor = IDM_RED; // Default color ! 105: lpobj->native.version = version; ! 106: lpobj->native.nWidth = OBJECT_WIDTH; // Default size ! 107: lpobj->native.nHeight = OBJECT_HEIGHT; ! 108: SetHiMetricFields (lpobj); ! 109: ! 110: // Place object in a location corrsponding to its number, for aesthetics. ! 111: lpobj->native.nX = (ifObj - 1) * 20; ! 112: lpobj->native.nY = (ifObj - 1) * 20; ! 113: ! 114: if (!CreateWindow ( ! 115: "ObjClass", ! 116: "Obj", ! 117: WS_BORDER | WS_THICKFRAME | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, ! 118: lpobj->native.nX, ! 119: lpobj->native.nY, ! 120: lpobj->native.nWidth, ! 121: lpobj->native.nHeight, ! 122: hwndMain, ! 123: NULL, ! 124: hInst, ! 125: (LPSTR) lpobj )) ! 126: return FALSE; ! 127: ! 128: fDocChanged = fDoc_Changed; ! 129: ! 130: return lpobj; ! 131: } ! 132: ! 133: ! 134: ! 135: /* CutOrCopyObj ! 136: * ------------ ! 137: * ! 138: * Put data onto clipboard in all the formats supported. If the ! 139: * fOpIsCopy is TRUE, the operation is COPY, otherwise it is CUT. ! 140: * This is important, because we cannot put the Object Link format ! 141: * onto the clipboard if the object was cut from the document (there is ! 142: * no longer anything to link to). ! 143: * ! 144: * BOOL fOpIsCopy - TRUE if the operation is COPY; FALSE if CUT ! 145: * ! 146: * CUSTOMIZATION: None ! 147: * ! 148: * ! 149: */ ! 150: VOID CutOrCopyObj (BOOL fOpIsCopy) ! 151: { ! 152: LPOBJ lpobj; ! 153: HANDLE hData; ! 154: ! 155: if (OpenClipboard (hwndMain)) ! 156: { ! 157: EmptyClipboard (); ! 158: ! 159: lpobj = SelectedObject(); ! 160: ! 161: if ((hData = GetNative (lpobj)) != NULL) ! 162: SetClipboardData(cfNative, hData); ! 163: ! 164: if ((hData = GetLink(lpobj)) != NULL) ! 165: SetClipboardData(cfOwnerLink, hData); ! 166: ! 167: if (fOpIsCopy && docMain.doctype == doctypeFromFile) ! 168: { ! 169: // Can create a link if object exists in a file. ! 170: if ((hData = GetLink(lpobj)) != NULL) ! 171: SetClipboardData(cfObjectLink, hData); ! 172: } ! 173: ! 174: if ((hData = GetEnhMetafile(lpobj)) != NULL) ! 175: { ! 176: SetClipboardData(CF_ENHMETAFILE, hData); ! 177: // GlobalFree(hData); ! 178: } ! 179: ! 180: if ((hData = GetBitmap(lpobj)) != NULL) ! 181: { ! 182: SetClipboardData(CF_BITMAP, hData); ! 183: // DeleteObject(hData); ! 184: } ! 185: ! 186: ! 187: CloseClipboard (); ! 188: } ! 189: } ! 190: ! 191: ! 192: /* DestroyObj ! 193: * ---------- ! 194: * ! 195: * Revoke an object, and free all memory that had been allocated for it. ! 196: * ! 197: * HWND hwnd - The object's window ! 198: * ! 199: * CUSTOMIZATION: Re-implement, making sure you free all the memory that ! 200: * had been allocated for the OBJ structure and each of its ! 201: * fields. ! 202: * ! 203: */ ! 204: VOID DestroyObj (HWND hwnd) ! 205: { ! 206: LPOBJ lpobj = HwndToLpobj (hwnd); ! 207: ! 208: if(lpobj->aName) ! 209: { ! 210: GlobalDeleteAtom (lpobj->aName); ! 211: lpobj->aName = NULL; ! 212: } ! 213: ! 214: if (lpobj->hpal) ! 215: DeleteObject (lpobj->hpal); ! 216: // Allow the object's number to be reused. ! 217: docMain.rgfObjNums [GetObjNum(lpobj)] = FALSE; ! 218: ! 219: ! 220: // Free the memory that had been allocated for the object structure itself. ! 221: LocalUnlock (lpobj->hObj); ! 222: LocalFree (lpobj->hObj); ! 223: } ! 224: ! 225: ! 226: ! 227: /* DrawObj ! 228: * ------- ! 229: * ! 230: * This function draws an object onto the screen, into a metafile, or into ! 231: * a bitmap. ! 232: * The object will always look the same. ! 233: * ! 234: * HDC hdc - The device context to render the object into ! 235: * LPOBJ lpobj - The object to render ! 236: * RECT rc - The rectangle bounds of the object ! 237: * DCTYPE dctype - The type of device context. ! 238: * ! 239: * CUSTOMIZATION: Server Demo specific ! 240: * ! 241: */ ! 242: static VOID DrawObj (HDC hdc, LPOBJ lpobj, RECT rc, INT dctype) ! 243: { ! 244: HPEN hpen; ! 245: HPEN hpenOld; ! 246: HPALETTE hpalOld = NULL; ! 247: ! 248: if (dctype == dctypeMetafile || dctype == dctypeEnhMetafile) ! 249: { ! 250: SetWindowOrgEx (hdc, 0, 0, NULL); ! 251: // Paint entire object into the given rectangle. ! 252: SetWindowExtEx (hdc, rc.right, rc.bottom, NULL); ! 253: } ! 254: ! 255: if (lpobj->hpal) ! 256: { ! 257: hpalOld = SelectPalette (hdc, lpobj->hpal, TRUE); ! 258: RealizePalette (hdc); ! 259: } ! 260: ! 261: // Select brush of the color specified in the native data. ! 262: SelectObject (hdc, hbrColor [lpobj->native.idmColor - IDM_RED] ); ! 263: ! 264: hpen = CreatePen (PS_SOLID, ! 265: /* Width */ (rc.bottom-rc.top) / 10, ! 266: /* Gray */ 0x00808080); ! 267: hpenOld = SelectObject (hdc, hpen); ! 268: ! 269: // Draw rectangle with the gray pen and fill it in with the selected brush. ! 270: Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); ! 271: ! 272: // Print name of object inside rectangle. ! 273: SetBkMode (hdc, TRANSPARENT); ! 274: SetTextAlign (hdc, TA_BASELINE | TA_CENTER); ! 275: TextOut (hdc, ! 276: rc.right/2, ! 277: (rc.top+rc.bottom)/2, ! 278: lpobj->native.szName, ! 279: lstrlen (lpobj->native.szName)); ! 280: ! 281: // Restore original objects ! 282: SelectObject (hdc, ! 283: (dctype == dctypeMetafile || dctype == dctypeEnhMetafile) ! 284: ? GetStockObject (BLACK_PEN) : hpenOld); ! 285: if (hpalOld) ! 286: { ! 287: SelectPalette (hdc, ! 288: (dctype == dctypeMetafile || dctype == dctypeEnhMetafile) ! 289: ? GetStockObject (DEFAULT_PALETTE) : hpalOld, ! 290: TRUE); ! 291: } ! 292: ! 293: DeleteObject (hpen); ! 294: } ! 295: ! 296: ! 297: ! 298: /* GetBitmap ! 299: * --------- ! 300: * ! 301: * Return a handle to an object's picture data in bitmap format. ! 302: * ! 303: * LPOBJ lpobj - The object ! 304: * ! 305: * RETURNS: A handle to the object's picture data ! 306: * ! 307: * CUSTOMIZATION: Re-implement ! 308: * ! 309: */ ! 310: static HBITMAP GetBitmap (LPOBJ lpobj) ! 311: { ! 312: HDC hdcObj; ! 313: HDC hdcMem; ! 314: RECT rc; ! 315: HBITMAP hbitmap; ! 316: HBITMAP hbitmapOld; ! 317: ! 318: ! 319: hdcObj = GetDC (lpobj->hwnd); ! 320: // Create a memory device context. ! 321: hdcMem = CreateCompatibleDC (hdcObj); ! 322: GetClientRect (lpobj->hwnd, (LPRECT)&rc); ! 323: // Create new bitmap object based on the bitmap of the OLE object. ! 324: hbitmap = CreateCompatibleBitmap ! 325: (hdcObj, rc.right - rc.left, rc.bottom - rc.top); ! 326: // Select new bitmap as the bitmap object for the memory device context. ! 327: hbitmapOld = SelectObject (hdcMem, hbitmap); ! 328: ! 329: // Paint directly into the memory dc using the new bitmap object. ! 330: DrawObj (hdcMem, lpobj, rc, dctypeBitmap); ! 331: ! 332: // Restore old bitmap object. ! 333: hbitmap = SelectObject (hdcMem, hbitmapOld); ! 334: DeleteDC (hdcMem); ! 335: ReleaseDC (lpobj->hwnd, hdcObj); ! 336: ! 337: // convert width and height to HIMETRIC units ! 338: rc.right = rc.right - rc.left; ! 339: rc.bottom = rc.bottom - rc.top; ! 340: DeviceToHiMetric (hwndMain, (LPPOINT) &rc.right); ! 341: ! 342: // Set the 1/10 of HIMETRIC units for the bitmap ! 343: SetBitmapDimensionEx (hbitmap, (DWORD) (rc.right/10), (DWORD) (rc.bottom/10), NULL); ! 344: ! 345: return hbitmap; ! 346: } ! 347: ! 348: ! 349: ! 350: /* GetLink ! 351: * ------- ! 352: * ! 353: * Return a handle to an object's object or owner link data. ! 354: * Link information is in the form of three zero-separated strings, ! 355: * terminated with two zero bytes: CLASSNAME\0DOCNAME\0OBJNAME\0\0 ! 356: * ! 357: * LPOBJ lpobj - The object ! 358: * ! 359: * RETURNS: A handle to the object's link data ! 360: * ! 361: * CUSTOMIZATION: Re-implement ! 362: * ! 363: */ ! 364: static HANDLE GetLink (LPOBJ lpobj) ! 365: { ! 366: ! 367: CHAR sz[cchFilenameMax]; ! 368: LPSTR lpszLink = NULL; ! 369: HANDLE hLink = NULL; ! 370: INT cchLen; ! 371: INT i; ! 372: ! 373: // First make the class name. ! 374: lstrcpy (sz, szClassName); ! 375: cchLen = lstrlen (sz) + 1; ! 376: ! 377: // Then the document name. ! 378: cchLen += GlobalGetAtomName ! 379: (docMain.aName, (LPSTR)sz + cchLen, ! 380: cchFilenameMax - cchLen) + 1; ! 381: ! 382: // Then the object name. ! 383: lstrcpy (sz + cchLen, lpobj->native.szName); ! 384: cchLen += lstrlen (lpobj->native.szName) + 1; ! 385: ! 386: // Add a second null to the end. ! 387: sz[cchLen++] = 0; ! 388: ! 389: ! 390: hLink = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, cchLen); ! 391: if (hLink == NULL) ! 392: return NULL; ! 393: if ((lpszLink = GlobalLock (hLink)) == NULL) ! 394: { ! 395: GlobalFree (hLink); ! 396: return NULL; ! 397: } ! 398: ! 399: for (i=0; i < cchLen; i++) ! 400: lpszLink[i] = sz[i]; ! 401: ! 402: GlobalUnlock (hLink); ! 403: ! 404: return hLink; ! 405: } ! 406: ! 407: ! 408: ! 409: /* GetMetafilePict ! 410: * --------------- ! 411: * ! 412: * Return a handle to an object's picture data in metafile format. ! 413: * ! 414: * LPOBJ lpobj - The object ! 415: * ! 416: * RETURNS: A handle to the object's data in metafile format. ! 417: * ! 418: * CUSTOMIZATION: Re-implement ! 419: * ! 420: */ ! 421: static HANDLE GetMetafilePict (LPOBJ lpobj) ! 422: { ! 423: ! 424: LPMETAFILEPICT lppict = NULL; ! 425: HANDLE hpict = NULL; ! 426: HANDLE hMF = NULL; ! 427: RECT rc; ! 428: HDC hdc; ! 429: ! 430: hdc = CreateMetaFile(NULL); ! 431: ! 432: GetClientRect (lpobj->hwnd, (LPRECT)&rc); ! 433: ! 434: // Paint directly into the metafile. ! 435: DrawObj (hdc, lpobj, rc, dctypeMetafile); ! 436: ! 437: // Get handle to the metafile. ! 438: if ((hMF = CloseMetaFile (hdc)) == NULL) ! 439: return NULL; ! 440: ! 441: if(!(hpict = GlobalAlloc (GMEM_DDESHARE, sizeof (METAFILEPICT)))) ! 442: { ! 443: DeleteMetaFile (hMF); ! 444: return NULL; ! 445: } ! 446: ! 447: if ((lppict = (LPMETAFILEPICT)GlobalLock (hpict)) == NULL) ! 448: { ! 449: DeleteMetaFile (hMF); ! 450: GlobalFree (hpict); ! 451: return NULL; ! 452: } ! 453: ! 454: rc.right = rc.right - rc.left; ! 455: rc.bottom = rc.bottom - rc.top; ! 456: ! 457: DeviceToHiMetric (hwndMain, (LPPOINT) &rc.right); ! 458: ! 459: lppict->mm = MM_ANISOTROPIC; ! 460: lppict->hMF = hMF; ! 461: lppict->xExt = rc.right; ! 462: lppict->yExt = rc.bottom; ! 463: GlobalUnlock (hpict); ! 464: return hpict; ! 465: } ! 466: ! 467: /* GetEnhMetafile ! 468: * --------------- ! 469: * ! 470: * Return a handle to an object's picture data in metafile format. ! 471: * ! 472: * LPOBJ lpobj - The object ! 473: * ! 474: * RETURNS: A handle to the object's data in metafile format. ! 475: * ! 476: * CUSTOMIZATION: Re-implement ! 477: * ! 478: */ ! 479: static HANDLE GetEnhMetafile (LPOBJ lpobj) ! 480: { ! 481: ! 482: LPMETAFILEPICT lppict = NULL; ! 483: HANDLE hemf = NULL; ! 484: HANDLE hMF = NULL; ! 485: RECT rc,rect; ! 486: HDC hdc; ! 487: ! 488: GetClientRect (lpobj->hwnd, (LPRECT)&rc); ! 489: ! 490: rect.left = rect.top = 0; ! 491: rect.right = rc.right - rc.left; ! 492: rect.bottom = rc.bottom - rc.top; ! 493: ! 494: DeviceToHiMetric (hwndMain, (LPPOINT) &rect.right); ! 495: ! 496: hdc = CreateEnhMetaFile(NULL, NULL, &rect, NULL); ! 497: DrawObj (hdc, lpobj, rc, dctypeMetafile); ! 498: if ((hemf = (HANDLE)CloseEnhMetaFile (hdc)) == NULL) ! 499: return NULL; ! 500: ! 501: return hemf; ! 502: } ! 503: ! 504: ! 505: /* GetNative ! 506: * --------- ! 507: * ! 508: * Return a handle to an object's native data. ! 509: * ! 510: * LPOBJ lpobj - The object whose native data is to be retrieved. ! 511: * ! 512: * RETURNS: a handle to the object's native data. ! 513: * ! 514: * CUSTOMIZATION: The line "*lpnative = lpobj->native;" will change to ! 515: * whatever code is necessary to copy an object's native data. ! 516: * ! 517: */ ! 518: static HANDLE GetNative (LPOBJ lpobj) ! 519: { ! 520: LPNATIVE lpnative = NULL; ! 521: HANDLE hNative = NULL; ! 522: ! 523: hNative = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, sizeof (NATIVE)); ! 524: if (hNative == NULL) ! 525: return NULL; ! 526: if ((lpnative = (LPNATIVE) GlobalLock (hNative)) == NULL) ! 527: { ! 528: GlobalFree (hNative); ! 529: return NULL; ! 530: } ! 531: ! 532: // Copy the native data. ! 533: *lpnative = lpobj->native; ! 534: ! 535: GlobalUnlock (hNative); ! 536: return hNative; ! 537: } ! 538: ! 539: ! 540: ! 541: /* GetObjNum ! 542: * --------- ! 543: * ! 544: * LPSTR lpobj - The object whose number is desired ! 545: * ! 546: * RETURNS: The number of the object, i.e., the numerical portion of its name. ! 547: * ! 548: * CUSTOMIZATION: Server Demo specific ! 549: */ ! 550: static INT GetObjNum (LPOBJ lpobj) ! 551: { ! 552: LPSTR lpsz; ! 553: INT n=0; ! 554: ! 555: lpsz = lpobj->native.szName + 7; ! 556: while (*lpsz && *lpsz>='0' && *lpsz<='9') ! 557: n = 10*n + *lpsz++ - '0'; ! 558: return n; ! 559: } ! 560: ! 561: ! 562: ! 563: /* GetText ! 564: * ------- ! 565: * ! 566: * Return a handle to an object's data in text form. ! 567: * This function simply returns the name of the object. ! 568: * ! 569: * LPOBJ lpobj - The object ! 570: * ! 571: * RETURNS: A handle to the object's text. ! 572: * ! 573: * CUSTOMIZATION: Re-implement, if your application supports CF_TEXT as a ! 574: * presentation format. ! 575: * ! 576: */ ! 577: static HANDLE GetText (LPOBJ lpobj) ! 578: { ! 579: HANDLE hText = NULL; ! 580: LPSTR lpszText = NULL; ! 581: ! 582: if(!(hText = GlobalAlloc (GMEM_DDESHARE, sizeof (lpobj->native.szName)))) ! 583: return NULL; ! 584: ! 585: if (!(lpszText = GlobalLock (hText))) ! 586: return NULL; ! 587: ! 588: lstrcpy (lpszText, lpobj->native.szName); ! 589: ! 590: GlobalUnlock (hText); ! 591: ! 592: return hText; ! 593: } ! 594: ! 595: ! 596: ! 597: /* ObjDoVerb OBJECT "DoVerb" METHOD ! 598: * --------- ! 599: * ! 600: * This method is called by the client, through the library, to either ! 601: * PLAY, or EDIT the object. PLAY is implemented as a beep, and ! 602: * EDIT will bring up the server and show the object for editing. ! 603: * ! 604: * LPOLEOBJECT lpoleobject - The OLE object ! 605: * WORD wVerb - The verb acting on the object: PLAY or EDIT ! 606: * BOOL fShow - Should the object be shown? ! 607: * BOOL fTakeFocus - Should the object window get the focus? ! 608: * ! 609: * RETURNS: OLE_OK ! 610: * ! 611: * CUSTOMIZATION: Add any more verbs your application supports. ! 612: * Implement verbPlay if your application supports it. ! 613: * ! 614: */ ! 615: OLESTATUS APIENTRY ObjDoVerb ! 616: (LPOLEOBJECT lpoleobject, UINT wVerb, BOOL fShow, BOOL fTakeFocus) ! 617: { ! 618: switch (wVerb) ! 619: { ! 620: case verbPlay: ! 621: { // The application can do whatever is appropriate for the object. ! 622: INT i; ! 623: for (i=0; i<25;i++) MessageBeep (0); ! 624: return OLE_OK; ! 625: } ! 626: ! 627: case verbEdit: ! 628: if (fShow) ! 629: return objvtbl.Show (lpoleobject, fTakeFocus); ! 630: else ! 631: return OLE_OK; ! 632: default: ! 633: // Unknown verb. ! 634: return OLE_ERROR_DOVERB; ! 635: } ! 636: } ! 637: ! 638: ! 639: ! 640: /* ObjEnumFormats OBJECT "EnumFormats" METHOD ! 641: * --------------- ! 642: * ! 643: * This method is used to enumerate all supported clipboard formats. ! 644: * Terminate by returning NULL. ! 645: * ! 646: * LPOLEOBJECT lpoleobject - The OLE object ! 647: * OLECLIPFORMAT cfFormat - The 'current' clipboard format ! 648: * ! 649: * RETURNS: The 'next' clipboard format which is supported. ! 650: * ! 651: * CUSTOMIZATION: Verify that the list of formats this function ! 652: * returns matches the list of formats your application ! 653: * supports. ! 654: * ! 655: */ ! 656: OLECLIPFORMAT APIENTRY ObjEnumFormats ! 657: (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat) ! 658: { ! 659: if (cfFormat == 0) ! 660: return cfNative; ! 661: ! 662: if (cfFormat == cfNative) ! 663: return cfOwnerLink; ! 664: ! 665: if (cfFormat == cfOwnerLink) ! 666: return CF_ENHMETAFILE; ! 667: ! 668: if (cfFormat == CF_ENHMETAFILE) ! 669: return CF_METAFILEPICT; ! 670: ! 671: if (cfFormat == CF_METAFILEPICT) ! 672: return CF_BITMAP; ! 673: ! 674: if (cfFormat == CF_BITMAP) ! 675: return cfObjectLink; ! 676: ! 677: if (cfFormat == cfObjectLink) ! 678: return NULL; ! 679: ! 680: return NULL; ! 681: } ! 682: ! 683: ! 684: ! 685: /* ObjGetData OBJECT "GetData" METHOD ! 686: * ----------- ! 687: * ! 688: * Return the data requested for the specified object in the specified format. ! 689: * ! 690: * LPOLEOBJECT lpoleobject - The OLE object ! 691: * WORD cfFormat - The data type requested in standard ! 692: * clipboard format ! 693: * LPHANDLE lphandle - Pointer to handle to memory where data ! 694: * will be stored ! 695: * ! 696: * RETURNS: OLE_OK if successful ! 697: * OLE_ERROR_MEMORY if there was an error getting the data. ! 698: * OLE_ERROR_FORMAT if the requested format is unknown. ! 699: * ! 700: * ! 701: * CUSTOMIZATION: Add any additional formats your application supports, and ! 702: * remove any formats it does not support. ! 703: * ! 704: */ ! 705: OLESTATUS APIENTRY ObjGetData ! 706: (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, LPHANDLE lphandle) ! 707: { ! 708: ! 709: LPOBJ lpobj; ! 710: ! 711: lpobj = (LPOBJ) lpoleobject; ! 712: ! 713: if (cfFormat == cfNative) ! 714: { ! 715: if (!(*lphandle = GetNative (lpobj))) ! 716: return OLE_ERROR_MEMORY; ! 717: // The client has requested the data in native format, therefore ! 718: // the data in the client and server are in sync. ! 719: fDocChanged = FALSE; ! 720: return OLE_OK; ! 721: } ! 722: ! 723: if (cfFormat == CF_ENHMETAFILE) ! 724: { ! 725: if (!(*lphandle = GetEnhMetafile (lpobj))) ! 726: return OLE_ERROR_MEMORY; ! 727: return OLE_OK; ! 728: } ! 729: ! 730: if (cfFormat == CF_METAFILEPICT) ! 731: { ! 732: if (!(*lphandle = GetMetafilePict (lpobj))) ! 733: return OLE_ERROR_MEMORY; ! 734: return OLE_OK; ! 735: } ! 736: ! 737: if (cfFormat == CF_BITMAP) ! 738: { ! 739: if (!(*lphandle = (HANDLE)GetBitmap (lpobj))) ! 740: return OLE_ERROR_MEMORY; ! 741: return OLE_OK; ! 742: } ! 743: ! 744: if (cfFormat == CF_TEXT) ! 745: { ! 746: if (!(*lphandle = GetText (lpobj))) ! 747: return OLE_ERROR_MEMORY; ! 748: return OLE_OK; ! 749: } ! 750: ! 751: if (cfFormat == cfObjectLink) ! 752: { ! 753: if (!(*lphandle = GetLink (lpobj))) ! 754: return OLE_ERROR_MEMORY; ! 755: return OLE_OK; ! 756: } ! 757: ! 758: if (cfFormat == cfOwnerLink) ! 759: { ! 760: if (!(*lphandle = GetLink (lpobj))) ! 761: return OLE_ERROR_MEMORY; ! 762: return OLE_OK; ! 763: } ! 764: ! 765: return OLE_ERROR_FORMAT; ! 766: } ! 767: ! 768: ! 769: ! 770: /* ObjQueryProtocol OBJECT "QueryProtocol" METHOD ! 771: * ---------------- ! 772: * ! 773: * LPOLEOBJECT lpoleobject - The OLE object ! 774: * LPSTR lpszProtocol - The protocol name, either "StdFileEditing" ! 775: * or "StdExecute" ! 776: * ! 777: * RETURNS: If lpszProtocol is supported, return a pointer to an OLEOBJECT ! 778: * structure with an appropriate method table for that protocol. ! 779: * Otherwise, return NULL. ! 780: * ! 781: * CUSTOMIZATION: Allow any additional protocols your application supports. ! 782: * ! 783: * ! 784: */ ! 785: LPVOID APIENTRY ObjQueryProtocol ! 786: (LPOLEOBJECT lpoleobject, LPSTR lpszProtocol) ! 787: { ! 788: return lstrcmp (lpszProtocol, "StdFileEditing") ? NULL : lpoleobject ; ! 789: } ! 790: ! 791: ! 792: ! 793: /* ObjRelease OBJECT "Release" METHOD ! 794: * ----------- ! 795: * ! 796: * The server application should not destroy data when the library calls the ! 797: * ReleaseObj method. ! 798: * The library calls the ReleaseObj method when no clients are connected ! 799: * to the object. ! 800: * ! 801: * LPOLEOBJECT lpoleobject - The OLE object ! 802: * ! 803: * RETURNS: OLE_OK ! 804: * ! 805: * CUSTOMIZATION: Re-implement. Do whatever needs to be done, if anything, ! 806: * when no clients are connected to an object. ! 807: * ! 808: */ ! 809: OLESTATUS APIENTRY ObjRelease (LPOLEOBJECT lpoleobject) ! 810: { ! 811: INT i; ! 812: /* No client is connected to the object so break all assocaiations ! 813: between clients and the object. */ ! 814: for (i=0; i < clpoleclient; i++) ! 815: ((LPOBJ)lpoleobject)->lpoleclient[i] = NULL; ! 816: return OLE_OK; ! 817: } ! 818: ! 819: ! 820: ! 821: /* ObjSetBounds OBJECT "SetBounds" METHOD ! 822: * ------------ ! 823: * ! 824: * This method is called to set new bounds for an object. ! 825: * The bounds are in HIMETRIC units. ! 826: * A call to this method is ignored for linked objects because the size of ! 827: * a linked object depends only on the source file. ! 828: * ! 829: * LPOLEOBJECT lpoleobject - The OLE object ! 830: * LPRECT lprect - The new bounds ! 831: * ! 832: * RETURNS: OLE_OK ! 833: * ! 834: * CUSTOMIZATION: Re-implement ! 835: * How an object is sized is application-specific. (Server Demo ! 836: * uses MoveWindow.) ! 837: * ! 838: */ ! 839: OLESTATUS APIENTRY ObjSetBounds (LPOLEOBJECT lpoleobj, LPRECT lprect) ! 840: { ! 841: if (docMain.doctype == doctypeEmbedded) ! 842: { ! 843: RECT rect = *lprect; ! 844: LPOBJ lpobj = (LPOBJ) lpoleobj; ! 845: ! 846: // the units are in HIMETRIC ! 847: rect.right = rect.right - rect.left; ! 848: rect.bottom = rect.top - rect.bottom; ! 849: HiMetricToDevice (hwndMain, (LPPOINT) &rect.right); ! 850: MoveWindow (lpobj->hwnd, lpobj->native.nX, lpobj->native.nY, ! 851: rect.right + 2 * GetSystemMetrics(SM_CXFRAME), ! 852: rect.bottom + 2 * GetSystemMetrics(SM_CYFRAME), ! 853: TRUE); ! 854: } ! 855: return OLE_OK; ! 856: } ! 857: ! 858: ! 859: ! 860: /* ObjSetColorScheme OBJECT "SetColorScheme" METHOD ! 861: * ----------------- ! 862: * ! 863: * The client calls this method to suggest a color scheme (palette) for ! 864: * the server to use for the object. ! 865: * ! 866: * LPOLEOBJECT lpoleobject - The OLE object ! 867: * LPLOGPALETTE lppal - Suggested palette ! 868: * ! 869: * RETURNS: OLE_ERROR_PALETTE if CreatePalette fails, ! 870: * OLE_OK otherwise ! 871: * ! 872: * ! 873: * CUSTOMIZATION: If your application supports color schemes, then this ! 874: * function is a good example of how to create and store ! 875: * a palette. ! 876: * ! 877: */ ! 878: OLESTATUS APIENTRY ObjSetColorScheme ! 879: (LPOLEOBJECT lpoleobject, LPLOGPALETTE lppal) ! 880: { ! 881: HPALETTE hpal = CreatePalette (lppal); ! 882: LPOBJ lpobj = (LPOBJ) lpoleobject; ! 883: ! 884: if (hpal==NULL) ! 885: return OLE_ERROR_PALETTE; ! 886: ! 887: if (lpobj->hpal) ! 888: DeleteObject (lpobj->hpal); ! 889: lpobj->hpal = hpal; ! 890: return OLE_OK; ! 891: } ! 892: ! 893: ! 894: ! 895: /* ObjSetData OBJECT "SetData" METHOD ! 896: * ---------- ! 897: * ! 898: * This method is used to store data into the object in the specified ! 899: * format. This will be called with Native format after an embedded ! 900: * object has been opened by the Edit method. ! 901: * ! 902: * LPOLEOBJECT lpoleobject - The OLE object ! 903: * WORD cfFormat - Data type, i.e., clipboard format ! 904: * HANDLE hdata - Handle to the data. ! 905: * ! 906: * RETURNS: OLE_OK if the data was stored properly ! 907: * OLE_ERROR_FORMAT if format was not cfNative. ! 908: * OLE_ERROR_MEMORY if memory could not be locked. ! 909: * ! 910: * CUSTOMIZATION: The large then-clause will need to be re-implemented for ! 911: * your application. You may wish to support additional ! 912: * formats besides cfNative. ! 913: * ! 914: */ ! 915: OLESTATUS APIENTRY ObjSetData ! 916: (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata) ! 917: { ! 918: LPNATIVE lpnative; ! 919: LPOBJ lpobj; ! 920: ! 921: lpobj = (LPOBJ)lpoleobject; ! 922: ! 923: if (cfFormat != cfNative) ! 924: { ! 925: return OLE_ERROR_FORMAT; ! 926: } ! 927: ! 928: lpnative = (LPNATIVE) GlobalLock (hdata); ! 929: ! 930: if (lpnative) ! 931: { ! 932: lpobj->native = *lpnative; ! 933: if (lpobj->aName) ! 934: GlobalDeleteAtom (lpobj->aName); ! 935: lpobj->aName = GlobalAddAtom (lpnative->szName); ! 936: // CreateNewObj made an "Object 1" but we may be changing its number. ! 937: docMain.rgfObjNums[1] = FALSE; ! 938: docMain.rgfObjNums [GetObjNum(lpobj)] = TRUE; ! 939: ! 940: MoveWindow (lpobj->hwnd, 0, 0, ! 941: lpobj->native.nWidth + 2 * GetSystemMetrics(SM_CXFRAME), ! 942: lpobj->native.nHeight+ 2 * GetSystemMetrics(SM_CYFRAME), ! 943: FALSE); ! 944: GlobalUnlock (hdata); ! 945: } ! 946: // Server is responsible for deleting the data. ! 947: GlobalFree(hdata); ! 948: return lpnative ? OLE_OK : OLE_ERROR_MEMORY; ! 949: } ! 950: ! 951: ! 952: ! 953: /* ObjSetTargetDevice OBJECT "SetTargetDevice" METHOD ! 954: * ------------------- ! 955: * ! 956: * This method is used to indicate the device type that an object ! 957: * will be rendered on. It is the server's responsibility to free hdata. ! 958: * ! 959: * LPOLEOBJECT lpoleobject - The OLE object ! 960: * HANDLE hdata - Handle to memory containing ! 961: * a StdTargetDevice structure ! 962: * ! 963: * RETURNS: OLE_OK ! 964: * ! 965: * CUSTOMIZATION: Implement. Server Demo currently does not do anything. ! 966: * ! 967: */ ! 968: OLESTATUS APIENTRY ObjSetTargetDevice (LPOLEOBJECT lpoleobject, HANDLE hdata) ! 969: { ! 970: if (hdata == NULL) ! 971: { ! 972: // Rendering for the screen is requested. ! 973: } ! 974: else ! 975: { ! 976: LPSTR lpstd = (LPSTR) GlobalLock (hdata); ! 977: // lpstd points to a StdTargetDevice structure. ! 978: // Use it to do whatever is appropriate to generate the best results ! 979: // on the specified target device. ! 980: GlobalUnlock (hdata); ! 981: // Server is responsible for freeing the data. ! 982: GlobalFree (hdata); ! 983: } ! 984: return OLE_OK; ! 985: } ! 986: ! 987: ! 988: ! 989: /* ObjShow OBJECT "Show" METHOD ! 990: * -------- ! 991: * ! 992: * This method is used to display the object. ! 993: * The server application should be activated and brought to the top. ! 994: * Also, in a REAL server application, the object should be scrolled ! 995: * into view. The object should be selected. ! 996: * ! 997: * LPOLEOBJECT lpoleobject - Pointer to the OLE object ! 998: * BOOL fTakeFocus - Should server window get the focus? ! 999: * ! 1000: * RETURNS: OLE_OK ! 1001: * ! 1002: * ! 1003: * CUSTOMIZATION: In your application, the document should be scrolled ! 1004: * to bring the object into view. Server Demo brings the ! 1005: * object to the front, in case it is a linked object inside a ! 1006: * document with other objects obscuring it. ! 1007: * ! 1008: */ ! 1009: OLESTATUS APIENTRY ObjShow (LPOLEOBJECT lpoleobject, BOOL fTakeFocus) ! 1010: { ! 1011: LPOBJ lpobj; ! 1012: HWND hwndOldFocus; ! 1013: ! 1014: hwndOldFocus = GetFocus(); ! 1015: lpobj = (LPOBJ) lpoleobject; ! 1016: ! 1017: if (fTakeFocus) ! 1018: SetForegroundWindow (lpobj->hwnd); ! 1019: ! 1020: ShowWindow(hwndMain, SW_SHOWNORMAL); ! 1021: ! 1022: SetFocus (fTakeFocus ? lpobj->hwnd : hwndOldFocus); ! 1023: return OLE_OK; ! 1024: } ! 1025: ! 1026: ! 1027: ! 1028: /* PaintObj ! 1029: * --------- ! 1030: * ! 1031: * This function is called by the WM_PAINT message to paint an object ! 1032: * on the screen. ! 1033: * ! 1034: * HWND hwnd - The object window in which to paint the object ! 1035: * ! 1036: * CUSTOMIZATION: Server Demo specific ! 1037: * ! 1038: */ ! 1039: VOID PaintObj (HWND hwnd) ! 1040: { ! 1041: LPOBJ lpobj; ! 1042: RECT rc; ! 1043: HDC hdc; ! 1044: PAINTSTRUCT paintstruct; ! 1045: ! 1046: BeginPaint (hwnd, &paintstruct); ! 1047: hdc = GetDC (hwnd); ! 1048: ! 1049: lpobj = HwndToLpobj (hwnd); ! 1050: GetClientRect (hwnd, (LPRECT) &rc); ! 1051: ! 1052: DrawObj (hdc, lpobj, rc, dctypeScreen); ! 1053: ! 1054: ReleaseDC (hwnd, hdc); ! 1055: EndPaint (hwnd, &paintstruct); ! 1056: } ! 1057: ! 1058: ! 1059: ! 1060: /* RevokeObj ! 1061: * --------- ! 1062: * ! 1063: * Call OleRevokeObject because the user has destroyed the object. ! 1064: * ! 1065: * LPOBJ lpobj - The object which has been destroyed ! 1066: * ! 1067: * ! 1068: * CUSTOMIZATION: You will only need to call OleRevokeObject once if there ! 1069: * is only one LPOLECLIENT in your OBJ structure, which there ! 1070: * should be. ! 1071: * ! 1072: */ ! 1073: VOID RevokeObj (LPOBJ lpobj) ! 1074: { ! 1075: INT i; ! 1076: ! 1077: for (i=0; i< clpoleclient; i++) ! 1078: { ! 1079: if (lpobj->lpoleclient[i]) ! 1080: OleRevokeObject (lpobj->lpoleclient[i]); ! 1081: else ! 1082: /* if lpobj->lpoleclient[i]==NULL then there are no more non-NULLs ! 1083: in the array. */ ! 1084: break; ! 1085: } ! 1086: } ! 1087: ! 1088: ! 1089: ! 1090: /* SendObjMsg ! 1091: * ---------- ! 1092: * ! 1093: * This function sends a message to a specific object. ! 1094: * ! 1095: * LPOBJ lpobj - The object ! 1096: * WORD wMessage - The message to send ! 1097: * ! 1098: * CUSTOMIZATION: You will only need to call CallBack once if there ! 1099: * is only one LPOLECLIENT in your OBJ structure, which there ! 1100: * should be. ! 1101: * ! 1102: */ ! 1103: VOID SendObjMsg (LPOBJ lpobj, WORD wMessage) ! 1104: { ! 1105: INT i; ! 1106: for (i=0; i < clpoleclient; i++) ! 1107: { ! 1108: if (lpobj->lpoleclient[i]) ! 1109: { ! 1110: // Call the object's Callback function. ! 1111: lpobj->lpoleclient[i]->lpvtbl->CallBack ! 1112: (lpobj->lpoleclient[i], wMessage, (LPOLEOBJECT) lpobj); ! 1113: } ! 1114: else ! 1115: break; ! 1116: } ! 1117: } ! 1118: ! 1119: ! 1120: ! 1121: /* SizeObj ! 1122: * ------- ! 1123: * ! 1124: * Change the size of an object. ! 1125: * ! 1126: * HWND hwnd - The object's window ! 1127: * RECT rect - The requested new size in device units ! 1128: * BOOL fMove - Should the object be moved? (or just resized?) ! 1129: * ! 1130: * CUSTOMIZATION: Server Demo specific ! 1131: * ! 1132: */ ! 1133: VOID SizeObj (HWND hwnd, RECT rect, BOOL fMove) ! 1134: { ! 1135: LPOBJ lpobj; ! 1136: ! 1137: lpobj = HwndToLpobj (hwnd); ! 1138: if (fMove) ! 1139: { ! 1140: lpobj->native.nX = rect.left; ! 1141: lpobj->native.nY = rect.top; ! 1142: } ! 1143: lpobj->native.nWidth = rect.right - rect.left; ! 1144: lpobj->native.nHeight = rect.bottom - rect.top ; ! 1145: SetHiMetricFields (lpobj); ! 1146: InvalidateRect (hwnd, (LPRECT)NULL, TRUE); ! 1147: fDocChanged = TRUE; ! 1148: if (docMain.doctype == doctypeFromFile) ! 1149: { ! 1150: // If object is linked, update it in client now. ! 1151: SendObjMsg (lpobj, OLE_CHANGED); ! 1152: } ! 1153: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.