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