|
|
1.1 root 1: /*
2: * object.c - OLE object support routines
3: *
4: * Created by Microsoft Corporation.
5: * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
6: */
7:
8: //*** INCLUDES ****
9:
10: #include <windows.h> //* WINDOWS
11: #include <shellapi.h> //* SHELL
12: #include <ole.h> //* OLE
13:
14: #include "global.h" //* global variables and structures
15: #include "stream.h" //* application includes:
16: #include "dialog.h"
17: #include "object.h"
18: #include "clidemo.h"
19: #include "demorc.h"
20: #include "utility.h"
21: #include "register.h"
22:
23: //*** VARIABLES ***
24:
25: //*** Globals
26: INT cOleWait = 0;
27:
28:
29: /***************************************************************************
30: * CallBack()
31: *
32: * This routine will be called whenever an object has been changed,
33: * saved, renamed, is being painted, or an asynchronous operation has
34: * completed. This routine is called by the OLE client DLL in the
35: * above situations. A pointer to this function is kept in the client
36: * vtbl. It is our obligation as a client application to insure that a
37: * pointer to this procedure is in the vtbl.
38: *
39: * IMMPORTANT: notice that we are posting messages here rather that doing
40: * the work right away. Well, this is done to avoid any possibility of
41: * getting into another dispatch message loop. A MessageBox woul do this!
42: *
43: * Returns int - see below
44: *
45: * The return value is generally ignored, except for these notifications:
46: * OLE_QUERY_PAINT and OLE_QUERY_RETRY. For these two notifications,
47: * returning TRUE means continue the current operation(eg painting or retry)
48: * Returning FALSE means stop the current operation. This is useful as an
49: * object which takes a long time to paint can be interrupted in order to
50: * perform other operations.
51: ***************************************************************************/
52:
53: INT APIENTRY CallBack( //* ENTRY:
54: LPOLECLIENT lpClient, //* client application pointer
55: OLE_NOTIFICATION flags, //* notification code being sent
56: LPOLEOBJECT lpObject //* OLE object pointer
57: ){ //* LOCAL:
58: APPITEMPTR pItem; //* application item pointer
59:
60:
61: pItem = (APPITEMPTR)lpClient;
62: switch (flags)
63: {
64: case OLE_CLOSED: //* server has closed
65: if (!pItem->fVisible)
66: {
67: PostMessage(hwndFrame, WM_DELETE, (DWORD)pItem,0L);
68: Dirty(DOC_UNDIRTY);
69: }
70: SetFocus( hwndFrame );
71: break;
72:
73: case OLE_SAVED: //* server has saved object
74: case OLE_CHANGED: //* object has changes
75: cOleWait++;
76: pItem->fServerChangedBounds = pItem->fVisible = TRUE;
77: PostMessage(pItem->hwnd, WM_CHANGE, NULL, 0L);
78: break;
79:
80: case OLE_RELEASE: //* notification that an asynchronous
81: ToggleBlockTimer(FALSE); //* toggle timer off
82: if (hRetry)
83: PostMessage(hRetry,WM_COMMAND,IDCANCEL,0L);
84:
85: if (cOleWait) //* operation has completed
86: {
87: pItem->fRetry = TRUE;
88: if (!--cOleWait)
89: Hourglass(FALSE);
90: Release(pItem);
91: }
92: break;
93:
94: case OLE_QUERY_RETRY: //* Continue retrying.
95: ToggleBlockTimer(FALSE); //* toggle timer off
96: if (!hRetry && pItem->fRetry)
97: PostMessage(hwndFrame,WM_RETRY,(DWORD)pItem,0L);
98: return (pItem->fRetry);
99:
100: case OLE_QUERY_PAINT: //* continue repainting
101: return TRUE; //* a false return terminates either
102:
103: default:
104: break;
105: }
106: return 0; //* return value is ignored in
107: //* most cases, see header
108: }
109:
110: /***************************************************************************
111: * Release()
112: *
113: * Check for an error on the OLE_RELEASE notification.
114: **************************************************************************/
115:
116: static VOID Release( //* ENTRY:
117: APPITEMPTR pItem //* Item pointer
118: ){ //* LOCAL:
119: DWORD wParam; //* error code parameter
120:
121: if ((wParam = OleQueryReleaseError(pItem->lpObject)) == OLE_OK)
122: return;
123:
124: switch (OleQueryReleaseMethod(pItem->lpObject))
125: {
126: case OLE_LNKPASTE:
127: pItem->fVisible = FALSE;
128: break;
129:
130: case OLE_CREATEFROMTEMPLATE:
131: case OLE_CREATE:
132: pItem->fVisible = FALSE;
133: cOleWait++;
134: PostMessage(hwndFrame, WM_DELETE,(DWORD)pItem,1L);
135: Dirty(DOC_UNDIRTY);
136: }
137: //* post a message to the main window
138: //* which will display a message box
139: PostMessage(hwndFrame,WM_ERROR,wParam,NULL);
140:
141: }
142:
143: /***************************************************************************
144: * Error()
145: *
146: * This function checks for error conditions
147: * generated by OLE API callsFor OLE_WAIT_FOR_RELEASE,
148: * we keep track of the number of objects waiting, when
149: * this count is zero, it is safe to exit the application.
150: *
151: * Returns OLESTATUS - 0 if OLE_WAIT_FOR_RELEASE or OLE_OK
152: * otherwise the OLESTATUS returned after an action
153: * is taken.
154: *************************************************************************/
155:
156: OLESTATUS FAR Error( //* ENTRY
157: OLESTATUS olestat //* OLE status
158: ){
159:
160: switch (olestat)
161: {
162: case OLE_WAIT_FOR_RELEASE:
163: if (!cOleWait)
164: Hourglass(TRUE);
165: cOleWait++; //* increment wait count
166:
167: case OLE_OK:
168: return 0;
169:
170: case OLE_ERROR_STATIC: //* static object
171: ErrorMessage(W_STATIC_OBJECT);
172: break;
173:
174: case OLE_ERROR_REQUEST_PICT:
175: case OLE_ERROR_ADVISE_RENAME:
176: case OLE_ERROR_DOVERB:
177: case OLE_ERROR_SHOW:
178: case OLE_ERROR_OPEN:
179: case OLE_ERROR_NETWORK:
180: case OLE_ERROR_ADVISE_PICT:
181: case OLE_ERROR_COMM: //* Invalid links
182: InvalidLink();
183: break;
184:
185: case OLE_BUSY:
186: RetryMessage(NULL,RD_CANCEL);
187:
188: default:
189: break;
190: }
191: return olestat;
192: }
193:
194:
195: /****************************************************************************
196: * PreItemCreate()
197: *
198: * This routine allocates an application item structure. A pointer to this
199: * structure is passed as the client structure, therefore we need to
200: * have a pointer to the vtbl as the first entry. We are doing this
201: * to allow acess to the application item information during a OLE
202: * DLL callback. This approach simplifies matters.
203: *
204: * Returns APPITEMPTR - a pointer to a new application item structure
205: * which can operate as a client structure.
206: ***************************************************************************/
207:
208: APPITEMPTR FAR PreItemCreate( //* ENTRY:
209: LPOLECLIENT lpClient, //* OLE client pointer
210: BOOL fShow, //* show/no-show flag
211: LHCLIENTDOC lhcDoc //* client document handle
212: ){ //* LOCAL:
213: HANDLE hitem; //* temp handle for new item
214: APPITEMPTR pItem; //* application item pointer
215:
216:
217: if (hitem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(APPITEM)))
218: if (pItem = (APPITEMPTR)LocalLock(hitem))
219: { //* set the vtbl pointer
220: pItem->oleclient.lpvtbl = lpClient->lpvtbl;
221: pItem->lpObjectUndo = NULL;
222: pItem->fVisible = fShow;
223: pItem->fServerChangedBounds = FALSE;
224: pItem->lhcDoc = lhcDoc;
225:
226: return pItem; //* SUCCESS return
227: }
228:
229: ErrorMessage(E_FAILED_TO_ALLOC);
230: return NULL; //* ERROR return
231:
232: }
233:
234:
235: /***************************************************************************
236: * ItemWndProc()
237: *
238: * This function handles item window message processing.
239: * There is an item window for each OLE object. This was done to
240: * to simplify hit testing and repainting. These windows are child
241: * windows.
242:
243: * returns long - standard child routine
244: **************************************************************************/
245:
246: LONG APIENTRY ItemWndProc( //* ENTRY:
247: HWND hwnd, //* standard windows parameters
248: UINT msg,
249: DWORD wParam,
250: LONG lParam
251: ){ //* LOCAL:
252: static POINT dragPt; //* Mouse drag point
253: static RECT dragRect; //* Mouse drag rectangle
254: static BOOL fCaptured; //* captured flag
255: APPITEMPTR pItem; //* application item pointer
256: PAINTSTRUCT ps; //* paint structure
257: POINT pt; //* point
258: RECT rc; //* bounding rectangle
259:
260: switch (msg)
261: {
262: case WM_SIZE:
263: if (pItem = (APPITEMPTR)GetWindowLong(hwnd,0))
264: {
265: if (!pItem->fServerChangedBounds && pItem->otObject == OT_EMBEDDED)
266: ObjSetBounds(pItem);
267: else
268: pItem->fServerChangedBounds = FALSE;
269: }
270: break;
271:
272: case WM_CHANGE:
273: --cOleWait;
274: pItem = (APPITEMPTR)GetWindowLong(hwnd,0);
275: if (!Error(OleQueryBounds(pItem->lpObject, &rc)))
276: {
277: ConvertToClient(&rc);
278:
279: SetWindowPos(
280: hwnd,
281: NULL,
282: 0,
283: 0,
284: rc.right - rc.left + 2*GetSystemMetrics(SM_CXFRAME),
285: rc.bottom - rc.top + 2*GetSystemMetrics(SM_CYFRAME),
286: SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
287: );
288:
289: if (!pItem->fNew && !fLoadFile)
290: ShowNewWindow(pItem);
291: else
292: InvalidateRect(hwnd, NULL, TRUE);
293:
294: Dirty(DOC_DIRTY);
295: }
296: break;
297:
298: case WM_NCLBUTTONDOWN:
299: SetTopItem((APPITEMPTR)GetWindowLong(hwnd,0));
300: return (DefWindowProc(hwnd, msg, wParam, lParam));
301:
302: case WM_PAINT:
303: BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
304: GetClientRect(hwnd, &rc);
305: pItem = (APPITEMPTR)GetWindowLong(hwnd, 0);
306: //* Call OLE draw
307: Error(OleDraw(pItem->lpObject, ps.hdc, &rc, NULL, NULL));
308:
309: EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
310: break;
311:
312: case WM_LBUTTONDBLCLK: //* execute a verb
313: ANY_OBJECT_BUSY;
314: ExecuteVerb(OLEVERB_PRIMARY,(APPITEMPTR)GetWindowLong(hwnd,0));
315: break;
316:
317: case WM_LBUTTONDOWN:
318: GetWindowRect(hwnd, (LPRECT)&dragRect);
319: ScreenToClient(hwndFrame, (LPPOINT)&dragRect);
320: ScreenToClient(hwndFrame, (LPPOINT)&dragRect.right);
321:
322: dragPt.x = LOWORD(lParam);
323: dragPt.y = HIWORD(lParam);
324:
325: ClientToScreen(hwnd, (LPPOINT)&dragPt);
326: ScreenToClient(hwndFrame, (LPPOINT)&dragPt);
327:
328: SetCapture(hwnd);
329: fCaptured = TRUE;
330: SetTopItem((APPITEMPTR)GetWindowLong(hwnd,0));
331: break;
332:
333: case WM_LBUTTONUP:
334: if (!fCaptured)
335: break;
336: ReleaseCapture();
337: fCaptured = FALSE;
338: Dirty(DOC_DIRTY);
339: break;
340:
341: case WM_MOUSEMOVE:
342: if (!fCaptured)
343: break;
344: pt.x = LOWORD(lParam);
345: pt.y = HIWORD(lParam);
346:
347: ClientToScreen(hwnd, (LPPOINT)&pt);
348: ScreenToClient(hwndFrame, (LPPOINT)&pt);
349:
350: OffsetRect(
351: (LPRECT)&dragRect,
352: pt.x - dragPt.x,
353: pt.y - dragPt.y
354: );
355:
356: MoveWindow(
357: hwnd,
358: dragRect.left, dragRect.top,
359: dragRect.right - dragRect.left,
360: dragRect.bottom - dragRect.top, TRUE
361: );
362:
363: dragPt.x = pt.x;
364: dragPt.y = pt.y;
365: break;
366:
367: default:
368: return (DefWindowProc(hwnd, msg, wParam, lParam));
369: }
370: return 0L;
371:
372: }
373:
374: /****************************************************************************
375: * PostItemCreate()
376: *
377: * This function creates a child window which will contain the newly
378: * created OLE object. A pointer to our item information is stored in the
379: * extra bytes of this window. This is where we internally keep track
380: * of information related to the object as well as the
381: * pointer to the object for subsequent OLE API calls. This routine is
382: * called after an OLE object has been created by the client library.
383: *
384: * Returns BOOL - TRUE if application item has been created.
385: ****************************************************************************/
386:
387: BOOL FAR PostItemCreate( //* ENTRY:
388: LPOLEOBJECT lpObject, //* OLE object pointer
389: LONG otObject, //* OLE object type
390: LPRECT lprcObject, //* object bounding rect
391: APPITEMPTR pItem //* application item pointer
392: ){ //* LOCAL:
393: INT i; //* index
394: RECT rc; //* bounding rectangle
395: CHAR pData[OBJECT_LINK_MAX];//* copy of link data
396:
397: if (lprcObject) //* if the size of the objects
398: rc = *lprcObject; //* bounding rectangle is not
399: else if (OleQueryBounds(lpObject, &rc) == OLE_OK)
400: ConvertToClient(&rc);
401: else
402: SetRect(&rc, 0, 0, 0, 0);
403:
404: if (!(pItem->hwnd = CreateWindow( //* Create the child window
405: szItemClass, "",
406: WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME,
407: rc.left,rc.top,
408: rc.right - rc.left + 2 * GetSystemMetrics(SM_CXFRAME),
409: rc.bottom - rc.top + 2 * GetSystemMetrics(SM_CYFRAME),
410: hwndFrame, NULL, hInst, NULL
411: ))) goto Error;
412:
413: //* in windows extra bytes
414: SetWindowLong(pItem->hwnd, 0, (LONG)pItem);
415:
416: pItem->otObject = otObject;
417: pItem->lpObject = lpObject;
418: pItem->fRetry = TRUE;
419:
420: if( pItem->otObject == OT_EMBEDDED )//* if object is embedded tell library
421: { //* the container name and object name.
422: UINT cb=CBOBJNAMEMAX; //* The name will be the server window title.
423: CHAR sz[CBOBJNAMEMAX]; //* when the object is edited.
424:
425: OleQueryName(lpObject, (LPSTR)sz, (UINT FAR *)&cb );
426:
427:
428: WaitForObject(pItem);
429: Error(OleSetHostNames(lpObject, (LPSTR)szAppName, (LPSTR)sz ));
430: WaitForObject(pItem);
431: }
432: else if (pItem->otObject == OT_LINK)//* if the object is linked
433: { //* retrieve update options
434:
435: WaitForObject(pItem);
436: if(Error(OleGetLinkUpdateOptions(pItem->lpObject, &pItem->uoObject)))
437: goto Error;
438:
439: if (ObjGetData(pItem,pData))
440: {
441: for (i=0; pData[i];i++); //* Skip past the server name
442: pItem->aLinkName = AddAtom(&pData[++i]);
443: }
444: else
445: pItem->aLinkName = AddAtom("");
446: }
447: iObjects++;
448: Dirty(DOC_DIRTY);
449: //* a user interface recommendations.
450: return TRUE; //* SUCCESS return
451:
452: Error: //* ERROR Tag
453:
454: ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
455: FreeAppItem(pItem);
456:
457: return FALSE; //* ERROR return
458:
459: }
460:
461: /***************************************************************************
462: * ConvertToClient()
463: *
464: * This function will convert to client from himetric.
465: **************************************************************************/
466:
467: VOID FAR ConvertToClient( //* ENTRY:
468: LPRECT lprc //* pointer to bounding rectangle
469: ){ //* LOCAL
470:
471: if (!(lprc->left || lprc->top || lprc->right || lprc->bottom))
472: SetRect(lprc, 0, 0, CXDEFAULT, CYDEFAULT);
473: else
474: {
475: HDC hdc = GetDC(NULL);
476:
477: lprc->right -= lprc->left;
478: lprc->bottom -= lprc->top ;
479: lprc->top = lprc->left = NULL;
480:
481: SetMapMode ( hdc, MM_HIMETRIC );
482: LPtoDP ( hdc, (LPPOINT)&lprc->right, 1 );
483:
484: ReleaseDC(NULL, hdc);
485: }
486: }
487:
488: /***************************************************************************
489: * ObjInsert()
490: *
491: * Query the user for object type to insert and insert the new OLE object
492: ***************************************************************************/
493:
494: VOID FAR ObjInsert( //* ENTRY:
495: LHCLIENTDOC lhcDoc, //* OLE document handle
496: LPOLECLIENT lpClient //* pointer to OLE client structure
497: ){ //* LOCAL:
498: LPOLEOBJECT lpObject; //* pointer to OLE object
499: APPITEMPTR pItem; //* item pointer
500: CHAR szServerName[CBPATHMAX];//* Class name for OleCreate()
501: CHAR szClassName[CBPATHMAX];//* Class name for OleCreate()
502: CHAR szTmp[CBOBJNAMEMAX]; //* buffer to unique object name
503:
504: if (DialogBoxParam(hInst, MAKEINTRESOURCE(DTCREATE),hwndFrame,
505: fnInsertNew, (LONG)((LPSTR)szClassName)) != IDCANCEL)
506: {
507: if (pItem = PreItemCreate(lpClient, FALSE, lhcDoc))
508: {
509: RegGetClassId(szServerName, szClassName);
510: pItem->aServer = AddAtom(szServerName);
511: if ( Error( OleCreate(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),
512: (LPSTR)szClassName, lhcDoc,CreateNewUniqueName(szTmp),
513: &lpObject,olerender_draw, 0)))
514: {
515: ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
516: FreeAppItem(pItem);
517: }
518: else
519: PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
520: }
521: }
522:
523: FreeProcInstance(lpfnInsertNew);
524:
525: }
526:
527: /***************************************************************************
528: * ObjDelete()
529: *
530: * Delete an OLE object. For this application, all OLE objects
531: * are associated with a child window; therefore the window must be
532: * destroyed.
533: *
534: * NOTE: There is one case when we call OleRelease and the other when
535: * we call OleDelete. We call OleRelease when we are deregistering
536: * a document and OleDelete when removing an object from a document.
537: **************************************************************************/
538:
539: VOID FAR ObjDelete( //* ENTRY:
540: APPITEMPTR pItem, //* pointer to application item
541: BOOL fDelete //* delete or release flag
542: ){ //* LOCAL:
543:
544: if (pItem->lpObjectUndo)
545: {
546: Error(OleDelete(pItem->lpObjectUndo));
547: //* wait for asynchronous operation
548: WaitForObject(pItem);
549: }
550:
551: if (fDelete ? Error(OleDelete(pItem->lpObject))
552: : Error(OleRelease(pItem->lpObject)))
553: {
554: ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
555: return; //* ERROR return
556: }
557:
558: if (pItem->fVisible)
559: {
560: ShowWindow(pItem->hwnd, SW_HIDE);
561: pItem->fVisible = FALSE;
562: }
563: //* the operation has to complete
564: WaitForObject(pItem); //* before the application structure
565:
566: FreeAppItem(pItem);
567: iObjects--;
568:
569: }
570:
571:
572: /***************************************************************************
573: * ObjPaste()
574: *
575: * This function obtains an object from the clipboard.
576: * Handles both embedded and linked objects. An item window is
577: * created for each new object.
578: *
579: * Returns BOOL - TRUE if object was pasted succesfully.
580: **************************************************************************/
581:
582: VOID FAR ObjPaste( //* ENTRY:
583: BOOL fPaste, //* Paste/PasteLink flag
584: LHCLIENTDOC lhcDoc, //* client document handle
585: LPOLECLIENT lpClient //* pointer to client
586: ){ //* LOCAL:
587: LPOLEOBJECT lpObject; //* object pointer
588: LONG otObject; //* object type
589: APPITEMPTR pItem; //* application item pointer
590: CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name string
591:
592: if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
593: return; //* ERROR return
594:
595: if (!OpenClipboard(hwndFrame))
596: goto Error; //* ERROR jump
597:
598:
599: if (fPaste) //* PASTE the object.
600: { //* Try "StdFileEditing" protocol
601: if (Error(OleCreateFromClip(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),lhcDoc,
602: CreateNewUniqueName(szTmp),&lpObject, olerender_draw,0)))
603: {
604: //* next try "Static" protocol
605: if (Error(OleCreateFromClip(
606: STATICP, (LPOLECLIENT)&(pItem->oleclient), lhcDoc,
607: CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
608: goto Error; //* ERROR jump
609: }
610: }
611: else
612: { //* LINK therefore must be
613: // "STdFileEditing" protocol
614: if (Error(OleCreateLinkFromClip(
615: STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient), lhcDoc,
616: CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
617: goto Error; //* ERROR jump
618: }
619:
620: OleQueryType(lpObject, &otObject);
621: CloseClipboard();
622:
623: if (!PostItemCreate(lpObject, otObject, NULL, pItem))
624: return; //* ERROR return
625:
626: ShowNewWindow(pItem);
627: return; //* SUCCESS return
628:
629:
630: Error: //* TAG Error
631:
632: ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
633: CloseClipboard();
634: FreeAppItem(pItem);
635:
636: return; //* ERROR return
637:
638: }
639:
640: /***************************************************************************
641: * ObjCopy()
642: *
643: * This function places an OLE object on the clipboard via the \
644: * OleCopyToClipboard() function.
645: *
646: * Returns BOOL - TRUE if object successfully placed on clipboard
647: **************************************************************************/
648:
649: BOOL FAR ObjCopy( //* ENTRY:
650: APPITEMPTR pItem //* pointer to app item
651: ){ //* LOCAL:
652: BOOL fReturn = TRUE; //* return value
653:
654: if (!OpenClipboard(hwndFrame))
655: return FALSE; //* ERROR return
656:
657: EmptyClipboard();
658:
659: if (Error(OleCopyToClipboard(pItem->lpObject)))
660: fReturn = FALSE; //* prepare for ERROR out
661:
662: CloseClipboard();
663: return fReturn; //* ERROR or SUCCESS
664:
665: }
666:
667: /***************************************************************************
668: * ObjCreateFromTemplate()
669: *
670: * Creates an embedded object from file.
671: **************************************************************************/
672:
673: VOID FAR ObjCreateFromTemplate( //* ENTRY:
674: LHCLIENTDOC lhcDoc, //* client document handle
675: LPOLECLIENT lpClient //* client vtbl. pointer
676: ){ //* LOCAL:
677: LPOLEOBJECT lpObject; //* OLE object pointer
678: APPITEMPTR pItem; //* application item pointer
679: CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name string
680: CHAR szFileName[CBPATHMAX];//* file name string
681:
682: *szFileName = NULL;
683:
684: if (!OfnGetName(hwndFrame, szFileName, IDM_INSERTFILE))
685: return; //* ERROR operation aborted by user
686:
687: if (!(pItem = PreItemCreate(lpClient, FALSE, lhcDoc)))
688: return; //* ERROR
689:
690: if (Error(OleCreateFromTemplate(STDFILEEDITING, (LPOLECLIENT)pItem, szFileName,
691: lhcDoc, CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
692: {
693: ErrorMessage(E_CREATE_FROM_TEMPLATE);
694: FreeAppItem(pItem);
695: return; //* ERROR
696: }
697:
698: PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
699:
700: } //* SUCCESS
701:
702:
703: /****************************************************************************
704: * ObjGetData()
705: *
706: * Get the object link data. The data that is retrieved from OLE is copied
707: * into lpLinkData if lpLinkData is not NULL. Otherwise, space is dynamically
708: * allocated or reallocated; space is allocated if pItem->lpLinkData is NULL
709: * otherwise the pointer is reallocated. The data is returned is freed if
710: * there has been an OLE_WARN_DELETE_DATA error.
711: ***************************************************************************/
712:
713: BOOL FAR ObjGetData( //* ENTRY:
714: APPITEMPTR pItem, //* OLE object
715: LPSTR lpLinkData //* pointer to linkdata
716: ){ //* LOCAL:
717: HANDLE hData; //* handle to OLE link data
718: LPSTR lpData; //* pointer to OLE link data
719: LPSTR lpWork; //* copy of OLE link data
720: BOOL fFree = FALSE; //* free OLE memory flag
721: LONG lSize; //* size of OLE link data
722: INT i;
723:
724: switch (Error(OleGetData(pItem->lpObject,
725: (OLECLIPFORMAT)(pItem->otObject == OT_LINK ? vcfLink : vcfOwnerLink), &hData)))
726: {
727: case OLE_WARN_DELETE_DATA:
728: fFree = TRUE;
729: case OLE_OK:
730: if(lpData = GlobalLock(hData))
731: {
732: //* copy the link data to new buffer
733: lSize=SizeOfLinkData(lpData);
734:
735: if (!lpLinkData)
736: {
737: if (!pItem->lpLinkData) //* allocate
738: AllocLinkData(pItem,lSize);
739: else //* otherwise reallocate
740: ReallocLinkData(pItem,lSize);
741: lpWork = pItem->lpLinkData;
742: }
743: else
744: lpWork = lpLinkData;
745:
746: if (lpWork)
747: for (i=0L; i<(INT)lSize; i++)
748: *(lpWork+i)=*(lpData+i);
749:
750: GlobalUnlock(hData); //* free the linked data as needed
751: if (fFree)
752: GlobalFree(hData);
753:
754: return TRUE; //* SUCCESS
755: }
756: default:
757: return FALSE; //* FAILURE
758: }
759:
760: }
761:
762: /***************************************************************************
763: * ObjChangeLink()
764: *
765: * Change the linkdata. This routine will change the document portion of
766: * link data to lpDoc. The old linkdata is expected to be in
767: * lpaItem->lpLinkData
768: **************************************************************************/
769:
770: VOID FAR ObjChangeLinkData( //* ENTRY:
771: APPITEMPTR pItem, //* OLE object
772: LPSTR lpDoc //* document name
773: ){ //* LOCAL:
774: LONG lSize; //* used to link data size
775: LPSTR lpLinkData; //* OLE link data pointer
776: static CHAR pWork[OBJECT_LINK_MAX]; //* used to construct new link data
777: INT i; //* index
778:
779: pItem->aLinkName = AddAtom(lpDoc);
780:
781: for (
782: lpLinkData = pItem->lpLinkData, i=0;
783: pWork[i] = *lpLinkData;
784: lpLinkData++, i++
785: );
786: //* into working buffer.
787: lstrcpy((LPSTR)&pWork[++i],lpDoc); //* copy new document name.
788:
789: for (; pWork[i]; i++); //* skip to end of document name
790: for (++lpLinkData;*lpLinkData;lpLinkData++);
791: //* copy item name.
792: lstrcpy((LPSTR)&pWork[++i],++lpLinkData);
793: for (; pWork[i]; i++); //* skip to end of buffer
794: //* which is the end of item info.
795: pWork[++i] = NULL; //* add extra null.
796:
797: lSize = SizeOfLinkData(pWork); //* reallocate space so there is
798: ReallocLinkData(pItem,lSize); //* a properly sized block of info
799: //* to send the linked data to the
800: if (lpLinkData = pItem->lpLinkData) //* OLE DLL.
801: for (i=0; i<(INT)lSize; i++) //* copy new linkdata into this space
802: *lpLinkData++ = pWork[i];
803: else
804: return; //* ERROR return
805:
806: Error(OleSetData(pItem->lpObject, vcfLink, GlobalHandle(pItem->lpLinkData)));
807:
808: } //* SUCCESS return
809:
810: /****************************************************************************
811: * ObjSaveUndo()
812: *
813: * Clone the OLE object so that any changes to object can be undone if the
814: * user choses to exit without update.
815: ***************************************************************************/
816:
817: VOID FAR ObjSaveUndo( //* ENTRY:
818: APPITEMPTR pItem //* application item
819: ){ //* LOCAL:
820: CHAR szTmp[CBOBJNAMEMAX]; //* holder of object name
821: LPSTR lpClone; //* pointer to clond object name
822: UINT i=CBOBJNAMEMAX;
823:
824: if (!pItem->lpObjectUndo)
825: {
826: OleQueryName(pItem->lpObject, szTmp, &i);
827: //* give clone a unique name by
828: //* altering object name prefix.
829: for (lpClone = OBJCLONE, i=0; *lpClone; szTmp[i++] = *lpClone++);
830:
831: if (Error(OleClone(pItem->lpObject, (LPOLECLIENT)pItem,
832: pItem->lhcDoc, szTmp, &(pItem->lpObjectUndo))))
833: return; //* ERROR return
834:
835: pItem->otObjectUndo = pItem->otObject;
836: pItem->uoObjectUndo = pItem->uoObject;
837: pItem->aLinkUndo = pItem->aLinkName;
838:
839: GetClientRect(pItem->hwnd, &pItem->rect);
840:
841: if (OleQueryOpen(pItem->lpObject) == OLE_OK)
842: pItem->fOpen = TRUE;
843:
844: }
845:
846: } //* SUCCESS return
847:
848: /****************************************************************************
849: * ObjUndo()
850: *
851: * Restore an object to its state before changes. The lpObject Undo is a
852: * clone to the original object with a different name, therefore, all we
853: * have to do is rename that object and ditch the changed object.
854: ***************************************************************************/
855:
856: VOID FAR ObjUndo( //* ENTRY:
857: APPITEMPTR pItem //* application item
858: ){ //* LOCAL:
859: CHAR szTmp[CBOBJNAMEMAX]; //* object name holder
860: UINT i = CBOBJNAMEMAX;
861:
862: OleQueryName(pItem->lpObject, szTmp, &i);
863: if (Error(OleDelete(pItem->lpObject)))
864: return; //* ERROR return
865: //* reset app item vars
866: pItem->lpObject = pItem->lpObjectUndo;
867: pItem->otObject = pItem->otObjectUndo;
868: pItem->uoObject = pItem->uoObjectUndo;
869: pItem->aLinkName = pItem->aLinkUndo;
870: pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
871: pItem->otObjectUndo = (LONG)NULL;
872:
873: if (Error(OleRename(pItem->lpObject,szTmp)))
874: return; //* ERROR return
875:
876: if (pItem->fOpen)
877: {
878: Error(OleReconnect(pItem->lpObject));
879: pItem->fOpen = FALSE;
880: }
881:
882: SetWindowPos(
883: pItem->hwnd,
884: NULL, 0, 0,
885: pItem->rect.right - pItem->rect.left + 2*GetSystemMetrics(SM_CXFRAME),
886: pItem->rect.bottom - pItem->rect.top + 2*GetSystemMetrics(SM_CYFRAME),
887: SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
888: );
889:
890: InvalidateRect(pItem->hwnd,NULL,TRUE);
891:
892: } //* SUCCESS return
893:
894:
895: /****************************************************************************
896: * ObjDelUndo()
897: *
898: * Delete the undo object if the user is happy with the changes he/she made.
899: ***************************************************************************/
900:
901: VOID FAR ObjDelUndo( //* ENTRY:
902: APPITEMPTR pItem //* application item
903: ){
904:
905: if (Error(OleDelete(pItem->lpObjectUndo)))
906: return; //* ERROR return
907:
908: pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
909: pItem->otObjectUndo = (LONG)NULL;
910: DeleteAtom(pItem->aLinkUndo);
911: pItem->lpObjectUndo = NULL;
912:
913: } //* SUCCESS return
914:
915: /****************************************************************************
916: * ObjFreeze()
917: *
918: * Convert an object to a static object.
919: ***************************************************************************/
920:
921: VOID FAR ObjFreeze( //* ENTRY:
922: APPITEMPTR pItem //* application item
923: ){ //* LOCAL:
924: CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name
925: LPSTR lpTemp; //* temporary prefix string
926: LPOLEOBJECT lpObjectTmp; //* temporary object pointer
927: UINT i=CBOBJNAMEMAX;
928:
929: OleQueryName(pItem->lpObject, szTmp, &i);
930: //* create a unique name by changing
931: //* the object name prefix
932: for (lpTemp = OBJTEMP, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
933:
934: //* this API creates a static object
935: if (Error(OleObjectConvert(pItem->lpObject, STATICP, (LPOLECLIENT)pItem,
936: pItem->lhcDoc, szTmp, &lpObjectTmp)))
937: return;
938: //* delete old object
939: if (Error(OleDelete(pItem->lpObject)))
940: return;
941:
942: WaitForObject(pItem);
943:
944: pItem->lpObject = lpObjectTmp;
945: pItem->otObject = OT_STATIC;
946: pItem->uoObject = -1L;
947:
948: for (lpTemp = OBJPREFIX, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
949: if (Error(OleRename(pItem->lpObject,szTmp)))
950: return;
951:
952:
953: }
954:
955: /***************************************************************************
956: * ObjCreateWrap()
957: *
958: * Create a wrapped object from the drag and drop feature of the 3.1 shell.
959: * NOTE: We are assuming that only one file has been dropped. See the SDK
960: * documentation for instructions on how to deal with multiple files.
961: ***************************************************************************/
962:
963: VOID FAR ObjCreateWrap( //* ENTRY:
964: HANDLE hdrop, //* handle to dropped object
965: LHCLIENTDOC lhcDoc, //* document handle
966: LPOLECLIENT lpClient //* pointer to client structure
967: ){ //* LOCAL:
968: CHAR szDragDrop[CBPATHMAX];//* Drag and drop file name
969: LPOLEOBJECT lpObject; //* pointer to OLE object
970: POINT pt; //* position of dropped object
971: RECT rc; //* object size and position
972: CHAR szTmp[CBOBJNAMEMAX]; //* buffer for unique object name
973: APPITEMPTR pItem; //* application item pointer
974: INT x,y; //* icon sizes
975:
976: x = GetSystemMetrics(SM_CXICON) / 2;
977: y = GetSystemMetrics(SM_CYICON) / 2;
978: //* Get the drag and drop filename
979: //* position
980: DragQueryPoint(hdrop, &pt);
981: DragQueryFile(hdrop, 0, szDragDrop, CBPATHMAX);
982: DragFinish(hdrop);
983:
984: SetRect(&rc, pt.x - x, pt.y - y, pt.x + x, pt.y + y);
985:
986: if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
987: return; //* ERROR return
988: //* create OLE object
989: if (Error(OleCreateFromFile(STDFILEEDITING, (LPOLECLIENT)pItem,
990: "Package", szDragDrop, lhcDoc, CreateNewUniqueName(szTmp),
991: &lpObject, olerender_draw, 0)))
992: {
993: ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
994: FreeAppItem(pItem);
995: return; //* ERROR return
996: }
997:
998: if (PostItemCreate(lpObject, OT_EMBEDDED, &rc, pItem))
999: ShowNewWindow(pItem);
1000:
1001: } //* SUCCESS return
1002:
1003: /***************************************************************************
1004: * UpdateObjectMenuItem()
1005: *
1006: * Add an object popup menu for the chosen object if multiple verbs exist.
1007: * The registration system is used to determine which verbs exist for the
1008: * given object.
1009: **************************************************************************/
1010:
1011: VOID FAR UpdateObjectMenuItem( //* ENTRY:
1012: HMENU hMenu //* main menu
1013: ){ //* LOCAL
1014: INT cVerbs; //* verb
1015: APPITEMPTR pItem; //* application item ponter
1016: DWORD dwSize = KEYNAMESIZE;
1017: CHAR szClass[KEYNAMESIZE], szBuffer[200];
1018: CHAR szVerb[KEYNAMESIZE];
1019: HMENU hPopupNew=NULL;
1020: HKEY hkeyTemp;
1021: CHAR pLinkData[OBJECT_LINK_MAX];
1022: //* delete current item and submenu
1023: DeleteMenu(hMenu, POS_OBJECT, MF_BYPOSITION );
1024:
1025: if (!(pItem = GetTopItem()) )
1026: goto Error; //* ERROR jump
1027: else if (!pItem->fVisible)
1028: goto Error; //* ERROR jump
1029: //* if STATIC ?
1030: if ((pItem->otObject != OT_EMBEDDED) && (pItem->otObject != OT_LINK))
1031: goto Error; //* ERROR jump
1032:
1033: if (!ObjGetData(pItem, pLinkData)) //* get linkdata as key reg database
1034: goto Error; //* ERROR jump
1035: //* open reg database
1036: szClass[0] = NULL;
1037: if (RegOpenKey(HKEY_CLASSES_ROOT, szClass, &hkeyTemp))
1038: goto Error; //* ERROR jump
1039: //* check if class is reg-db
1040: if (RegQueryValue(HKEY_CLASSES_ROOT, pLinkData, szClass, &dwSize))
1041: {
1042: RegCloseKey(hkeyTemp);
1043: goto Error; //* ERROR jump
1044: }
1045:
1046: for (cVerbs=0; ;++cVerbs) //* extract all verbs from reg-db
1047: {
1048: dwSize = KEYNAMESIZE;
1049: wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
1050: (LPSTR)pLinkData,cVerbs);
1051:
1052: if (RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &dwSize))
1053: break;
1054:
1055: if (!hPopupNew)
1056: hPopupNew = CreatePopupMenu();
1057:
1058: InsertMenu(hPopupNew, (UINT)-1, MF_BYPOSITION, IDM_VERBMIN+cVerbs, szVerb);
1059: }
1060:
1061: //* NOTE: For International versions the following verb menu
1062: //* may need to be formatted differently.
1063:
1064: switch (cVerbs) //* determine how many verbs found
1065: {
1066: case 0: //* none
1067: wsprintf(szBuffer, "Edit %s %s", (LPSTR)szClass, (LPSTR)"&Object");
1068: InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
1069: break;
1070:
1071: case 1: //* one
1072: wsprintf(szBuffer, "%s %s %s", (LPSTR)szVerb, (LPSTR)szClass,
1073: (LPSTR)"&Object");
1074: DestroyMenu(hPopupNew);
1075: InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
1076: break;
1077:
1078: default: //* > 1
1079: wsprintf(szBuffer, "%s %s", (LPSTR)szClass, (LPSTR)"&Object");
1080: InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION | MF_POPUP, (UINT)hPopupNew, szBuffer);
1081: EnableMenuItem(hMenu, POS_OBJECT, MF_ENABLED|MF_BYPOSITION);
1082: break;
1083: }
1084:
1085: RegCloseKey(hkeyTemp); //* close reg-db
1086: return; //* SUCCESS return
1087:
1088: Error: //* ERROR tag
1089: InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, NULL, "&Object");
1090: EnableMenuItem(hMenu, POS_OBJECT, MF_GRAYED | MF_BYPOSITION);
1091:
1092: } //* ERROR return
1093:
1094: /***************************************************************************
1095: * ExecuteVerb()
1096: *
1097: * Execute the verb for the given object.
1098: ***************************************************************************/
1099:
1100: VOID FAR ExecuteVerb( //* ENTRY:
1101: UINT iVerb, //* verb
1102: APPITEMPTR pItem //* application item pointer
1103: ){ //* LOCAL
1104: RECT rc; //* holds client area bounding rect
1105:
1106: if (pItem->otObject == OT_STATIC) //* if the object is static beep
1107: {
1108: ErrorMessage(W_STATIC_OBJECT);
1109: return; //* return
1110: }
1111: //* get cliet area rectangle
1112: GetClientRect(hwndFrame, (LPRECT)&rc);
1113: //* execute OLE verb
1114: if (Error(OleActivate(pItem->lpObject, iVerb, TRUE, TRUE, hwndFrame, &rc)))
1115: return;
1116:
1117: WaitForObject(pItem); //* wait for async. operation
1118:
1119: ObjSetBounds(pItem);
1120:
1121:
1122: } //* SUCCESS return
1123:
1124: /****************************************************************************
1125: * ObjSetBounds
1126: *
1127: * Set the object bounds. The object bounds are the child windos bounding
1128: * rectangle. OLE servers recieve need the bounding rectangle in HIMETRIC
1129: * coordinates. So, we convert from screen coordinates to HIMETRIC.
1130: *
1131: * Returns BOOL - TRUE if successful.
1132: ***************************************************************************/
1133:
1134: BOOL FAR ObjSetBounds( //* ENTRY:
1135: APPITEMPTR pItem //* application item pointer
1136: ){ //* LOCAL:
1137: RECT itemRect; //* bounding rectangle
1138: HDC hdc;
1139:
1140: GetWindowRect(pItem->hwnd,&itemRect);//* get item window react
1141:
1142: itemRect.right = ( itemRect.right - itemRect.left ) - 2 * GetSystemMetrics(SM_CXFRAME);
1143: itemRect.bottom = ( itemRect.bottom - itemRect.top ) - 2 * GetSystemMetrics(SM_CYFRAME);
1144: itemRect.top = NULL;
1145: itemRect.left = NULL;
1146:
1147: hdc = GetDC(NULL);
1148: SetMapMode(hdc,MM_HIMETRIC);
1149:
1150: DPtoLP(hdc,(LPPOINT)&itemRect.right,1);
1151:
1152: ReleaseDC(NULL,hdc);
1153: //* set the rect for the server
1154: if (Error(OleSetBounds(pItem->lpObject,(LPRECT)&itemRect)))
1155: return FALSE; //* ERROR return
1156:
1157: WaitForObject(pItem); //* wait for async. operation
1158: return TRUE; //* SUCCESS return
1159:
1160: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.