|
|
/*
* PASTESPL.CPP * * Implements the OleUIPasteSpecial function which invokes the complete * Paste Special dialog. * * Copyright (c)1992 Microsoft Corporation, All Rights Reserved */
#include "precomp.h"
#include "common.h"
#include "utility.h"
#include "resimage.h"
#include "iconbox.h"
#include <stdlib.h>
OLEDBGDATA
// Length of buffers to hold the strings 'Unknown Type', Unknown Source'
// and 'the application which created it'
// Extra long to allow room for localization.
#define PS_UNKNOWNSTRLEN 200
#define PS_UNKNOWNNAMELEN 256
// Property label used to store clipboard viewer chain information
#define NEXTCBVIEWER TEXT("NextCBViewer")
// Internally used structure
typedef struct tagPASTESPECIAL { // Keep this item first as the Standard* functions depend on it here.
LPOLEUIPASTESPECIAL lpOPS; //Original structure passed.
UINT nIDD; // IDD of dialog (used for help info)
/*
* What we store extra in this structure besides the original caller's * pointer are those fields that we need to modify during the life of * the dialog but that we don't want to change in the original structure * until the user presses OK. */
DWORD dwFlags; // Local copy of paste special flags
int nPasteListCurSel; // Save the selection the user made last
int nPasteLinkListCurSel; // in the paste and pastelink lists
int nSelectedIndex; // Index in arrPasteEntries[] corresponding to user selection
BOOL fLink; // Indicates if Paste or PasteLink was selected by user
HGLOBAL hBuff; // Scratch Buffer for building up strings
TCHAR szUnknownType[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Type' string
TCHAR szUnknownSource[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Source' string
TCHAR szAppName[OLEUI_CCHKEYMAX]; // Application name of Source. Used in the result text
// when Paste is selected. Obtained using clsidOD.
// Information obtained from OBJECTDESCRIPTOR. This information is accessed when the Paste
// radio button is selected.
CLSID clsidOD; // ClassID of source
SIZEL sizelOD; // sizel transfered in
// ObjectDescriptor
TCHAR szFullUserTypeNameOD[PS_UNKNOWNNAMELEN]; // Full User Type Name
TCHAR szSourceOfDataOD[PS_UNKNOWNNAMELEN]; // Source of Data
BOOL fSrcAspectIconOD; // Does Source specify DVASPECT_ICON?
BOOL fSrcOnlyIconicOD; // Does Source specify OLEMISC_ONLYICONIC?
HGLOBAL hMetaPictOD; // Metafile containing icon and icon title
HGLOBAL hObjDesc; // Handle to OBJECTDESCRIPTOR structure from which the
// above information is obtained
// Information obtained from LINKSRCDESCRIPTOR. This infomation is accessed when the PasteLink
// radio button is selected.
CLSID clsidLSD; // ClassID of source
SIZEL sizelLSD; // sizel transfered in
// LinkSrcDescriptor
TCHAR szFullUserTypeNameLSD[PS_UNKNOWNNAMELEN];// Full User Type Name
TCHAR szSourceOfDataLSD[PS_UNKNOWNNAMELEN]; // Source of Data
BOOL fSrcAspectIconLSD; // Does Source specify DVASPECT_ICON?
BOOL fSrcOnlyIconicLSD; // Does Source specify OLEMISC_ONLYICONIC?
HGLOBAL hMetaPictLSD; // Metafile containing icon and icon title
HGLOBAL hLinkSrcDesc; // Handle to LINKSRCDESCRIPTOR structure from which the
// above information is obtained
BOOL fClipboardChanged; // Has clipboard content changed
// if so bring down dlg after
// ChangeIcon dlg returns.
} PASTESPECIAL, *PPASTESPECIAL, FAR *LPPASTESPECIAL;
// Data corresponding to each list item. A pointer to this structure is attached to each
// Paste\PasteLink list box item using LB_SETITEMDATA
typedef struct tagPASTELISTITEMDATA { int nPasteEntriesIndex; // Index of arrPasteEntries[] corresponding to list item
BOOL fCntrEnableIcon; // Does calling application (called container here)
// specify OLEUIPASTE_ENABLEICON for this item?
} PASTELISTITEMDATA, *PPASTELISTITEMDATA, FAR *LPPASTELISTITEMDATA;
// Internal function prototypes
// PASTESPL.CPP
INT_PTR CALLBACK PasteSpecialDialogProc(HWND, UINT, WPARAM, LPARAM); BOOL FPasteSpecialInit(HWND hDlg, WPARAM, LPARAM); BOOL FTogglePasteType(HWND, LPPASTESPECIAL, DWORD); void ChangeListSelection(HWND, LPPASTESPECIAL, HWND); void EnableDisplayAsIcon(HWND, LPPASTESPECIAL); void ToggleDisplayAsIcon(HWND, LPPASTESPECIAL); void ChangeIcon(HWND, LPPASTESPECIAL); void SetPasteSpecialHelpResults(HWND, LPPASTESPECIAL); BOOL FAddPasteListItem(HWND, BOOL, int, LPPASTESPECIAL, LPTSTR, LPTSTR); BOOL FFillPasteList(HWND, LPPASTESPECIAL); BOOL FFillPasteLinkList(HWND, LPPASTESPECIAL); BOOL FHasPercentS(LPCTSTR, LPPASTESPECIAL); HGLOBAL AllocateScratchMem(LPPASTESPECIAL); void FreeListData(HWND); BOOL FPasteSpecialReInit(HWND hDlg, LPPASTESPECIAL lpPS);
/*
* OleUIPasteSpecial * * Purpose: * Invokes the standard OLE Paste Special dialog box which allows the user * to select the format of the clipboard object to be pasted or paste linked. * * Parameters: * lpPS LPOLEUIPasteSpecial pointing to the in-out structure * for this dialog. * * Return Value: * UINT One of the following codes or one of the standard error codes (OLEUI_ERR_*) * defined in OLEDLG.H, indicating success or error: * OLEUI_OK User selected OK * OLEUI_CANCEL User cancelled the dialog * OLEUI_IOERR_SRCDATAOBJECTINVALID lpSrcDataObject field of OLEUIPASTESPECIAL invalid * OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid * OLEUI_IOERR_ARRLINKTYPESINVALID arrLinkTypes field of OLEUIPASTESPECIAL invalid * OLEUI_PSERR_CLIPBOARDCHANGED Clipboard contents changed while dialog was up */ STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS) { UINT uRet; HGLOBAL hMemDlg=NULL;
uRet = UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL), &hMemDlg);
if (uRet != OLEUI_SUCCESS) return uRet;
// Validate PasteSpecial specific fields
if (NULL != lpPS->lpSrcDataObj && IsBadReadPtr(lpPS->lpSrcDataObj, sizeof(IDataObject))) { uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID; } if (NULL == lpPS->arrPasteEntries || IsBadReadPtr(lpPS->arrPasteEntries, lpPS->cPasteEntries * sizeof(OLEUIPASTEENTRY))) { uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID; } if (0 > lpPS->cLinkTypes || lpPS->cLinkTypes > PS_MAXLINKTYPES || IsBadReadPtr(lpPS->arrLinkTypes, lpPS->cLinkTypes * sizeof(UINT))) { uRet = OLEUI_IOERR_ARRLINKTYPESINVALID; }
if (0 != lpPS->cClsidExclude && IsBadReadPtr(lpPS->lpClsidExclude, lpPS->cClsidExclude * sizeof(CLSID))) { uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; }
// If IDataObject passed is NULL, collect it from the clipboard
if (NULL == lpPS->lpSrcDataObj) { if (OleGetClipboard(&lpPS->lpSrcDataObj) != NOERROR) uRet = OLEUI_PSERR_GETCLIPBOARDFAILED;
if (NULL == lpPS->lpSrcDataObj) uRet = OLEUI_PSERR_GETCLIPBOARDFAILED; }
if (uRet >= OLEUI_ERR_STANDARDMIN) { return uRet; }
UINT nIDD = bWin4 ? IDD_PASTESPECIAL4 : IDD_PASTESPECIAL;
//Now that we've validated everything, we can invoke the dialog.
uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS, hMemDlg, MAKEINTRESOURCE(nIDD));
return uRet; }
/*
* PasteSpecialDialogProc * * Purpose: * Implements the OLE Paste Special dialog as invoked through the * OleUIPasteSpecial function. * * Parameters: * Standard * * Return Value: * Standard */ INT_PTR CALLBACK PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) { // Declare Win16/Win32 compatible WM_COMMAND parameters.
COMMANDPARAMS(wID, wCode, hWndMsg);
// This will fail under WM_INITDIALOG, where we allocate it.
UINT fHook = FALSE; LPPASTESPECIAL lpPS = (LPPASTESPECIAL)LpvStandardEntry( hDlg, iMsg, wParam, lParam, &fHook); LPOLEUIPASTESPECIAL lpOPS = NULL; if (lpPS != NULL) lpOPS = lpPS->lpOPS;
//If the hook processed the message, we're done.
if (0!=fHook) return (INT_PTR)fHook;
// Process help message from Change Icon
if (iMsg == uMsgHelp) { // if lPS is NULL (in low memory situations, just ignore it.
if (lpPS != NULL) { PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam); } return FALSE; }
//Process the temination message
if (iMsg == uMsgEndDialog) { EndDialog(hDlg, wParam); return TRUE; }
switch (iMsg) { case WM_DESTROY: if (lpPS) { HWND hwndNextViewer;
// Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected
if (lpPS->fLink) OleUIMetafilePictIconFree(lpPS->hMetaPictOD); else OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
// Free data associated with each list box entry
FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELIST)); FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELINKLIST));
//Free any specific allocations before calling StandardCleanup
if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc); if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc); if (lpPS->hBuff) { GlobalFree(lpPS->hBuff); lpPS->hBuff = NULL; }
// Change the clipboard notification chain
hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); if (hwndNextViewer != HWND_BROADCAST) { SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); ChangeClipboardChain(hDlg, hwndNextViewer); } RemoveProp(hDlg, NEXTCBVIEWER);
StandardCleanup(lpPS, hDlg); } break; case WM_INITDIALOG: FPasteSpecialInit(hDlg, wParam, lParam); return FALSE;
case WM_DRAWCLIPBOARD: { HWND hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); HWND hDlg_ChgIcon;
if (hwndNextViewer == HWND_BROADCAST) break;
if (hwndNextViewer) { SendMessage(hwndNextViewer, iMsg, wParam, lParam); // Refresh next viewer in case it got modified
// by the SendMessage() (likely if multiple
// PasteSpecial dialogs are up simultaneously)
hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); }
if (!(lpPS->dwFlags & PSF_STAYONCLIPBOARDCHANGE)) { SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); ChangeClipboardChain(hDlg, hwndNextViewer);
/* OLE2NOTE: if the ChangeIcon dialog is currently up, then
** we need to defer bringing down PasteSpecial dialog ** until after ChangeIcon dialog returns. if the ** ChangeIcon dialog is NOT up, then we can bring down ** the PasteSpecial dialog immediately. */ if ((hDlg_ChgIcon=(HWND)GetProp(hDlg,PROP_HWND_CHGICONDLG))!=NULL) { // ChangeIcon dialog is UP
lpPS->fClipboardChanged = TRUE; } else { // ChangeIcon dialog is NOT up
// Free icon and icon title metafile
SendDlgItemMessage( hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L); SendMessage( hDlg, uMsgEndDialog, OLEUI_PSERR_CLIPBOARDCHANGED,0L); } } else { // skip refresh, ignoring clipboard change if PSF_NOREFRESHDATAOBJECT
if (lpPS->dwFlags & PSF_NOREFRESHDATAOBJECT) break;
// release current data object
if (lpOPS->lpSrcDataObj != NULL) { lpOPS->lpSrcDataObj->Release(); lpOPS->lpSrcDataObj = NULL; }
// obtain new one
if (OleGetClipboard(&lpOPS->lpSrcDataObj) != NOERROR) { SendMessage(hDlg, uMsgEndDialog, OLEUI_PSERR_GETCLIPBOARDFAILED, 0); break; }
// otherwise update the display to the new clipboard object
FPasteSpecialReInit(hDlg, lpPS); } } break;
case WM_CHANGECBCHAIN: { HWND hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); if ((HWND)wParam == hwndNextViewer) SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)lParam)); else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST) SendMessage(hwndNextViewer, iMsg, wParam, lParam); } break;
case WM_COMMAND: switch (wID) { case IDC_PS_PASTE: FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE); break;
case IDC_PS_PASTELINK: FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK); break;
case IDC_PS_DISPLAYLIST: switch (wCode) { case LBN_SELCHANGE: ChangeListSelection(hDlg, lpPS, hWndMsg); break; case LBN_DBLCLK: // Same as pressing OK
if (IsWindowEnabled(GetDlgItem(hDlg, IDOK))) SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); break; } break;
case IDC_PS_DISPLAYASICON: ToggleDisplayAsIcon(hDlg, lpPS); break;
case IDC_PS_CHANGEICON: ChangeIcon(hDlg, lpPS); if (lpPS->fClipboardChanged) { // Free icon and icon title metafile
SendDlgItemMessage( hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE,0,0L); SendMessage(hDlg, uMsgEndDialog, OLEUI_PSERR_CLIPBOARDCHANGED, 0L); } break;
case IDOK: { BOOL fDestAspectIcon = ((lpPS->dwFlags & PSF_CHECKDISPLAYASICON) ? TRUE : FALSE); // Return current flags
lpOPS->dwFlags = lpPS->dwFlags; // Return index of arrPasteEntries[] corresponding to format selected by user
lpOPS->nSelectedIndex = lpPS->nSelectedIndex; // Return if user selected Paste or PasteLink
lpOPS->fLink = lpPS->fLink;
/* if user selected same ASPECT as displayed in the
** source, then sizel passed in the ** ObjectDescriptor/LinkSrcDescriptor is ** applicable. otherwise, the sizel does not apply. */ if (lpPS->fLink) { if (lpPS->fSrcAspectIconLSD == fDestAspectIcon) lpOPS->sizel = lpPS->sizelLSD; else lpOPS->sizel.cx = lpOPS->sizel.cy = 0; } else { if (lpPS->fSrcAspectIconOD == fDestAspectIcon) lpOPS->sizel = lpPS->sizelOD; else lpOPS->sizel.cx = lpOPS->sizel.cy = 0; } // Return metafile with icon and icon title that the user selected
lpOPS->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); } break;
case IDCANCEL: // Free icon and icon title metafile
SendDlgItemMessage( hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L); SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); break;
case IDC_OLEUIHELP: PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0)); break; } break; } return FALSE; }
BOOL FPasteSpecialReInit(HWND hDlg, LPPASTESPECIAL lpPS) { LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
// free the icon/icon-title metafiel
if (lpPS->fLink) OleUIMetafilePictIconFree(lpPS->hMetaPictOD); else OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
// Free data assocatiated with each list box entry
FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELIST)); FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELINKLIST)); SendDlgItemMessage(hDlg, IDC_PS_DISPLAYLIST, LB_RESETCONTENT, 0, 0);
// Initialize user selections in the Paste and PasteLink listboxes
lpPS->nPasteListCurSel = 0; lpPS->nPasteLinkListCurSel = 0;
// Free previous object descriptor/link descriptor data
if (lpPS->hObjDesc != NULL) { GlobalFree(lpPS->hObjDesc); lpPS->hObjDesc = NULL; } if (lpPS->hLinkSrcDesc != NULL) { GlobalFree(lpPS->hLinkSrcDesc); lpPS->hLinkSrcDesc = NULL; }
lpPS->szAppName[0] = '\0';
// GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an
// OLE1 object (offering CF_OWNERLINK) or has been copied to
// clipboard by FileMaager (offering CF_FILENAME), an
// OBJECTDESCRIPTOR will be created will be created from CF_OWNERLINK
// or CF_FILENAME. See OBJECTDESCRIPTOR for more info.
STGMEDIUM medium; CLIPFORMAT cfFormat; lpPS->hObjDesc = OleStdFillObjectDescriptorFromData( lpOPS->lpSrcDataObj, &medium, &cfFormat); if (lpPS->hObjDesc) { LPOBJECTDESCRIPTOR lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(lpPS->hObjDesc);
// Get FullUserTypeName, SourceOfCopy and CLSID
if (lpOD->dwFullUserTypeName) #if defined(WIN32) && !defined(UNICODE)
WTOA(lpPS->szFullUserTypeNameOD, (LPWSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); #else
lstrcpyn(lpPS->szFullUserTypeNameOD, (LPTSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); #endif
else lstrcpyn(lpPS->szFullUserTypeNameOD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN);
if (lpOD->dwSrcOfCopy) { #if defined(WIN32) && !defined(UNICODE)
WTOA(lpPS->szSourceOfDataOD, (LPWSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); #else
lstrcpyn(lpPS->szSourceOfDataOD, (LPTSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); #endif
// If CF_FILENAME was offered, source of copy is a
// path name. Fit the path to the static control that will display it.
if (cfFormat == _g_cfFileName) { lstrcpyn(lpPS->szSourceOfDataOD, ChopText(GetDlgItem(hDlg, IDC_PS_SOURCETEXT), 0, lpPS->szSourceOfDataOD, 0), PS_UNKNOWNNAMELEN); } } else lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN);
lpPS->clsidOD = lpOD->clsid; lpPS->sizelOD = lpOD->sizel;
// Does source specify DVASPECT_ICON?
if (lpOD->dwDrawAspect & DVASPECT_ICON) lpPS->fSrcAspectIconOD = TRUE; else lpPS->fSrcAspectIconOD = FALSE;
// Does source specify OLEMISC_ONLYICONIC?
if (lpOD->dwStatus & OLEMISC_ONLYICONIC) lpPS->fSrcOnlyIconicOD = TRUE; else lpPS->fSrcOnlyIconicOD = FALSE;
// Get application name of source from auxusertype3 in the registration database
LPOLESTR lpszAppName = NULL; if (OleRegGetUserType(lpPS->clsidOD, USERCLASSTYPE_APPNAME, &lpszAppName) == NOERROR) { #if defined(WIN32) && !defined(UNICODE)
WTOA(lpPS->szAppName, lpszAppName, OLEUI_CCHKEYMAX); #else
lstrcpyn(lpPS->szAppName, lpszAppName, OLEUI_CCHKEYMAX); #endif
OleStdFree(lpszAppName); } else { if (0 == LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNAPP, lpPS->szAppName, PS_UNKNOWNSTRLEN)) { PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); return FALSE; } }
// Retrieve an icon from the object
if (lpPS->fSrcAspectIconOD) { lpPS->hMetaPictOD = OleStdGetData( lpOPS->lpSrcDataObj, (CLIPFORMAT) CF_METAFILEPICT, NULL, DVASPECT_ICON, &medium );
} // If object does not offer icon, obtain it from the CLSID
if (NULL == lpPS->hMetaPictOD) lpPS->hMetaPictOD = OleGetIconOfClass(lpPS->clsidOD, NULL, TRUE); }
// Does object offer CF_LINKSRCDESCRIPTOR?
lpPS->hLinkSrcDesc = OleStdGetData( lpOPS->lpSrcDataObj, (CLIPFORMAT) _g_cfLinkSrcDescriptor, NULL, DVASPECT_CONTENT, &medium); if (lpPS->hLinkSrcDesc) { // Get FullUserTypeName, SourceOfCopy and CLSID
LPLINKSRCDESCRIPTOR lpLSD = (LPLINKSRCDESCRIPTOR)GlobalLock(lpPS->hLinkSrcDesc); if (lpLSD->dwFullUserTypeName) #if defined(WIN32) && !defined(UNICODE)
WTOA(lpPS->szFullUserTypeNameLSD, (LPWSTR)((LPBYTE)lpLSD+lpLSD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); #else
lstrcpyn(lpPS->szFullUserTypeNameLSD, (LPTSTR)((LPBYTE)lpLSD+lpLSD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); #endif
else lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN);
if (lpLSD->dwSrcOfCopy) #if defined(WIN32) && !defined(UNICODE)
WTOA(lpPS->szSourceOfDataLSD, (LPWSTR)((LPBYTE)lpLSD+lpLSD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); #else
lstrcpyn(lpPS->szSourceOfDataLSD, (LPTSTR)((LPBYTE)lpLSD+lpLSD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); #endif
else lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN);
// if no ObjectDescriptor, then use LinkSourceDescriptor source string
if (!lpPS->hObjDesc) lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szSourceOfDataLSD, PS_UNKNOWNNAMELEN);
lpPS->clsidLSD = lpLSD->clsid; lpPS->sizelLSD = lpLSD->sizel;
// Does source specify DVASPECT_ICON?
if (lpLSD->dwDrawAspect & DVASPECT_ICON) lpPS->fSrcAspectIconLSD = TRUE; else lpPS->fSrcAspectIconLSD = FALSE;
// Does source specify OLEMISC_ONLYICONIC?
if (lpLSD->dwStatus & OLEMISC_ONLYICONIC) lpPS->fSrcOnlyIconicLSD = TRUE; else lpPS->fSrcOnlyIconicLSD = FALSE;
// Retrieve an icon from the object
if (lpPS->fSrcAspectIconLSD) { lpPS->hMetaPictLSD = OleStdGetData( lpOPS->lpSrcDataObj, CF_METAFILEPICT, NULL, DVASPECT_ICON, &medium ); } // If object does not offer icon, obtain it from the CLSID
if (NULL == lpPS->hMetaPictLSD) { HWND hIconWnd = GetDlgItem(hDlg, IDC_PS_ICONDISPLAY); RECT IconRect; GetClientRect(hIconWnd, &IconRect);
LPTSTR lpszLabel = OleStdCopyString(lpPS->szSourceOfDataLSD); // width is 2 times width of iconbox because it can wrap
int nWidth = (IconRect.right-IconRect.left) * 2; // limit text to the width or max characters
LPTSTR lpszChopLabel = ChopText(hIconWnd, nWidth, lpszLabel, lstrlen(lpszLabel)); #if defined(WIN32) && !defined(UNICODE)
OLECHAR wszChopLabel[MAX_PATH]; ATOW(wszChopLabel, lpszChopLabel, MAX_PATH); lpPS->hMetaPictLSD = OleGetIconOfClass(lpPS->clsidLSD, wszChopLabel, FALSE); #else
lpPS->hMetaPictLSD = OleGetIconOfClass(lpPS->clsidLSD, lpszChopLabel, FALSE); #endif
OleStdFree(lpszLabel); } } else if (lpPS->hObjDesc) // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR
{ // Copy the values of OBJECTDESCRIPTOR
lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szFullUserTypeNameOD, PS_UNKNOWNNAMELEN); lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szSourceOfDataOD, PS_UNKNOWNNAMELEN); lpPS->clsidLSD = lpPS->clsidOD; lpPS->sizelLSD = lpPS->sizelOD; lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD; lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD;
// Don't copy the hMetaPict; instead get a separate copy
if (lpPS->fSrcAspectIconLSD) { lpPS->hMetaPictLSD = OleStdGetData( lpOPS->lpSrcDataObj, CF_METAFILEPICT, NULL, DVASPECT_ICON, &medium ); } if (NULL == lpPS->hMetaPictLSD) { HWND hIconWnd = GetDlgItem(hDlg, IDC_PS_ICONDISPLAY); RECT IconRect; GetClientRect(hIconWnd, &IconRect);
LPTSTR lpszLabel = OleStdCopyString(lpPS->szSourceOfDataLSD); // width is 2 times width of iconbox because it can wrap
int nWidth = (IconRect.right-IconRect.left) * 2; // limit text to the width or max characters
LPTSTR lpszChopLabel = ChopText(hIconWnd, nWidth, lpszLabel, lstrlen(lpszLabel)); #if defined(WIN32) && !defined(UNICODE)
OLECHAR wszChopLabel[MAX_PATH]; ATOW(wszChopLabel, lpszChopLabel, MAX_PATH); lpPS->hMetaPictLSD = OleGetIconOfClass(lpPS->clsidLSD, wszChopLabel, FALSE); #else
lpPS->hMetaPictLSD = OleGetIconOfClass(lpPS->clsidLSD, lpszChopLabel, FALSE); #endif
OleStdFree(lpszLabel); } }
// Not an OLE object
if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL) { lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN); lstrcpyn(lpPS->szFullUserTypeNameOD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN); lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN); lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN); lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL; }
// Allocate scratch memory to construct item names in the paste and pastelink listboxes
if (lpPS->hBuff != NULL) { GlobalFree(lpPS->hBuff); lpPS->hBuff = NULL; }
lpPS->hBuff = AllocateScratchMem(lpPS); if (lpPS->hBuff == NULL) { PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); return FALSE; }
// Select the Paste Link Button if specified. Otherwise select
// Paste Button by default
if (lpPS->dwFlags & PSF_SELECTPASTELINK) lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK; else lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE;
// Mark which PasteEntry formats are available from source data object
OleStdMarkPasteEntryList( lpOPS->lpSrcDataObj, lpOPS->arrPasteEntries, lpOPS->cPasteEntries);
// Check if items are available to be pasted
BOOL fPasteAvailable = FFillPasteList(hDlg, lpPS); if (!fPasteAvailable) lpPS->dwFlags &= ~PSF_SELECTPASTE; StandardEnableDlgItem(hDlg, IDC_PS_PASTE, fPasteAvailable);
// Check if items are available to be paste-linked
BOOL fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS); if (!fPasteLinkAvailable) lpPS->dwFlags &= ~PSF_SELECTPASTELINK; StandardEnableDlgItem(hDlg, IDC_PS_PASTELINK, fPasteLinkAvailable);
// If one of Paste or PasteLink is disabled, select the other one
// regardless of what the input flags say
if (fPasteAvailable && !fPasteLinkAvailable) lpPS->dwFlags |= PSF_SELECTPASTE; if (fPasteLinkAvailable && !fPasteAvailable) lpPS->dwFlags |= PSF_SELECTPASTELINK;
BOOL bEnabled = TRUE; if (lpPS->dwFlags & PSF_SELECTPASTE) { // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it.
lpPS->dwFlags &= ~PSF_SELECTPASTE; CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, IDC_PS_PASTE); FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE); } else if (lpPS->dwFlags & PSF_SELECTPASTELINK) { // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it.
lpPS->dwFlags &= ~PSF_SELECTPASTELINK; CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, IDC_PS_PASTELINK); FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK); } else // Items are not available to be be Pasted or Paste-Linked
{ // Enable or disable DisplayAsIcon and set the result text and image
EnableDisplayAsIcon(hDlg, lpPS); SetPasteSpecialHelpResults(hDlg, lpPS); SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataOD); CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, 0); bEnabled = FALSE; } StandardEnableDlgItem(hDlg, IDOK, bEnabled);
return TRUE; }
/*
* FPasteSpecialInit * * Purpose: * WM_INITIDIALOG handler for the Paste Special dialog box. * * Parameters: * hDlg HWND of the dialog * wParam WPARAM of the message * lParam LPARAM of the message * * Return Value: * BOOL Value to return for WM_INITDIALOG. */ BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam) { // Copy the structure at lParam into our instance memory.
HFONT hFont; LPPASTESPECIAL lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), &hFont);
// PvStandardInit sent a termination to us already.
if (NULL == lpPS) return FALSE;
LPOLEUIPASTESPECIAL lpOPS = (LPOLEUIPASTESPECIAL)lParam;
// Copy other information from lpOPS that we might modify.
lpPS->lpOPS = lpOPS; lpPS->nIDD = IDD_PASTESPECIAL; lpPS->dwFlags = lpOPS->dwFlags;
// If we got a font, send it to the necessary controls.
if (NULL!=hFont) { SendDlgItemMessage(hDlg, IDC_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L); SendDlgItemMessage(hDlg, IDC_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); }
// Hide the help button if required
if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP)) StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
// Show or hide the Change icon button
if (lpPS->dwFlags & PSF_HIDECHANGEICON) DestroyWindow(GetDlgItem(hDlg, IDC_PS_CHANGEICON));
// Hide all DisplayAsIcon related controls if it should be disabled
if (lpPS->dwFlags & PSF_DISABLEDISPLAYASICON) { StandardShowDlgItem(hDlg, IDC_PS_DISPLAYASICON, SW_HIDE); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); }
// clear PSF_CHECKDISPLAYASICON -> it's an output parameter only
lpPS->dwFlags &= ~ PSF_CHECKDISPLAYASICON;
// Change the caption if required
if (NULL != lpOPS->lpszCaption) SetWindowText(hDlg, lpOPS->lpszCaption);
// Load 'Unknown Source' and 'Unknown Type' strings
int n = LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN); if (n) n = LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN); if (!n) { PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); return FALSE; }
if (!FPasteSpecialReInit(hDlg, lpPS)) return FALSE;
// Give initial focus to the list box
SetFocus(GetDlgItem(hDlg, IDC_PS_DISPLAYLIST));
// Set property to handle clipboard change notifications
SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg));
lpPS->fClipboardChanged = FALSE;
/*
* PERFORM OTHER INITIALIZATION HERE. */
// Call the hook with lCustData in lParam
UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData); return TRUE; }
/*
* FTogglePasteType * * Purpose: * Toggles between Paste and Paste Link. The Paste list and PasteLink * list are always invisible. The Display List is filled from either * the Paste list or the PasteLink list depending on which Paste radio * button is selected. * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * dwOption Paste or PasteSpecial option * * Return Value: * BOOL Returns TRUE if the option has already been selected. * Otherwise the option is selected and FALSE is returned */ BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption) { DWORD dwTemp; HWND hList, hListDisplay; LRESULT dwData; int i, nItems; LPTSTR lpsz;
// Skip all this if the button is already selected
if (lpPS->dwFlags & dwOption) return TRUE;
dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK; lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption;
// Hide IconDisplay. This prevents flashing if the icon display is changed
StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE);
hListDisplay = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST);
// If Paste was selected
if (lpPS->dwFlags & PSF_SELECTPASTE) { // Set the Source of the object in the clipboard
SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataOD);
// If an icon is available
if (lpPS->hMetaPictOD) // Set the icon display
SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET, 0, (LPARAM)lpPS->hMetaPictOD);
hList = GetDlgItem(hDlg, IDC_PS_PASTELIST); // We are switching from PasteLink to Paste. Remember current selection
// in PasteLink list so it can be restored.
lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L); if (lpPS->nPasteLinkListCurSel == LB_ERR) lpPS->nPasteLinkListCurSel = 0; // Remember if user selected Paste or PasteLink
lpPS->fLink = FALSE; } else // If PasteLink was selected
{ // Set the Source of the object in the clipboard
SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataLSD);
// If an icon is available
if (lpPS->hMetaPictLSD) // Set the icon display
SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET, 0, (LPARAM)lpPS->hMetaPictLSD);
hList = GetDlgItem(hDlg, IDC_PS_PASTELINKLIST); // We are switching from Paste to PasteLink. Remember current selection
// in Paste list so it can be restored.
lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L); if (lpPS->nPasteListCurSel == LB_ERR) lpPS->nPasteListCurSel = 0; // Remember if user selected Paste or PasteLink
lpPS->fLink = TRUE; }
// Turn drawing off while the Display List is being filled
SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L);
// Move data to Display list box
SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L); nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L); lpsz = (LPTSTR)GlobalLock(lpPS->hBuff); for (i = 0; i < nItems; i++) { SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz); dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz); SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData); } GlobalUnlock(lpPS->hBuff);
// Restore the selection in the Display List from user's last selection
if (lpPS->dwFlags & PSF_SELECTPASTE) SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L); else SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L);
// Paint Display List
SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L); InvalidateRect(hListDisplay, NULL, TRUE); UpdateWindow(hListDisplay);
// Auto give the focus to the Display List
if (GetForegroundWindow() == hDlg) SetFocus(hListDisplay);
// Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to
// the current selection
ChangeListSelection(hDlg, lpPS, hListDisplay);
return FALSE; }
/*
* ChangeListSelection * * Purpose: * When the user changes the selection in the list, DisplayAsIcon is enabled or disabled, * Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding * to the current format selection is saved. * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * hList HWND of the List * * Return Value: * No return value */ void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList) { LPPASTELISTITEMDATA lpItemData; int nCurSel;
EnableDisplayAsIcon(hDlg, lpPS); SetPasteSpecialHelpResults(hDlg, lpPS);
// Remember index of arrPasteEntries[] corresponding to the current selection
nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L); if (nCurSel == LB_ERR) return; lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nCurSel, 0L); if ((LRESULT)lpItemData == LB_ERR) return; lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex; }
/*
* EnableDisplayAsIcon * * Purpose: * Enable or disable the DisplayAsIcon button depending on whether * the current selection can be displayed as an icon or not. The following table describes * the state of DisplayAsIcon. The calling application is termed CONTAINER, the source * of data on the clipboard is termed SOURCE. * Y = Yes; N = No; Blank = State does not matter; * ===================================================================== * SOURCE SOURCE CONTAINER DisplayAsIcon * specifies specifies specifies Initial State * DVASPECT_ICON OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON * * N Unchecked&Disabled * Y Y Checked&Disabled * Y N Y Checked&Enabled * N N Y Unchecked&Enabled * ===================================================================== * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * * Return Value: * No return value */ void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS) { int nIndex; BOOL fCntrEnableIcon; BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD; BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD; HWND hList; LPPASTELISTITEMDATA lpItemData; HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD;
hList = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST);
// Get data corresponding to the current selection in the listbox
nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0); if (nIndex != LB_ERR) { lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L); if ((LRESULT)lpItemData != LB_ERR) fCntrEnableIcon = lpItemData->fCntrEnableIcon; else fCntrEnableIcon = FALSE; } else fCntrEnableIcon = FALSE;
// If there is an icon available
if (hMetaPict != NULL) { if (!fCntrEnableIcon) // Does CONTAINER specify OLEUIPASTE_ENABLEICON?
{ // Uncheck & Disable DisplayAsIcon
lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE); StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE);
// Hide IconDisplay and ChangeIcon button
StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); } else if (fSrcOnlyIconic) // Does SOURCE specify OLEMISC_ONLYICONIC?
{ // Check & Disable DisplayAsIcon
lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, TRUE); StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE);
// Show IconDisplay and ChangeIcon button
StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_SHOWNORMAL); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_SHOWNORMAL); } else if (fSrcAspectIcon) // Does SOURCE specify DVASPECT_ICON?
{ // Check & Enable DisplayAsIcon
lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, TRUE); StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, TRUE);
// Show IconDisplay and ChangeIcon button
StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_SHOWNORMAL); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_SHOWNORMAL); } else { //Uncheck and Enable DisplayAsIcon
lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE); StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, TRUE);
// Hide IconDisplay and ChangeIcon button
StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE);
} } else // No icon available
{ // Unchecked & Disabled
lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE); StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE);
// Hide IconDisplay and ChangeIcon button
StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); } }
/*
* ToggleDisplayAsIcon * * Purpose: * Toggles the DisplayAsIcon button. Hides or shows the Icon Display and * the ChangeIcon button and changes the help result text and bitmap. * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * * Return Value: * None * */ void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS) { BOOL fCheck; int i;
fCheck = IsDlgButtonChecked(hDlg, IDC_PS_DISPLAYASICON);
if (fCheck) lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
// Set the help result text and bitmap
SetPasteSpecialHelpResults(hDlg, lpPS);
// Show or hide the Icon Display and ChangeIcon button depending
// on the check state
i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE; StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, i); StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, i); }
/*
* ChangeIcon * * Purpose: * Brings up the ChangeIcon dialog which allows the user to change * the icon and label. * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * * Return Value: * None * */
void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS) { OLEUICHANGEICON ci; UINT uRet; CLSID clsid = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD;
//Initialize the structure
memset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); ci.cbStruct = sizeof(ci); ci.hWndOwner = hDlg; ci.clsid = clsid; ci.dwFlags = CIF_SELECTCURRENT;
// Only show help in the ChangeIcon dialog if we're showing it in this dialog.
if (lpPS->dwFlags & PSF_SHOWHELP) ci.dwFlags |= CIF_SHOWHELP;
// Let the hook in to customize Change Icon if desired.
uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
if (0 == uRet) uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
// Update the display if necessary.
if (0!=uRet) { /*
* OleUIChangeIcon will have already freed our * current hMetaPict that we passed in when OK is * pressed in that dialog. So we use 0L as lParam * here so the IconBox doesn't try to free the * metafilepict again. */ SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET, 0, (LPARAM)ci.hMetaPict); // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate
// icons - changing one does not change the other.
if (lpPS->fLink) lpPS->hMetaPictLSD = ci.hMetaPict; else lpPS->hMetaPictOD = ci.hMetaPict; } }
/*
*SetPasteSpecialHelpResults * * Purpose: * Sets the help result text and bitmap according to the current * list selection. The following state table indicates which ResultText * and ResultImage are selected. If %s in the lpstrFormatName is present, * it is assumed that an object is being pasted/paste-linked, otherwise it * is assumed that data is being pasted/paste-linked. * Y = Yes; N = No; Blank = State does not matter; * The numbers in the the ResultText and ResultImage columns refer to the table * entries that follow. * ===================================================================== * Paste/ lpstrFormatName in DisplayAsIcon Result Result * PasteLink arrPasteEntry[]contains %s checked Text Image * (Is Object == Y, Is Data == N) * Paste N 1 1 * Paste Y N 2 2 * Paste Y Y 3 3 * PasteLink N 4 4 * PasteLink Y N 5 4 * PasteLink Y Y 6 5 * ===================================================================== * Result Text: * * 1. "Inserts the contents of the Clipboard into your document as <native type name, * and optionally an additional help sentence>" * 2. "Inserts the contents of the Clipboard into your document so that you may * activate it using <object app name>" * 3. "Inserts the contents of the Clipboard into your document so that you may * activate it using <object app name>. It will be displayed as an icon." * 4. "Inserts the contents of the Clipboard into your document as <native type name>. * Paste Link creates a link to the source file so that changes to the source file * will be reflected in your document." * 5. "Inserts a picture of the Clipboard contents into your document. Paste Link * creates a link to the source file so that changes to the source file will be * reflected in your document." * 6. "Inserts an icon into your document which represents the Clipboard contents. * Paste Link creates a link to the source file so that changes to the source file * will be reflected in your document." * ===================================================================== * Result Image: * * 1. Clipboard Image * 2. Paste image, non-iconic. * 3. Paste image, iconic. * 4. Paste Link image, non-iconic * 5. Paste Link image, iconic * ==================================================================== * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * * Return Value: * No return value */ void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS) { LPTSTR psz1, psz2, psz3, psz4; UINT i, iString, iImage, cch; int nPasteEntriesIndex; BOOL fDisplayAsIcon; BOOL fIsObject; HWND hList; LPPASTELISTITEMDATA lpItemData; LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; LPTSTR szFullUserTypeName = (lpPS->fLink) ? lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD; LPTSTR szInsert;
hList = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST);
i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); if (i != LB_ERR) { lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L); if ((LRESULT)lpItemData == LB_ERR) return; nPasteEntriesIndex = lpItemData->nPasteEntriesIndex; // Check if there is a '%s' in the lpstrFormatName, then an object is being
// pasted/pastelinked. Otherwise Data is being pasted-pastelinked.
fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName, lpPS); } else return;
// Is DisplayAsIcon checked?
fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON));
szInsert = szFullUserTypeName;
if (lpPS->dwFlags & PSF_SELECTPASTE) // If user selected Paste
{ if (fIsObject) { iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT; iImage = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; szInsert = lpPS->szAppName; } else { iString = IDS_PSPASTEDATA; iImage = RESULTIMAGE_PASTE; } } else if (lpPS->dwFlags & PSF_SELECTPASTELINK) // User selected PasteLink
{ if (fIsObject) { iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT; iImage = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK; } else { iString = IDS_PSPASTELINKDATA; iImage = RESULTIMAGE_LINK; }
} else // Should never occur.
{ iString = IDS_PSNONOLE; iImage = RESULTIMAGE_PASTE; }
// hBuff contains enough space for the 4 buffers required to build up the help
// result text.
cch = (UINT)(GlobalSize(lpPS->hBuff) / sizeof(TCHAR)) / 4;
psz1 = (LPTSTR)GlobalLock(lpPS->hBuff); psz2 = psz1 + cch; psz3 = psz2 + cch; psz4 = psz3 + cch;
// Default is an empty string.
*psz1 = 0;
if (0 != LoadString(_g_hOleStdResInst, iString, psz1, cch) && nPasteEntriesIndex != -1) { // Insert the FullUserTypeName of the source object into the partial result text
// specified by the container.
wsprintf(psz3, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText, (LPTSTR)szInsert); // Insert the above partial result text into the standard result text.
wsprintf(psz4, psz1, (LPTSTR)psz3); psz1 = psz4; }
// If LoadString failed, we simply clear out the results (*psz1 = 0 above)
SetDlgItemText(hDlg, IDC_PS_RESULTTEXT, psz1);
GlobalUnlock(lpPS->hBuff);
// Change the result bitmap
SendDlgItemMessage(hDlg, IDC_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L); }
/*
* FAddPasteListItem * * Purpose: * Adds an item to the list box * * Parameters: * hList HWND List into which item is to be added * fInsertFirst BOOL Insert in the beginning of the list? * nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to * lpPS Paste Special Dialog Structure * lpszBuf LPSTR Scratch buffer to build up string for list entry * lpszFullUserTypeName LPSTR full user type name for object entry * * Return Value: * BOOL TRUE if sucessful. * FALSE if unsucessful. */ BOOL FAddPasteListItem( HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex, LPPASTESPECIAL lpPS, LPTSTR lpszBuf, LPTSTR lpszFullUserTypeName) { LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; LPPASTELISTITEMDATA lpItemData; int nIndex;
// Allocate memory for each list box item
lpItemData = (LPPASTELISTITEMDATA)OleStdMalloc(sizeof(PASTELISTITEMDATA)); if (NULL == lpItemData) return FALSE;
// Fill data associated with each list box item
lpItemData->nPasteEntriesIndex = nPasteEntriesIndex; lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags & OLEUIPASTE_ENABLEICON) ? TRUE : FALSE);
// Build list box entry string, insert the string and add the data the corresponds to it
wsprintf( lpszBuf, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName, lpszFullUserTypeName );
// only add to listbox if not a duplicate
if (LB_ERR!=SendMessage(hList,LB_FINDSTRING, 0, (LPARAM)lpszBuf)) { // item is already in list; SKIP this one
OleStdFree((LPVOID)lpItemData); return TRUE; // this is NOT an error
}
nIndex = (int)SendMessage( hList, (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING), 0, (LPARAM)lpszBuf ); SendMessage( hList, LB_SETITEMDATA, nIndex, (LPARAM)(LPPASTELISTITEMDATA)lpItemData ); return TRUE; }
/*
* FFillPasteList * * Purpose: * Fills the invisible paste list with the formats offered by the clipboard object and * asked for by the container. * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * * Return Value: * BOOL TRUE if sucessful and if formats could be found. * FALSE if unsucessful or if no formats could be found. */ BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS) { LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; HWND hList; int i, j; int nItems = 0; int nDefFormat = -1; BOOL fTryObjFmt = FALSE; BOOL fInsertFirst; BOOL fExclude;
hList = GetDlgItem(hDlg, IDC_PS_PASTELIST); SendMessage(hList, LB_RESETCONTENT, 0, 0);
// Loop over the target's priority list of formats
for (i = 0; i < lpOPS->cPasteEntries; i++) { if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY && !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE)) continue;
fInsertFirst = FALSE;
if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfFileName || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfEmbeddedObject || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfEmbedSource) { if (! fTryObjFmt) { fTryObjFmt = TRUE; // only use 1st object format
fInsertFirst = TRUE; // OLE obj format should always be 1st
//Check if this CLSID is in the exclusion list.
fExclude=FALSE;
for (j=0; j < (int)lpOPS->cClsidExclude; j++) { if (IsEqualCLSID(lpPS->clsidOD, lpOPS->lpClsidExclude[j])) { fExclude=TRUE; break; } }
if (fExclude) continue; // don't add the object entry to list
} else { continue; // already added an object format to list
} }
// add to list if entry is marked TRUE
if (lpOPS->arrPasteEntries[i].dwScratchSpace) { if (nDefFormat < 0) nDefFormat = (fInsertFirst ? 0 : nItems); else if (fInsertFirst) nDefFormat++; // adjust for obj fmt inserted 1st in list
LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff); if (lpszBuf) { if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, lpszBuf, lpPS->szFullUserTypeNameOD)) { GlobalUnlock(lpPS->hBuff); goto error; } GlobalUnlock(lpPS->hBuff); } nItems++; } }
// initialize selection to first format matched in list
if (nDefFormat >= 0) lpPS->nPasteListCurSel = nDefFormat;
// Clean up
// If no items have been added to the list box (none of the formats
// offered by the source matched those acceptable to the container),
// return FALSE
if (nItems > 0) return TRUE; else return FALSE;
error: FreeListData(hList);
return FALSE; }
/*
* FFillPasteLinkList * * Purpose: * Fills the invisible paste link list with the formats offered by the clipboard object and * asked for by the container. * * Parameters: * hDlg HWND of the dialog * lpPS Paste Special Dialog Structure * * Return Value: * BOOL TRUE if sucessful and if formats could be found. * FALSE if unsucessful or if no formats could be found. */ BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS) { LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; LPDATAOBJECT lpSrcDataObj = lpOPS->lpSrcDataObj; LPENUMFORMATETC lpEnumFmtEtc = NULL; OLEUIPASTEFLAG pasteFlag; UINT arrLinkTypesSupported[PS_MAXLINKTYPES]; // Array of flags that
// indicate which link types
// are supported by source.
FORMATETC fmtetc; int i, j; int nItems = 0; BOOL fLinkTypeSupported = FALSE; HWND hList; int nDefFormat = -1; BOOL fTryObjFmt = FALSE; BOOL fInsertFirst; HRESULT hrErr;
// Remember which link type formats are offered by lpSrcDataObj.
memset(&fmtetc, 0, sizeof(FORMATETC)); for (i = 0; i < lpOPS->cLinkTypes; i++) { if (lpOPS->arrLinkTypes[i] == _g_cfLinkSource) { OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n")) hrErr = OleQueryLinkFromData(lpSrcDataObj); OLEDBG_END2 if(NOERROR == hrErr) { arrLinkTypesSupported[i] = 1; fLinkTypeSupported = TRUE; } else arrLinkTypesSupported[i] = 0; } else { fmtetc.cfFormat = (CLIPFORMAT)lpOPS->arrLinkTypes[i]; fmtetc.dwAspect = DVASPECT_CONTENT; fmtetc.tymed = 0xFFFFFFFF; // All tymed values
fmtetc.lindex = -1; OLEDBG_BEGIN2(TEXT("IDataObject::QueryGetData called\r\n")) hrErr = lpSrcDataObj->QueryGetData(&fmtetc); OLEDBG_END2 if(NOERROR == hrErr) { arrLinkTypesSupported[i] = 1; fLinkTypeSupported = TRUE; } else arrLinkTypesSupported[i] = 0; } } // No link types are offered by lpSrcDataObj
if (! fLinkTypeSupported) { nItems = 0; goto cleanup; }
hList = GetDlgItem(hDlg, IDC_PS_PASTELINKLIST); SendMessage(hList, LB_RESETCONTENT, 0, 0);
// Enumerate the formats acceptable to container
for (i = 0; i < lpOPS->cPasteEntries; i++) { fLinkTypeSupported = FALSE;
// If container will accept any link type offered by source object
if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE) fLinkTypeSupported = TRUE; else { // Check if any of the link types offered by the source
// object are acceptable to the container
// This code depends on the LINKTYPE enum values being powers of 2
for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0; j < lpOPS->cLinkTypes; (UINT&)pasteFlag *= 2, j++) { if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) && arrLinkTypesSupported[j]) { fLinkTypeSupported = TRUE; break; } } }
fInsertFirst = FALSE;
if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfFileName || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfLinkSource) { if (! fTryObjFmt) { fTryObjFmt = TRUE; // only use 1st object format
fInsertFirst = TRUE; // OLE obj format should always be 1st
} else { continue; // already added an object format to list
} }
// add to list if entry is marked TRUE
if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace) { if (nDefFormat < 0) nDefFormat = (fInsertFirst ? 0 : nItems); else if (fInsertFirst) nDefFormat++; // adjust for obj fmt inserted 1st in list
LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff); if (lpszBuf) { if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, lpszBuf, lpPS->szFullUserTypeNameLSD)) { GlobalUnlock(lpPS->hBuff); goto error; } GlobalUnlock(lpPS->hBuff); } nItems++; } } // end FOR
nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L);
// initialize selection to first format matched in list
if (nDefFormat >= 0) lpPS->nPasteLinkListCurSel = nDefFormat;
cleanup: // Clean up
// If no items have been added to the list box (none of the formats
// offered by the source matched those acceptable to the destination),
// return FALSE
if (nItems > 0) return TRUE; else return FALSE;
error: FreeListData(hList);
return FALSE; }
/*
* FreeListData * * Purpose: * Free the local memory associated with each list box item * * Parameters: * hList HWND of the list * * Return Value: * None */ void FreeListData(HWND hList) { int nItems, i; LPPASTELISTITEMDATA lpItemData;
nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L); for (i = 0; i < nItems; i++) { lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); if ((LRESULT)lpItemData != LB_ERR) OleStdFree((LPVOID)lpItemData); } }
/*
* FHasPercentS * * Purpose: * Determines if string contains %s. * * Parameters: * lpsz LPCSTR string in which occurence of '%s' is looked for * * Return Value: * BOOL TRUE if %s is found, else FALSE. */ BOOL FHasPercentS(LPCTSTR lpsz, LPPASTESPECIAL lpPS) { int n = 0; LPTSTR lpszTmp;
if (!lpsz) return FALSE; // Copy input string to buffer. This allows caller to pass a
// code-based string. Code segments may be swapped out in low memory situations
// and so code-based strings need to be copied before string elements can be accessed.
lpszTmp = (LPTSTR)GlobalLock(lpPS->hBuff); lstrcpy(lpszTmp, lpsz);
while (*lpszTmp) { if (*lpszTmp == '%') { lpszTmp = CharNext(lpszTmp); if (*lpszTmp == 's') // if %s, return
{ GlobalUnlock(lpPS->hBuff); return TRUE; } else if (*lpszTmp == '%') // if %%, skip to next character
lpszTmp = CharNext(lpszTmp); } else lpszTmp = CharNext(lpszTmp); }
GlobalUnlock(lpPS->hBuff); return FALSE; }
/*
* AllocateScratchMem * * Purpose: * Allocates scratch memory for use by the PasteSpecial dialog. The memory is * is used as the buffer for building up strings using wsprintf. Strings are built up * using the buffer while inserting items into the Paste & PasteLink lists and while * setting the help result text. It must be big enough to handle the string that results after * replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[] * by the FullUserTypeName. It must also be big enough to build the dialog's result text * after %s substitutions by the FullUserTypeName or the ApplicationName. * * Parameters: * lpPS Paste Special Dialog Structure * * Return Value: * HGLOBAL Handle to allocated global memory */ HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS) { LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; int nLen, i; int nSubstitutedText = 0; int nAlloc = 0;
// Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR
// and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted
// for %s in the result-text/list entries.
if (lpPS->szFullUserTypeNameOD) nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD); if (lpPS->szFullUserTypeNameLSD) nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD)); if (lpPS->szAppName) nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName));
// Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries
nLen = 0; for (i = 0; i < lpOPS->cPasteEntries; i++) { nLen = max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName)); nLen = max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText)); }
// Get the maximum length of lpstrFormatNames and lpstrResultText after %s has
// been substituted (At most one %s can appear in each string).
// Add 1 to hold NULL terminator.
nAlloc = (nLen+nSubstitutedText+1)*sizeof(TCHAR);
// Allocate scratch memory to be used to build strings
// nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[]
// after %s substitution.
// We also need space to build up the help result text. 512 is the maximum length of the
// standard dialog help text before substitutions. 512+nAlloc is the maximum length
// after %s substition.
// SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text
return GlobalAlloc(GHND, (DWORD)4*(512 * sizeof(TCHAR) + nAlloc)); }
|