|
|
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.