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