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