|
|
1.1 root 1: /*
2: * PASTESPL.C
3: *
4: * Implements the OleUIPasteSpecial function which invokes the complete
5: * Paste Special dialog.
6: *
7: * Copyright (c)1992 Microsoft Corporation, All Rights Reserved
8: */
9:
10: #define STRICT 1
11: #include "ole2ui.h"
12: #include "pastespl.h"
13: #include "common.h"
14: #include "utility.h"
15: #include "resimage.h"
16: #include "iconbox.h"
17: #include "geticon.h"
18: #include "regdb.h"
19: #include <stdlib.h>
20:
21: OLEDBGDATA
22:
23: /*
24: * OleUIPasteSpecial
25: *
26: * Purpose:
27: * Invokes the standard OLE Paste Special dialog box which allows the user
28: * to select the format of the clipboard object to be pasted or paste linked.
29: *
30: * Parameters:
31: * lpPS LPOLEUIPasteSpecial pointing to the in-out structure
32: * for this dialog.
33: *
34: * Return Value:
35: * UINT One of the following codes or one of the standard error codes (OLEUI_ERR_*)
36: * defined in OLE2UI.H, indicating success or error:
37: * OLEUI_OK User selected OK
38: * OLEUI_CANCEL User cancelled the dialog
39: * OLEUI_IOERR_SRCDATAOBJECTINVALID lpSrcDataObject field of OLEUIPASTESPECIAL invalid
40: * OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid
41: * OLEUI_IOERR_ARRLINKTYPESINVALID arrLinkTypes field of OLEUIPASTESPECIAL invalid
42: * OLEUI_PSERR_CLIPBOARDCHANGED Clipboard contents changed while dialog was up
43: */
44:
45: STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS)
46: {
47: UINT uRet;
48: HGLOBAL hMemDlg=NULL;
49:
50: uRet=UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL)
51: , &hMemDlg);
52:
53: if (uRet != OLEUI_SUCCESS)
54: return uRet;
55:
56: //Validate PasteSpecial specific fields
57: if (NULL == lpPS->lpSrcDataObj || IsBadReadPtr(lpPS->lpSrcDataObj, sizeof(IDataObject)))
58: uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID;
59: if (NULL == lpPS->arrPasteEntries || IsBadReadPtr(lpPS->arrPasteEntries, sizeof(OLEUIPASTEENTRY)))
60: uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID;
61: if (NULL != lpPS->arrLinkTypes && IsBadReadPtr(lpPS->arrLinkTypes, sizeof(UINT)))
62: uRet = OLEUI_IOERR_ARRLINKTYPESINVALID;
63: if (uRet >= OLEUI_ERR_STANDARDMIN)
64: {
65: if (NULL != hMemDlg)
66: FreeResource(hMemDlg);
67: return uRet;
68: }
69:
70: //Now that we've validated everything, we can invoke the dialog.
71: uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS
72: , hMemDlg, MAKEINTRESOURCE(IDD_PASTESPECIAL));
73:
74: /*
75: * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
76: */
77:
78: return uRet;
79: }
80:
81:
82: /*
83: * PasteSpecialDialogProc
84: *
85: * Purpose:
86: * Implements the OLE Paste Special dialog as invoked through the
87: * OleUIPasteSpecial function.
88: *
89: * Parameters:
90: * Standard
91: *
92: * Return Value:
93: * Standard
94: */
95:
96: BOOL CALLBACK EXPORT PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
97: {
98: LPOLEUIPASTESPECIAL lpOPS;
99: LPPASTESPECIAL lpPS;
100: BOOL fHook=FALSE;
101: HCURSOR hCursorOld;
102:
103: //Declare Win16/Win32 compatible WM_COMMAND parameters.
104: COMMANDPARAMS(wID, wCode, hWndMsg);
105:
106: //This will fail under WM_INITDIALOG, where we allocate it.
107: lpPS=(LPPASTESPECIAL)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &fHook);
108:
109: //If the hook processed the message, we're done.
110: if (0!=fHook)
111: return fHook;
112:
113: // Process help message from Change Icon
114: if (iMsg == uMsgHelp)
115: {
116: PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam);
117: return FALSE;
118: }
119:
120: //Process the temination message
121: if (iMsg==uMsgEndDialog)
122: {
123: HWND hwndNextViewer;
124:
125: // Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected
126: if (lpPS->fLink)
127: OleUIMetafilePictIconFree(lpPS->hMetaPictOD);
128: else OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
129:
130: // Free data associated with each list box entry
131: FreeListData(GetDlgItem(hDlg, ID_PS_PASTELIST));
132: FreeListData(GetDlgItem(hDlg, ID_PS_PASTELINKLIST));
133:
134: //Free any specific allocations before calling StandardCleanup
135: if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc);
136: if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc);
137: if (lpPS->hBuff) GlobalFree(lpPS->hBuff);
138:
139: // Change the clipboard notification chain
140: hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
141: if (hwndNextViewer != HWND_BROADCAST)
142: {
143: SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
144: ChangeClipboardChain(hDlg, hwndNextViewer);
145: }
146: RemoveProp(hDlg, NEXTCBVIEWER);
147:
148: StandardCleanup(lpPS, hDlg);
149: EndDialog(hDlg, wParam);
150: return TRUE;
151: }
152:
153: switch (iMsg)
154: {
155: case WM_INITDIALOG:
156: hCursorOld = HourGlassOn();
157: FPasteSpecialInit(hDlg, wParam, lParam);
158: HourGlassOff(hCursorOld);
159: return TRUE;
160:
161: case WM_DRAWCLIPBOARD:
162: {
163: HWND hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
164:
165: if (hwndNextViewer == HWND_BROADCAST)
166: break;
167:
168: if (hwndNextViewer)
169: {
170: SendMessage(hwndNextViewer, iMsg, wParam, lParam);
171: // Refresh next viewer in case it got modified
172: // by the SendMessage() (likely if multiple
173: // PasteSpecial dialogs are up simultaneously)
174: hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
175: }
176: SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
177: ChangeClipboardChain(hDlg, hwndNextViewer);
178: wParam = OLEUI_PSERR_CLIPBOARDCHANGED;
179: goto LCancel;
180: }
181:
182: case WM_CHANGECBCHAIN:
183: {
184: HWND hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
185:
186: if (wParam == (WORD)hwndNextViewer)
187: SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)LOWORD(lParam)));
188: else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST)
189: SendMessage(hwndNextViewer, iMsg, wParam, lParam);
190: break;
191: }
192:
193: case WM_COMMAND:
194: switch (wID)
195: {
196: case ID_PS_PASTE:
197: FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
198: break;
199:
200: case ID_PS_PASTELINK:
201: FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
202: break;
203:
204: case ID_PS_DISPLAYLIST:
205: switch (wCode)
206: {
207: case LBN_SELCHANGE:
208: ChangeListSelection(hDlg, lpPS, hWndMsg);
209: break;
210:
211: case LBN_DBLCLK:
212: // Same as pressing OK
213: SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
214: break;
215: }
216: break;
217:
218: case ID_PS_DISPLAYASICON:
219: ToggleDisplayAsIcon(hDlg, lpPS);
220: break;
221:
222: case ID_PS_CHANGEICON:
223: ChangeIcon(hDlg, lpPS);
224: break;
225:
226: case IDOK:
227: lpOPS = lpPS->lpOPS;
228: // Return current flags
229: lpOPS->dwFlags = lpPS->dwFlags;
230: // Return index of arrPasteEntries[] corresponding to format selected by user
231: lpOPS->nSelectedIndex = lpPS->nSelectedIndex;
232: // Return if user selected Paste or PasteLink
233: lpOPS->fLink = lpPS->fLink;
234: // Return metafile with icon and icon title that the user selected
235: lpOPS->hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY,
236: IBXM_IMAGEGET, 0, 0L);
237: SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
238: break;
239:
240: case IDCANCEL:
241: wParam = OLEUI_CANCEL;
242: LCancel:
243: // Free icon and icon title metafile
244: SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L);
245: SendMessage(hDlg, uMsgEndDialog, wParam, 0L);
246: break;
247:
248: case ID_OLEUIHELP:
249: PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp,
250: (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0));
251: break;
252: }
253: break;
254: }
255: return FALSE;
256: }
257:
258:
259: /*
260: * FPasteSpecialInit
261: *
262: * Purpose:
263: * WM_INITIDIALOG handler for the Paste Special dialog box.
264: *
265: * Parameters:
266: * hDlg HWND of the dialog
267: * wParam WPARAM of the message
268: * lParam LPARAM of the message
269: *
270: * Return Value:
271: * BOOL Value to return for WM_INITDIALOG.
272: */
273:
274: BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
275: {
276: LPPASTESPECIAL lpPS;
277: LPOLEUIPASTESPECIAL lpOPS;
278: HFONT hFont;
279: BOOL fPasteAvailable, fPasteLinkAvailable;
280: STGMEDIUM medium;
281: LPOBJECTDESCRIPTOR lpOD;
282: LPLINKSRCDESCRIPTOR lpLSD;
283: int n;
284: CLIPFORMAT cfFormat;
285:
286: // Copy the structure at lParam into our instance memory.
287: lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), TRUE, &hFont);
288:
289: // PvStandardInit sent a termination to us already.
290: if (NULL == lpPS)
291: return FALSE;
292:
293: lpOPS=(LPOLEUIPASTESPECIAL)lParam;
294:
295: // Copy other information from lpOPS that we might modify.
296: lpPS->lpOPS = lpOPS;
297: lpPS->dwFlags = lpOPS->dwFlags;
298:
299: // Initialize user selections in the Paste and PasteLink listboxes
300: lpPS->nPasteListCurSel = 0;
301: lpPS->nPasteLinkListCurSel = 0;
302:
303: // If we got a font, send it to the necessary controls.
304: if (NULL!=hFont)
305: {
306: SendDlgItemMessage(hDlg, ID_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L);
307: SendDlgItemMessage(hDlg, ID_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
308: }
309:
310: // Hide the help button if required
311: if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP))
312: StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
313:
314: // PSF_CHECKDISPLAYASICON is an OUT flag. Clear it if has been set on the way in.
315: lpPS->dwFlags = lpPS->dwFlags & ~PSF_CHECKDISPLAYASICON;
316:
317: // Change the caption if required
318: if (NULL != lpOPS->lpszCaption)
319: SetWindowText(hDlg, lpOPS->lpszCaption);
320:
321: // Load 'Unknown Source' and 'Unknown Type' strings
322: n = LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN);
323: if (n)
324: n = LoadString(ghInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN);
325: if (!n)
326: {
327: PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
328: return FALSE;
329: }
330: lpPS->szAppName[0]='\0';
331:
332: // GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an OLE1 object (offering CF_OWNERLINK)
333: // or has been copied to clipboard by FileMaager (offering CF_FILENAME), an OBJECTDESCRIPTOR will be
334: // created will be created from CF_OWNERLINK or CF_FILENAME. See OBJECTDESCRIPTOR for more info.
335:
336: if (lpPS->hObjDesc = OleStdFillObjectDescriptorFromData(lpOPS->lpSrcDataObj, &medium, &cfFormat))
337: {
338: lpOD = GlobalLock(lpPS->hObjDesc);
339:
340: // Get FullUserTypeName, SourceOfCopy and CLSID
341: if (lpOD->dwFullUserTypeName)
342: lpPS->szFullUserTypeNameOD = (LPSTR)lpOD+lpOD->dwFullUserTypeName;
343: else lpPS->szFullUserTypeNameOD = lpPS->szUnknownType;
344:
345: if (lpOD->dwSrcOfCopy)
346: {
347: lpPS->szSourceOfDataOD = (LPSTR)lpOD+lpOD->dwSrcOfCopy;
348: // If CF_FILENAME was offered, source of copy is a path name. Fit the path to the
349: // static control that will display it.
350: if (cfFormat == cfFileName)
351: lpPS->szSourceOfDataOD = ChopText(GetDlgItem(hDlg, ID_PS_SOURCETEXT), 0, lpPS->szSourceOfDataOD);
352: }
353: else lpPS->szSourceOfDataOD = lpPS->szUnknownSource;
354:
355: lpPS->clsidOD = lpOD->clsid;
356:
357: // Does source specify DVASPECT_ICON?
358: if (lpOD->dwDrawAspect & DVASPECT_ICON)
359: lpPS->fSrcAspectIconOD = TRUE;
360: else lpPS->fSrcAspectIconOD = FALSE;
361:
362: // Does source specify OLEMISC_ONLYICONIC?
363: if (lpOD->dwStatus & OLEMISC_ONLYICONIC)
364: lpPS->fSrcOnlyIconicOD = TRUE;
365: else lpPS->fSrcOnlyIconicOD = FALSE;
366:
367: // Get application name of source from auxusertype3 in the registration database
368: if (0==OleStdGetAuxUserType(&lpPS->clsidOD, 3, lpPS->szAppName, OLEUI_CCHKEYMAX, NULL))
369: {
370: // Use "the application which created it" as the name of the application
371: if (0==LoadString(ghInst, IDS_PSUNKNOWNAPP, lpPS->szAppName, PS_UNKNOWNSTRLEN))
372: {
373: PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
374: return FALSE;
375: }
376: }
377:
378: // Retrieve an icon from the object
379: if (lpPS->fSrcAspectIconOD)
380: {
381: lpPS->hMetaPictOD = OleStdGetData(
382: lpOPS->lpSrcDataObj,
383: CF_METAFILEPICT,
384: NULL,
385: DVASPECT_ICON,
386: &medium
387: );
388:
389: }
390: // If object does not offer icon, obtain it from the CLSID
391: if (NULL == lpPS->hMetaPictOD)
392: {
393: lpPS->hMetaPictOD = GetIconOfClass(
394: ghInst,
395: &lpPS->clsidOD,
396: NULL,
397: TRUE // Use the short user type name (auxusertype3)
398: );
399:
400:
401: }
402: }
403:
404: // Does object offer CF_LINKSRCDESCRIPTOR?
405: if (lpPS->hLinkSrcDesc = OleStdGetData(
406: lpOPS->lpSrcDataObj,
407: cfLinkSrcDescriptor,
408: NULL,
409: DVASPECT_CONTENT,
410: &medium))
411: {
412: // Get FullUserTypeName, SourceOfCopy and CLSID
413: lpLSD = GlobalLock(lpPS->hLinkSrcDesc);
414: if (lpLSD->dwFullUserTypeName)
415: lpPS->szFullUserTypeNameLSD = (LPSTR)lpLSD+lpLSD->dwFullUserTypeName;
416: else lpPS->szFullUserTypeNameLSD = lpPS->szUnknownType;
417:
418: if (lpLSD->dwSrcOfCopy)
419: lpPS->szSourceOfDataLSD = (LPSTR)lpLSD+lpLSD->dwSrcOfCopy;
420: else lpPS->szSourceOfDataLSD = lpPS->szUnknownSource;
421:
422: lpPS->clsidLSD = lpLSD->clsid;
423:
424: // Does source specify DVASPECT_ICON?
425: if (lpOD->dwDrawAspect & DVASPECT_ICON)
426: lpPS->fSrcAspectIconLSD = TRUE;
427: else lpPS->fSrcAspectIconLSD = FALSE;
428:
429: // Does source specify OLEMISC_ONLYICONIC?
430: if (lpLSD->dwStatus & OLEMISC_ONLYICONIC)
431: lpPS->fSrcOnlyIconicLSD = TRUE;
432: else lpPS->fSrcOnlyIconicLSD = FALSE;
433:
434: // Retrieve an icon from the object
435: if (lpPS->fSrcAspectIconLSD)
436: {
437: lpPS->hMetaPictLSD = OleStdGetData(
438: lpOPS->lpSrcDataObj,
439: CF_METAFILEPICT,
440: NULL,
441: DVASPECT_ICON,
442: &medium
443: );
444:
445: }
446: // If object does not offer icon, obtain it from the CLSID
447: if (NULL == lpPS->hMetaPictLSD)
448: {
449: char szLabel[OLEUI_CCHLABELMAX];
450: HWND hIconWnd;
451: RECT IconRect;
452: int nWidth;
453: LPSTR lpszLabel;
454:
455: hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY);
456:
457: GetClientRect(hIconWnd, &IconRect);
458:
459: nWidth = (IconRect.right * 3) / 2; // width is 1.5 times width of iconbox
460:
461: lstrcpyn(szLabel, lpPS->szSourceOfDataLSD, sizeof(szLabel));
462: szLabel[sizeof(szLabel)-1] = '\0';
463:
464: lpszLabel = ChopText(hIconWnd, nWidth, (LPSTR)szLabel);
465:
466: lpPS->hMetaPictLSD = GetIconOfClass(
467: ghInst,
468: &lpPS->clsidLSD,
469: lpszLabel, // use chopped source string as label
470: FALSE // not applicable
471: );
472: }
473: }
474: else if (lpPS->hObjDesc) // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR
475: {
476: // Copy the values of OBJECTDESCRIPTOR
477: lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD;
478: lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD;
479: lpPS->clsidLSD = lpPS->clsidOD;
480: lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD;
481: lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD;
482:
483: // Don't copy the hMetaPict; instead get a separate copy
484: if (lpPS->fSrcAspectIconLSD)
485: {
486: lpPS->hMetaPictLSD = OleStdGetData(
487: lpOPS->lpSrcDataObj,
488: CF_METAFILEPICT,
489: NULL,
490: DVASPECT_ICON,
491: &medium
492: );
493: }
494: if (NULL == lpPS->hMetaPictLSD)
495: {
496: char szLabel[OLEUI_CCHLABELMAX];
497: HWND hIconWnd;
498: RECT IconRect;
499: int nWidth;
500: LPSTR lpszLabel;
501:
502: hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY);
503:
504: GetClientRect(hIconWnd, &IconRect);
505:
506: nWidth = (IconRect.right * 3) / 2; // width is 1.5 times width of iconbox
507:
508: lstrcpyn(szLabel, lpPS->szSourceOfDataLSD, sizeof(szLabel));
509: szLabel[sizeof(szLabel)-1] = '\0';
510:
511: lpszLabel = ChopText(hIconWnd, nWidth, (LPSTR)szLabel);
512:
513: lpPS->hMetaPictLSD = GetIconOfClass(
514: ghInst,
515: &lpPS->clsidLSD,
516: lpszLabel, // Use chopped source string as label
517: FALSE // Not applicable
518: );
519: }
520: }
521:
522: // Not an OLE object
523: if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL)
524: {
525: lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD = lpPS->szUnknownType;
526: lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD = lpPS->szUnknownSource;
527: lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL;
528: }
529:
530: // Allocate scratch memory to construct item names in the paste and pastelink listboxes
531: lpPS->hBuff = AllocateScratchMem(lpPS);
532: if (lpPS->hBuff == NULL)
533: {
534: PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
535: return FALSE;
536: }
537:
538: // Select the Paste Link Button if specified. Otherwise select
539: // Paste Button by default
540: if (lpPS->dwFlags & PSF_SELECTPASTELINK)
541: lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK;
542: else
543: lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE;
544:
545: // Mark which PasteEntry formats are available from source data object
546: OleStdMarkPasteEntryList(
547: lpOPS->lpSrcDataObj,lpOPS->arrPasteEntries,lpOPS->cPasteEntries);
548:
549: // Check if items are available to be pasted
550: fPasteAvailable = FFillPasteList(hDlg, lpPS);
551: if (!fPasteAvailable)
552: {
553: lpPS->dwFlags &= ~PSF_SELECTPASTE;
554: EnableWindow(GetDlgItem(hDlg, ID_PS_PASTE), FALSE);
555: }
556:
557: // Check if items are available to be paste-linked
558: fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS);
559: if (!fPasteLinkAvailable)
560: {
561: lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
562: EnableWindow(GetDlgItem(hDlg, ID_PS_PASTELINK), FALSE);
563: }
564:
565: // If one of Paste or PasteLink is disabled, select the other one regardless of what
566: // the input flags say
567: if (fPasteAvailable && !fPasteLinkAvailable)
568: lpPS->dwFlags |= PSF_SELECTPASTE;
569: if (fPasteLinkAvailable && !fPasteAvailable)
570: lpPS->dwFlags |= PSF_SELECTPASTELINK;
571:
572: if (lpPS->dwFlags & PSF_SELECTPASTE)
573: {
574: // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it.
575: lpPS->dwFlags &= ~PSF_SELECTPASTE;
576: CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTE);
577: FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
578: }
579: else if (lpPS->dwFlags & PSF_SELECTPASTELINK)
580: {
581: // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it.
582: lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
583: CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTELINK);
584: FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
585: }
586: else // Items are not available to be be Pasted or Paste-Linked
587: {
588: // Enable or disable DisplayAsIcon and set the result text and image
589: EnableDisplayAsIcon(hDlg, lpPS);
590: SetPasteSpecialHelpResults(hDlg, lpPS);
591: }
592:
593: // Set property to handle clipboard change notifications
594: SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
595: SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg));
596:
597: /*
598: * PERFORM OTHER INITIALIZATION HERE.
599: */
600:
601: // Call the hook with lCustData in lParam
602: UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData);
603: return TRUE;
604: }
605:
606: /*
607: * FTogglePasteType
608: *
609: * Purpose:
610: * Toggles between Paste and Paste Link. The Paste list and PasteLink
611: * list are always invisible. The Display List is filled from either
612: * the Paste list or the PasteLink list depending on which Paste radio
613: * button is selected.
614: *
615: * Parameters:
616: * hDlg HWND of the dialog
617: * lpPS Paste Special Dialog Structure
618: * dwOption Paste or PasteSpecial option
619: *
620: * Return Value:
621: * BOOL Returns TRUE if the option has already been selected.
622: * Otherwise the option is selected and FALSE is returned
623: */
624:
625: BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption)
626: {
627: DWORD dwTemp;
628: HWND hList, hListDisplay;
629: DWORD dwData;
630: int i, nItems;
631: LPSTR lpsz;
632:
633: // Skip all this if the button is already selected
634: if (lpPS->dwFlags & dwOption)
635: return TRUE;
636:
637: dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK;
638: lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption;
639:
640: // Hide IconDisplay. This prevents flashing if the icon display is changed
641: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
642:
643: hListDisplay = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
644:
645: // If Paste was selected
646: if (lpPS->dwFlags & PSF_SELECTPASTE)
647: {
648: // Set the Source of the object in the clipboard
649: SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataOD);
650:
651: // If an icon is available
652: if (lpPS->hMetaPictOD)
653: // Set the icon display
654: SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET,
655: (WPARAM)lpPS->hMetaPictOD, 0L);
656:
657:
658: hList = GetDlgItem(hDlg, ID_PS_PASTELIST);
659: // We are switching from PasteLink to Paste. Remember current selection
660: // in PasteLink list so it can be restored.
661: lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
662: if (lpPS->nPasteLinkListCurSel == LB_ERR)
663: lpPS->nPasteLinkListCurSel = 0;
664: // Remember if user selected Paste or PasteLink
665: lpPS->fLink = FALSE;
666: }
667: else // If PasteLink was selected
668: {
669: // Set the Source of the object in the clipboard
670: SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataLSD);
671:
672: // If an icon is available
673: if (lpPS->hMetaPictLSD)
674: // Set the icon display
675: SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET,
676: (WPARAM)lpPS->hMetaPictLSD, 0L);
677:
678:
679: hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST);
680: // We are switching from Paste to PasteLink. Remember current selection
681: // in Paste list so it can be restored.
682: lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
683: if (lpPS->nPasteListCurSel == LB_ERR)
684: lpPS->nPasteListCurSel = 0;
685: // Remember if user selected Paste or PasteLink
686: lpPS->fLink = TRUE;
687: }
688:
689: // Turn drawing off while the Display List is being filled
690: SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L);
691:
692: // Move data to Display list box
693: SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L);
694: nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
695: lpsz = (LPSTR)GlobalLock(lpPS->hBuff);
696: for (i = 0; i < nItems; i++)
697: {
698: SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz);
699: dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
700: SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz);
701: SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData);
702: }
703: GlobalUnlock(lpPS->hBuff);
704:
705: // Restore the selection in the Display List from user's last selection
706: if (lpPS->dwFlags & PSF_SELECTPASTE)
707: SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L);
708: else
709: SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L);
710:
711: // Paint Display List
712: SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L);
713: InvalidateRect(hListDisplay, NULL, TRUE);
714: UpdateWindow(hListDisplay);
715:
716: // Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to
717: // the current selection
718: ChangeListSelection(hDlg, lpPS, hListDisplay);
719:
720: return FALSE;
721: }
722:
723:
724: /*
725: * ChangeListSelection
726: *
727: * Purpose:
728: * When the user changes the selection in the list, DisplayAsIcon is enabled or disabled,
729: * Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding
730: * to the current format selection is saved.
731: *
732: * Parameters:
733: * hDlg HWND of the dialog
734: * lpPS Paste Special Dialog Structure
735: * hList HWND of the List
736: *
737: * Return Value:
738: * No return value
739: */
740:
741: void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList)
742: {
743: LPPASTELISTITEMDATA lpItemData;
744: int nCurSel;
745:
746: EnableDisplayAsIcon(hDlg, lpPS);
747: SetPasteSpecialHelpResults(hDlg, lpPS);
748:
749: // Remember index of arrPasteEntries[] corresponding to the current selection
750: nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
751: if (nCurSel == LB_ERR) return;
752: lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA,
753: (WPARAM)nCurSel, 0L);
754: if ((LRESULT)lpItemData == LB_ERR) return;
755: lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex;
756: }
757:
758: /*
759: * EnableDisplayAsIcon
760: *
761: * Purpose:
762: * Enable or disable the DisplayAsIcon button depending on whether
763: * the current selection can be displayed as an icon or not. The following table describes
764: * the state of DisplayAsIcon. The calling application is termed CONTAINER, the source
765: * of data on the clipboard is termed SOURCE.
766: * Y = Yes; N = No; Blank = State does not matter;
767: * =====================================================================
768: * SOURCE SOURCE CONTAINER DisplayAsIcon
769: * specifies specifies specifies Initial State
770: * DVASPECT_ICON OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON
771: *
772: * N Unchecked&Disabled
773: * Y Y Checked&Disabled
774: * Y N Y Checked&Enabled
775: * N N Y Unchecked&Enabled
776: * =====================================================================
777: *
778: * Parameters:
779: * hDlg HWND of the dialog
780: * lpPS Paste Special Dialog Structure
781: *
782: * Return Value:
783: * No return value
784: */
785:
786: void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
787: {
788: int nIndex;
789: BOOL fCntrEnableIcon;
790: BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD;
791: BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD;
792: HWND hList;
793: LPPASTELISTITEMDATA lpItemData;
794: HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD;
795:
796: hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
797:
798: // Get data corresponding to the current selection in the listbox
799: nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0);
800: if (nIndex != LB_ERR)
801: {
802: lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L);
803: if ((LRESULT)lpItemData != LB_ERR)
804: fCntrEnableIcon = lpItemData->fCntrEnableIcon;
805: else fCntrEnableIcon = FALSE;
806: }
807: else fCntrEnableIcon = FALSE;
808:
809: // If there is an icon available
810: if (hMetaPict != NULL)
811: {
812: if (!fCntrEnableIcon) // Does CONTAINER specify OLEUIPASTE_ENABLEICON?
813: {
814: // Uncheck & Disable DisplayAsIcon
815: lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
816: CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
817: EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
818:
819: // Hide IconDisplay and ChangeIcon button
820: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
821: StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
822: }
823: else if (fSrcOnlyIconic) // Does SOURCE specify OLEMISC_ONLYICONIC?
824: {
825: // Check & Disable DisplayAsIcon
826: lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
827: CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE);
828: EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
829:
830: // Show IconDisplay and ChangeIcon button
831: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL);
832: StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL);
833: }
834: else if (fSrcAspectIcon) // Does SOURCE specify DVASPECT_ICON?
835: {
836: // Check & Enable DisplayAsIcon
837: lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
838: CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE);
839: EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE);
840:
841: // Show IconDisplay and ChangeIcon button
842: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL);
843: StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL);
844: }
845: else
846: {
847: //Uncheck and Enable DisplayAsIcon
848: lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
849: CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
850: EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE);
851:
852: // Hide IconDisplay and ChangeIcon button
853: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
854: StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
855:
856: }
857: }
858: else // No icon available
859: {
860: // Unchecked & Disabled
861: lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
862: CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
863: EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
864:
865: // Hide IconDisplay and ChangeIcon button
866: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
867: StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
868: }
869: }
870:
871: /*
872: * ToggleDisplayAsIcon
873: *
874: * Purpose:
875: * Toggles the DisplayAsIcon button. Hides or shows the Icon Display and
876: * the ChangeIcon button and changes the help result text and bitmap.
877: *
878: * Parameters:
879: * hDlg HWND of the dialog
880: * lpPS Paste Special Dialog Structure
881: *
882: * Return Value:
883: * None
884: *
885: */
886:
887: void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
888: {
889: BOOL fCheck;
890: int i;
891:
892: fCheck = IsDlgButtonChecked(hDlg, ID_PS_DISPLAYASICON);
893:
894: if (fCheck)
895: lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
896: else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
897:
898: // Set the help result text and bitmap
899: SetPasteSpecialHelpResults(hDlg, lpPS);
900:
901: // Show or hide the Icon Display and ChangeIcon button depending
902: // on the check state
903: i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
904: StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, i);
905: StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, i);
906: }
907:
908: /*
909: * ChangeIcon
910: *
911: * Purpose:
912: * Brings up the ChangeIcon dialog which allows the user to change
913: * the icon and label.
914: *
915: * Parameters:
916: * hDlg HWND of the dialog
917: * lpPS Paste Special Dialog Structure
918: *
919: * Return Value:
920: * None
921: *
922: */
923:
924: void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS)
925: {
926: OLEUICHANGEICON ci;
927: UINT uRet;
928: CLSID clsid = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD;
929:
930: //Initialize the structure
931: _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
932:
933: ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
934: ci.cbStruct = sizeof(ci);
935: ci.hWndOwner = hDlg;
936: ci.clsid = clsid;
937: ci.dwFlags = CIF_SELECTCURRENT;
938:
939: // Only show help in the ChangeIcon dialog if we're showing it in this dialog.
940: if (lpPS->dwFlags & PSF_SHOWHELP)
941: ci.dwFlags = CIF_SHOWHELP;
942:
943: // Let the hook in to customize Change Icon if desired.
944: uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LONG)(LPSTR)&ci);
945:
946: if (0 == uRet)
947: uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
948:
949: // Update the display if necessary.
950: if (0!=uRet)
951: {
952: /*
953: * OleUIChangeIcon will have already freed our
954: * current hMetaPict that we passed in when OK is
955: * pressed in that dialog. So we use 0L as lParam
956: * here so the IconBox doesn't try to free the
957: * metafilepict again.
958: */
959: SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)ci.hMetaPict, 0L);
960: // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate
961: // icons - changing one does not change the other.
962: if (lpPS->fLink)
963: lpPS->hMetaPictLSD = ci.hMetaPict;
964: else lpPS->hMetaPictOD = ci.hMetaPict;
965: }
966: }
967:
968: /*
969: *SetPasteSpecialHelpResults
970: *
971: * Purpose:
972: * Sets the help result text and bitmap according to the current
973: * list selection. The following state table indicates which ResultText
974: * and ResultImage are selected. If %s in the lpstrFormatName is present,
975: * it is assumed that an object is being pasted/paste-linked, otherwise it
976: * is assumed that data is being pasted/paste-linked.
977: * Y = Yes; N = No; Blank = State does not matter;
978: * The numbers in the the ResultText and ResultImage columns refer to the table
979: * entries that follow.
980: * =====================================================================
981: * Paste/ lpstrFormatName in DisplayAsIcon Result Result
982: * PasteLink arrPasteEntry[]contains %s checked Text Image
983: * (Is Object == Y, Is Data == N)
984: * Paste N 1 1
985: * Paste Y N 2 2
986: * Paste Y Y 3 3
987: * PasteLink N 4 4
988: * PasteLink Y N 5 4
989: * PasteLink Y Y 6 5
990: * =====================================================================
991: * Result Text:
992: *
993: * 1. "Inserts the contents of the Clipboard into your document as <native type name,
994: * and optionally an additional help sentence>"
995: * 2. "Inserts the contents of the Clipboard into your document so that you may
996: * activate it using <object app name>"
997: * 3. "Inserts the contents of the Clipboard into your document so that you may
998: * activate it using <object app name>. It will be displayed as an icon."
999: * 4. "Inserts the contents of the Clipboard into your document as <native type name>.
1000: * Paste Link creates a link to the source file so that changes to the source file
1001: * will be reflected in your document."
1002: * 5. "Inserts a picture of the Clipboard contents into your document. Paste Link
1003: * creates a link to the source file so that changes to the source file will be
1004: * reflected in your document."
1005: * 6. "Inserts an icon into your document which represents the Clipboard contents.
1006: * Paste Link creates a link to the source file so that changes to the source file
1007: * will be reflected in your document."
1008: * =====================================================================
1009: * Result Image:
1010: *
1011: * 1. Clipboard Image
1012: * 2. Paste image, non-iconic.
1013: * 3. Paste image, iconic.
1014: * 4. Paste Link image, non-iconic
1015: * 5. Paste Link image, iconic
1016: * ====================================================================
1017: *
1018: * Parameters:
1019: * hDlg HWND of the dialog
1020: * lpPS Paste Special Dialog Structure
1021: *
1022: * Return Value:
1023: * No return value
1024: */
1025: void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS)
1026: {
1027: LPSTR psz1, psz2, psz3, psz4;
1028: UINT i, iString, iImage, cch;
1029: int nPasteEntriesIndex;
1030: BOOL fDisplayAsIcon;
1031: BOOL fIsObject;
1032: HWND hList;
1033: LPPASTELISTITEMDATA lpItemData;
1034: LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
1035: LPSTR szFullUserTypeName = (lpPS->fLink) ? lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD;
1036: LPSTR szInsert;
1037:
1038: hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
1039:
1040: i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
1041: if (i != LB_ERR)
1042: {
1043: lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L);
1044: if ((LRESULT)lpItemData == LB_ERR) return;
1045: nPasteEntriesIndex = lpItemData->nPasteEntriesIndex;
1046: // Check if there is a '%s' in the lpstrFormatName, then an object is being
1047: // pasted/pastelinked. Otherwise Data is being pasted-pastelinked.
1048: fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
1049: lpPS);
1050: }
1051: else return;
1052:
1053: // Is DisplayAsIcon checked?
1054: fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON));
1055:
1056: szInsert = szFullUserTypeName;
1057:
1058: if (lpPS->dwFlags & PSF_SELECTPASTE) // If user selected Paste
1059: {
1060: if (fIsObject)
1061: {
1062: iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT;
1063: iImage = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
1064: szInsert = lpPS->szAppName;
1065: }
1066: else
1067: {
1068: iString = IDS_PSPASTEDATA;
1069: iImage = RESULTIMAGE_PASTE;
1070: }
1071: }
1072: else if (lpPS->dwFlags & PSF_SELECTPASTELINK) // User selected PasteLink
1073: {
1074: if (fIsObject)
1075: {
1076: iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT;
1077: iImage = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
1078: }
1079: else
1080: {
1081: iString = IDS_PSPASTELINKDATA;
1082: iImage = RESULTIMAGE_LINK;
1083: }
1084:
1085: }
1086: else // Should never occur.
1087: {
1088: iString = IDS_PSNONOLE;
1089: iImage = RESULTIMAGE_PASTE;
1090: }
1091:
1092: // hBuff contains enough space for the 4 buffers required to build up the help
1093: // result text.
1094: cch = (UINT)GlobalSize(lpPS->hBuff)/4;
1095:
1096: psz1=(LPSTR)GlobalLock(lpPS->hBuff);
1097: psz2=psz1+cch;
1098: psz3=psz2+cch;
1099: psz4=psz3+cch;
1100:
1101: // Default is an empty string.
1102: *psz1=0;
1103:
1104: if (0!=LoadString(ghInst, iString, psz1, cch))
1105: {
1106: // Insert the FullUserTypeName of the source object into the partial result text
1107: // specified by the container.
1108: wsprintf(psz3, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText,
1109: (LPSTR)szInsert);
1110: // Insert the above partial result text into the standard result text.
1111: wsprintf(psz4, psz1, (LPSTR)psz3);
1112: psz1=psz4;
1113: }
1114:
1115: // If LoadString failed, we simply clear out the results (*psz1=0 above)
1116: SetDlgItemText(hDlg, ID_PS_RESULTTEXT, psz1);
1117:
1118: // Change the result bitmap
1119: SendDlgItemMessage(hDlg, ID_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
1120:
1121: GlobalUnlock(lpPS->hBuff);
1122: }
1123:
1124: /*
1125: * FAddPasteListItem
1126: *
1127: * Purpose:
1128: * Adds an item to the list box
1129: *
1130: * Parameters:
1131: * hList HWND List into which item is to be added
1132: * fInsertFirst BOOL Insert in the beginning of the list?
1133: * nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to
1134: * lpPS Paste Special Dialog Structure
1135: * pIMalloc LPMALLOC Memory Allocator
1136: * lpszBuf LPSTR Scratch buffer to build up string for list entry
1137: *
1138: * Return Value:
1139: * BOOL TRUE if sucessful.
1140: * FALSE if unsucessful.
1141: */
1142: BOOL FAddPasteListItem(
1143: HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex, LPPASTESPECIAL lpPS,
1144: LPMALLOC pIMalloc, LPSTR lpszBuf)
1145: {
1146: LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
1147: LPPASTELISTITEMDATA lpItemData;
1148: int nIndex;
1149: LPSTR szFullUserTypeName = (lpPS->fLink) ?
1150: lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD;
1151:
1152: // Allocate memory for each list box item
1153: lpItemData = (LPPASTELISTITEMDATA)pIMalloc->lpVtbl->Alloc(
1154: pIMalloc, (DWORD)sizeof(PASTELISTITEMDATA));
1155: if (NULL == lpItemData)
1156: return FALSE;
1157:
1158: // Fill data associated with each list box item
1159: lpItemData->nPasteEntriesIndex = nPasteEntriesIndex;
1160: lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags &
1161: OLEUIPASTE_ENABLEICON) ? TRUE : FALSE);
1162:
1163: // Build list box entry string, insert the string and add the data the corresponds to it
1164: wsprintf(
1165: (LPSTR)lpszBuf,
1166: lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
1167: (LPSTR)szFullUserTypeName
1168: );
1169: nIndex = (int)SendMessage(
1170: hList,
1171: (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING),
1172: 0,
1173: (LPARAM)(LPSTR)lpszBuf
1174: );
1175: SendMessage(
1176: hList,
1177: LB_SETITEMDATA,
1178: nIndex,
1179: (LPARAM)(LPPASTELISTITEMDATA)lpItemData
1180: );
1181: return TRUE;
1182: }
1183:
1184:
1185: /*
1186: * FFillPasteList
1187: *
1188: * Purpose:
1189: * Fills the invisible paste list with the formats offered by the clipboard object and
1190: * asked for by the container.
1191: *
1192: * Parameters:
1193: * hDlg HWND of the dialog
1194: * lpPS Paste Special Dialog Structure
1195: *
1196: * Return Value:
1197: * BOOL TRUE if sucessful and if formats could be found.
1198: * FALSE if unsucessful or if no formats could be found.
1199: */
1200: BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS)
1201: {
1202: LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
1203: LPMALLOC pIMalloc = NULL;
1204: LPSTR lpszBuf = (LPSTR)GlobalLock(lpPS->hBuff);
1205: HWND hList;
1206: int i;
1207: int nItems = 0;
1208: int nDefFormat = -1;
1209: BOOL fTryObjFmt = FALSE;
1210: BOOL fInsertFirst;
1211: HRESULT hrErr;
1212:
1213: hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
1214: if (hrErr != NOERROR)
1215: goto error;
1216:
1217: hList = GetDlgItem(hDlg, ID_PS_PASTELIST);
1218:
1219: // Loop over the target's priority list of formats
1220: for (i = 0; i < lpOPS->cPasteEntries; i++)
1221: {
1222: if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY &&
1223: !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE))
1224: continue;
1225:
1226: fInsertFirst = FALSE;
1227:
1228: if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName
1229: || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbeddedObject
1230: || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbedSource) {
1231: if (! fTryObjFmt) {
1232: fTryObjFmt = TRUE; // only use 1st object format
1233: fInsertFirst = TRUE; // OLE obj format should always be 1st
1234: } else {
1235: continue; // already added an object format to list
1236: }
1237: }
1238:
1239: // add to list if entry is marked TRUE
1240: if (lpOPS->arrPasteEntries[i].dwScratchSpace) {
1241: if (nDefFormat < 0)
1242: nDefFormat = (fInsertFirst ? 0 : nItems);
1243: else if (fInsertFirst)
1244: nDefFormat++; // adjust for obj fmt inserted 1st in list
1245:
1246: if (!FAddPasteListItem(hList,fInsertFirst,i,lpPS,pIMalloc,lpszBuf))
1247: goto error;
1248: nItems++;
1249: }
1250: }
1251:
1252: // initialize selection to first format matched in list
1253: if (nDefFormat >= 0)
1254: lpPS->nPasteListCurSel = nDefFormat;
1255:
1256: // Clean up
1257: if (pIMalloc)
1258: OleStdRelease((LPUNKNOWN)pIMalloc);
1259: if (lpszBuf)
1260: GlobalUnlock(lpPS->hBuff);
1261:
1262: // If no items have been added to the list box (none of the formats
1263: // offered by the source matched those acceptable to the container),
1264: // return FALSE
1265: if (nItems > 0)
1266: return TRUE;
1267: else
1268: return FALSE;
1269:
1270: error:
1271: if (pIMalloc)
1272: OleStdRelease((LPUNKNOWN)pIMalloc);
1273: if (lpszBuf)
1274: GlobalUnlock(lpPS->hBuff);
1275: FreeListData(hList);
1276:
1277: return FALSE;
1278: }
1279:
1280:
1281: /*
1282: * FFillPasteLinkList
1283: *
1284: * Purpose:
1285: * Fills the invisible paste link list with the formats offered by the clipboard object and
1286: * asked for by the container.
1287: *
1288: * Parameters:
1289: * hDlg HWND of the dialog
1290: * lpPS Paste Special Dialog Structure
1291: *
1292: * Return Value:
1293: * BOOL TRUE if sucessful and if formats could be found.
1294: * FALSE if unsucessful or if no formats could be found.
1295: */
1296: BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS)
1297: {
1298: LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
1299: LPDATAOBJECT lpSrcDataObj = lpOPS->lpSrcDataObj;
1300: LPENUMFORMATETC lpEnumFmtEtc = NULL;
1301: LPMALLOC pIMalloc = NULL;
1302: LPSTR lpszBuf = (LPSTR)GlobalLock(lpPS->hBuff);
1303: OLEUIPASTEFLAG pasteFlag;
1304: UINT arrLinkTypesSupported[PS_MAXLINKTYPES]; // Array of flags that
1305: // indicate which link types
1306: // are supported by source.
1307: FORMATETC fmtetc;
1308: int i, j;
1309: int nItems = 0;
1310: BOOL fLinkTypeSupported = FALSE;
1311: HWND hList;
1312: int nDefFormat = -1;
1313: BOOL fTryObjFmt = FALSE;
1314: BOOL fInsertFirst;
1315: HRESULT hrErr;
1316:
1317: hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
1318: if (hrErr != NOERROR)
1319: goto error;
1320:
1321: // Remember which link type formats are offered by lpSrcDataObj.
1322: _fmemset(&fmtetc, 0, sizeof(FORMATETC));
1323: for (i = 0; i < lpOPS->cLinkTypes; i++)
1324: {
1325: if (lpOPS->arrLinkTypes[i] = cfLinkSource) {
1326: OLEDBG_BEGIN2("OleQueryLinkFromData called\r\n")
1327: hrErr = OleQueryLinkFromData(lpSrcDataObj);
1328: OLEDBG_END2
1329: if(NOERROR == hrErr)
1330: {
1331: arrLinkTypesSupported[i] = 1;
1332: fLinkTypeSupported = TRUE;
1333: }
1334: else arrLinkTypesSupported[i] = 0;
1335: }
1336: else {
1337: fmtetc.cfFormat = lpOPS->arrLinkTypes[i];
1338: fmtetc.dwAspect = DVASPECT_CONTENT;
1339: fmtetc.tymed = 0xFFFFFFFF; // All tymed values
1340: fmtetc.lindex = -1;
1341: OLEDBG_BEGIN2("IDataObject::QueryGetData called\r\n")
1342: hrErr = lpSrcDataObj->lpVtbl->QueryGetData(lpSrcDataObj,&fmtetc);
1343: OLEDBG_END2
1344: if(NOERROR == hrErr)
1345: {
1346: arrLinkTypesSupported[i] = 1;
1347: fLinkTypeSupported = TRUE;
1348: }
1349: else arrLinkTypesSupported[i] = 0;
1350: }
1351: }
1352: // No link types are offered by lpSrcDataObj
1353: if (! fLinkTypeSupported) {
1354: nItems = 0;
1355: goto cleanup;
1356: }
1357:
1358: hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST);
1359:
1360: // Enumerate the formats acceptable to container
1361: for (i = 0; i < lpOPS->cPasteEntries; i++)
1362: {
1363: fLinkTypeSupported = FALSE;
1364:
1365: // If container will accept any link type offered by source object
1366: if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE)
1367: fLinkTypeSupported = TRUE;
1368: else
1369: {
1370: // Check if any of the link types offered by the source
1371: // object are acceptable to the container
1372: // This code depends on the LINKTYPE enum values being powers of 2
1373: for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0;
1374: j < lpOPS->cLinkTypes;
1375: pasteFlag*=2, j++)
1376: {
1377: if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) &&
1378: arrLinkTypesSupported[j])
1379: {
1380: fLinkTypeSupported = TRUE;
1381: break;
1382: }
1383: }
1384: }
1385:
1386: fInsertFirst = FALSE;
1387:
1388: if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName
1389: || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfLinkSource) {
1390: if (! fTryObjFmt) {
1391: fTryObjFmt = TRUE; // only use 1st object format
1392: fInsertFirst = TRUE; // OLE obj format should always be 1st
1393: } else {
1394: continue; // already added an object format to list
1395: }
1396: }
1397:
1398: // add to list if entry is marked TRUE
1399: if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace) {
1400: if (nDefFormat < 0)
1401: nDefFormat = (fInsertFirst ? 0 : nItems);
1402: else if (fInsertFirst)
1403: nDefFormat++; // adjust for obj fmt inserted 1st in list
1404:
1405: if (!FAddPasteListItem(hList,fInsertFirst,i,lpPS,pIMalloc,lpszBuf))
1406: goto error;
1407: nItems++;
1408: }
1409: } // end FOR
1410:
1411: nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L);
1412:
1413: // initialize selection to first format matched in list
1414: if (nDefFormat >= 0)
1415: lpPS->nPasteLinkListCurSel = nDefFormat;
1416:
1417: cleanup:
1418: // Clean up
1419: if (pIMalloc)
1420: OleStdRelease((LPUNKNOWN)pIMalloc);
1421: if (lpszBuf)
1422: GlobalUnlock(lpPS->hBuff);
1423:
1424: // If no items have been added to the list box (none of the formats
1425: // offered by the source matched those acceptable to the destination),
1426: // return FALSE
1427: if (nItems > 0)
1428: return TRUE;
1429: else
1430: return FALSE;
1431:
1432: error:
1433: if (pIMalloc)
1434: OleStdRelease((LPUNKNOWN)pIMalloc);
1435: if (lpszBuf)
1436: GlobalUnlock(lpPS->hBuff);
1437: FreeListData(hList);
1438:
1439: return FALSE;
1440: }
1441:
1442:
1443: /*
1444: * FreeListData
1445: *
1446: * Purpose:
1447: * Free the local memory associated with each list box item
1448: *
1449: * Parameters:
1450: * hList HWND of the list
1451: *
1452: * Return Value:
1453: * None
1454: */
1455: void FreeListData(HWND hList)
1456: {
1457: int nItems, i;
1458: LPPASTELISTITEMDATA lpItemData;
1459: LPMALLOC pIMalloc;
1460: HRESULT hrErr;
1461:
1462: hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
1463: if (hrErr != NOERROR)
1464: return;
1465:
1466: nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
1467: for (i = 0; i < nItems; i++)
1468: {
1469: lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
1470: if ((LRESULT)lpItemData != LB_ERR)
1471: pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpItemData);
1472: }
1473: OleStdRelease((LPUNKNOWN)pIMalloc);
1474: }
1475:
1476: /*
1477: * FHasPercentS
1478: *
1479: * Purpose:
1480: * Determines if string contains %s.
1481: *
1482: * Parameters:
1483: * lpsz LPCSTR string in which occurence of '%s' is looked for
1484: *
1485: * Return Value:
1486: * BOOL TRUE if %s is found, else FALSE.
1487: */
1488:
1489: BOOL FHasPercentS(LPCSTR lpsz, LPPASTESPECIAL lpPS)
1490: {
1491: int n = 0;
1492: LPSTR lpszTmp;
1493:
1494: if (!lpsz) return FALSE;
1495: // Copy input string to buffer. This allows caller to pass a
1496: // code-based string. Code segments may be swapped out in low memory situations
1497: // and so code-based strings need to be copied before string elements can be accessed.
1498: lpszTmp = (LPSTR)GlobalLock(lpPS->hBuff);
1499: lstrcpy(lpszTmp, lpsz);
1500:
1501: while (*lpszTmp)
1502: {
1503: if (*lpszTmp == '%')
1504: {
1505: lpszTmp = AnsiNext(lpszTmp);
1506: if (*lpszTmp == 's') // If %s, return
1507: {
1508: GlobalUnlock(lpPS->hBuff);
1509: return TRUE;
1510: }
1511: else if (*lpszTmp == '%') // if %%, skip to next character
1512: lpszTmp = AnsiNext(lpszTmp);
1513: }
1514: else lpszTmp = AnsiNext(lpszTmp);
1515: }
1516:
1517: GlobalUnlock(lpPS->hBuff);
1518: return FALSE;
1519: }
1520:
1521: /*
1522: * AllocateScratchMem
1523: *
1524: * Purpose:
1525: * Allocates scratch memory for use by the PasteSpecial dialog. The memory is
1526: * is used as the buffer for building up strings using wsprintf. Strings are built up
1527: * using the buffer while inserting items into the Paste & PasteLink lists and while
1528: * setting the help result text. It must be big enough to handle the string that results after
1529: * replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[]
1530: * by the FullUserTypeName. It must also be big enough to build the dialog's result text
1531: * after %s substitutions by the FullUserTypeName or the ApplicationName.
1532: *
1533: * Parameters:
1534: * lpPS Paste Special Dialog Structure
1535: *
1536: * Return Value:
1537: * HGLOBAL Handle to allocated global memory
1538: */
1539:
1540: HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS)
1541: {
1542: LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
1543: int nLen, i;
1544: int nSubstitutedText = 0;
1545: int nAlloc = 0;
1546:
1547: // Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR
1548: // and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted
1549: // for %s in the result-text/list entries.
1550: if (lpPS->szFullUserTypeNameOD)
1551: nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD);
1552: if (lpPS->szFullUserTypeNameLSD)
1553: nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD));
1554: if (lpPS->szAppName)
1555: nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName));
1556:
1557: // Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries
1558: nLen = 0;
1559: for (i = 0; i < lpOPS->cPasteEntries; i++)
1560: {
1561: nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName));
1562: nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText));
1563: }
1564:
1565: // Get the maximum length of lpstrFormatNames and lpstrResultText after %s has
1566: // been substituted (At most one %s can appear in each string).
1567: // Add 1 to hold NULL terminator.
1568: nAlloc = nLen+nSubstitutedText+1;
1569:
1570: // Allocate scratch memory to be used to build strings
1571: // nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[]
1572: // after %s substitution.
1573: // We also need space to build up the help result text. 512 is the maximum length of the
1574: // standard dialog help text before substitutions. 512+nAlloc is the maximum length
1575: // after %s substition.
1576: // SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text
1577: return GlobalAlloc(GHND, (DWORD)4*(512+nAlloc));
1578: }
1579:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.