//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1994 by Borland International, All Rights Reserved // // Defines type TPasteSpecialDlg //---------------------------------------------------------------------------- #define INC_OLE2 #include #include #include #include #include #include #include #include // for IDHELP #include // // OWL OLE Dialog diagnostic group. // DIAG_DECLARE_GROUP(OwlOleDlg); // // // static bool CompareTargetDevice(DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight) { if (ptdLeft == ptdRight) return true; else if (!ptdRight || !ptdLeft) return false; else if (ptdLeft->tdSize != ptdRight->tdSize) return false; else if (memcmp(ptdLeft, ptdRight, (int)ptdLeft->tdSize) != 0) return false; return true; } // // Returns 0 for exact match, 1 for no match, -1 for partial match (which is // defined to mean the left is a subset of the right: fewer aspects, // null target device, fewer medium). // static int CompareFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight) { bool bExact = true; if (pFetcLeft->cfFormat != pFetcRight->cfFormat) return 1; else if (!CompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd)) return 1; if (pFetcLeft->dwAspect == pFetcRight->dwAspect) // // Same aspects implies equality // ; else if ((pFetcLeft->dwAspect & ~pFetcRight->dwAspect) != 0) // // Left not subset of aspects of right implies not equal // return 1; else // // left subset of right // bExact = false; if (pFetcLeft->tymed == pFetcRight->tymed) // same medium flags; equal ; else if ((pFetcLeft->tymed & ~pFetcRight->tymed) != 0) // // left not subset of medium flags of right; not equal // return 1; else // // left subset of right // bExact = false; return bExact ? 0 : -1; } DEFINE_RESPONSE_TABLE1(TPasteSpecialDlg, TOleDialog) EV_WM_DRAWCLIPBOARD, EV_WM_CHANGECBCHAIN, EV_BN_CLICKED(IDC_CHANGEICON, ChangeIconClicked), EV_BN_CLICKED(IDC_PASTE, PasteClicked), EV_BN_CLICKED(IDC_PASTELINK, PasteLinkClicked), EV_BN_CLICKED(IDC_DISPLAYASICON, DisplayAsIconClicked), EV_LBN_SELCHANGE(IDC_DISPLAYLIST, DisplayListSelChange), EV_LBN_DBLCLK(IDC_DISPLAYLIST, DisplayListDblClk), END_RESPONSE_TABLE; // // Initialize all data members to 0 [or false] // TPasteSpecialDlg::TData::TData() { // // This class is really just a PODS, so we'll take // advantage of memset // memset(this, 0, sizeof(TData)); } // // Initialize all data members to 0 [or false] // TPasteSpecialDlg::TPasteListItemData::TPasteListItemData() { // // This class is really just a PODS, so we'll take // advantage of memset // memset(this, 0, sizeof(TPasteListItemData)); } // // Initialize all data members to 0 [or false] // TPasteSpecialDlg::TPasteEntry::TPasteEntry() { // // This class is really just a PODS, so we'll take // advantage of memset // memset(this, 0, sizeof(TPasteEntry)); } // // Initialize helper object used internally by TPasteSpecialDlg // TPasteSpecialDlg::THelper::THelper() { // // This structure is a private PODS which allows // us to take advantage of memset. // memset(this, 0, sizeof(THelper)); } // // Initialize TPasteSpecial Dialog: // - Alias Dialog controls with C++ objects // - Initialize internal variables // TPasteSpecialDlg::TPasteSpecialDlg(TWindow* parent, TOcInitInfo &initInfo, TData *data, TResId templateId, const char far *title, TModule* module): TOleDialog(parent, templateId ? templateId : TResId(DLG_PASTESPECIAL), title, module), InitInfo(initInfo), Helper(*new THelper) { // // Wrap controls // ResultImage = new TResultImage(this, IDC_RESULTIMAGE); IconImage = new TIconImage(this, IDC_ICONIMAGE); DisplayAsIcon = new TCheckBox(this, IDC_DISPLAYASICON); Paste = new TRadioButton(this, IDC_PASTE); PasteLink = new TRadioButton(this, IDC_PASTELINK); DisplayList = new TListBox(this, IDC_DISPLAYLIST); PasteList = new TListBox(this, IDC_PASTELIST); PasteLinkList = new TListBox(this, IDC_PASTELINKLIST); ChangeIcon = new TButton(this, IDC_CHANGEICON); ResultText = new TStatic(this, IDC_RESULTTEXT); SourceText = new TStatic(this, IDC_SOURCE); Help = new TButton(this, IDHELP); // // Store TData pointer (if specified) // Data = data; // // Init internal variables // DeleteData = false; pOleUIEntries = 0; pBOleEntries = 0; pBOleLinkEntries = 0; } // // Cleanup memory allocated for TPasteSpecialInfo pointers if // user relied on default one. // TPasteSpecialDlg::~TPasteSpecialDlg() { delete &Helper; // // Delete Data pointer if we allocated it // if (DeleteData) { delete Data; if (pOleUIEntries) delete []pOleUIEntries; if (pBOleEntries) delete []pBOleEntries; if (pBOleLinkEntries) delete []pBOleLinkEntries; } } // // Check if a TPasteSpecialInfo pointer was specified - Create one // if necessary. // int TPasteSpecialDlg::DoExecute() { if (!Data) { if (!GetDefaultPasteSpecialData()) { return IDCANCEL; } } return TDialog::DoExecute(); } // // Validate flags, Initialize Helper structure, // Fill Paste/PasteLink listboxes // bool TPasteSpecialDlg::EvInitDialog(HWND hwndFocus) { // // Call base to alias controls // TOleDialog::EvInitDialog(hwndFocus); // // Enable Wait cursor // HCURSOR oldCursor = HourGlassOn(); // // Copy user info. and init helper class // Helper.Flags = Data->Flags; Helper.PasteListCurSel = 0; Helper.PasteLinkListCurSel = 0; // // Set control font // if (Font) { ResultText->SetWindowFont(*Font, false); SourceText->SetWindowFont(*Font, false); } // // Hide help if requested // if (!(Helper.Flags & psShowHelp)) Activate(Help, false); // // Hide IconDisplay related controls if requested // if (Helper.Flags & psDisableDisplayAsIcon) { Activate(DisplayAsIcon, false); Activate(IconImage, false); Activate(ChangeIcon, false); } // // Clear 'CheckDisplayAsIcon' [out-flag only] // Helper.Flags &= ~psCheckDisplayAsIcon; // // Load 'Unknown Source' and 'Unknown Type' strings // GetModule()->LoadString(IDS_PSUNKNOWNTYPE, Helper.UnknownType, MaxUnknownLen); GetModule()->LoadString(IDS_PSUNKNOWNSRC, Helper.UnknownSource, MaxUnknownLen); Helper.AppName[0]= 0; // // Fill OBJECTDESCRIPTOR structure // STGMEDIUM medium; CLIPFORMAT cfFormat; Helper.ObjDesc = FillObjectDescriptorFromData(Data->lpSrcDataObj, &medium, &cfFormat); if (Helper.ObjDesc) { LPOBJECTDESCRIPTOR lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(Helper.ObjDesc); // // Retrieve FullUserTypeName, SourceOfCopy and CLSID // if (lpOD->dwFullUserTypeName) Helper.FullUserTypeNameOD = (LPSTR)lpOD + (int)lpOD->dwFullUserTypeName; else Helper.FullUserTypeNameOD = Helper.UnknownType; if (lpOD->dwSrcOfCopy) { Helper.SourceOfDataOD = (LPSTR)lpOD + (int)lpOD->dwSrcOfCopy; // // If CF_FILENAME is offered, source of copy is a path name; // Chop the name to fit the static control it will be displayed in // if (cfFormat == cfFileName) Helper.SourceOfDataOD= ChopText(*SourceText, 0, Helper.SourceOfDataOD); } else { Helper.SourceOfDataOD = Helper.UnknownSource; } Helper.ClsIdOD = lpOD->clsid; Helper.SizeLOD = lpOD->sizel; // // Update helper class about DVASPECT_ICON & OLEMISC_ONLYICONIC flags // Helper.SrcAspectIconOD = (lpOD->dwDrawAspect & DVASPECT_ICON) ? true : false; Helper.SrcOnlyIconicOD = (lpOD->dwStatus & OLEMISC_ONLYICONIC) ? true : false; // // Get App. Name of source from auxusertype3 in reg. database // if (!GetAuxUserType(Helper.ClsIdOD, 3, Helper.AppName, MaxKeyLen, 0)) { // // Default to "the application which created it" as the name // GetModule()->LoadString(IDS_PSUNKNOWNAPP, Helper.AppName, MaxKeyLen); } // // Retrieve an icon from the object // if (Helper.SrcAspectIconOD) { Helper.MetaPictOD = GetData(Data->lpSrcDataObj, CF_METAFILEPICT, 0, DVASPECT_ICON, &medium); } // // If none, retrieve icon from CLSID // if (!Helper.MetaPictOD) { Helper.MetaPictOD = GetIconFromClass(Helper.ClsIdOD, 0, TRUE); } } // // Does object offer CF_LINKSRCDESCRIPTOR // Helper.LinkSrcDesc = GetData(Data->lpSrcDataObj, cfLinkSrcDescriptor, 0, DVASPECT_CONTENT, &medium); if (Helper.LinkSrcDesc) { LPLINKSRCDESCRIPTOR lpLSD = (LPLINKSRCDESCRIPTOR) GlobalLock(Helper.LinkSrcDesc); // // Get FullUserTypeName, SourceOfCopy and CLSID // if (lpLSD->dwFullUserTypeName) Helper.FullUserTypeNameLSD = (LPSTR)lpLSD + (int)lpLSD->dwFullUserTypeName; else Helper.FullUserTypeNameLSD = Helper.UnknownType; if (lpLSD->dwSrcOfCopy) Helper.SourceOfDataLSD = (LPSTR)lpLSD + (int)lpLSD->dwSrcOfCopy; else Helper.SourceOfDataLSD = Helper.UnknownSource; // // If no objectDescriptor, use linkSourceDescriptor source string // if (!Helper.ObjDesc) Helper.SourceOfDataOD = Helper.SourceOfDataLSD; Helper.ClsIdLSD = lpLSD->clsid; Helper.SizeLLSD = lpLSD->sizel; // // Update helper class about DVASPECT_ICON & OLEMISC_ONLYICONIC // Helper.SrcAspectIconLSD = (lpLSD->dwDrawAspect & DVASPECT_ICON) ? true : false; Helper.SrcOnlyIconicLSD = (lpLSD->dwStatus & OLEMISC_ONLYICONIC) ? true : false; // // Retrieve an icon from object // if (Helper.SrcAspectIconLSD) { Helper.MetaPictLSD = GetData(Data->lpSrcDataObj, CF_METAFILEPICT, 0, DVASPECT_ICON, &medium); // // If object offers none, retrieve icon from CLSID // if (!Helper.MetaPictLSD) { // // Retrieve 1.5 times width of iconbox // TRect rect; IconImage->GetClientRect(rect); int width = rect.Width() *3/2; // // Chop label to fit width // char label[MaxLabelLen]; strcpyn(label, Helper.SourceOfDataLSD, sizeof(label)); label[sizeof(label)-1] = 0; LPSTR lpszLabel = ChopText(*IconImage, width, label); // // Retrieve icon // Helper.MetaPictLSD = GetIconFromClass(Helper.ClsIdLSD, lpszLabel, FALSE); } } } else if (Helper.ObjDesc) // Offers no LINKSRCDESCRIPTOR but { // Offers OBJECTDESCRIPTOR - Copy OD values! Helper.FullUserTypeNameLSD = Helper.FullUserTypeNameOD; Helper.SourceOfDataLSD = Helper.SourceOfDataOD; Helper.ClsIdLSD = Helper.ClsIdOD; Helper.SizeLLSD = Helper.SizeLOD; Helper.SrcAspectIconLSD = Helper.SrcAspectIconOD; Helper.SrcOnlyIconicLSD = Helper.SrcOnlyIconicOD; // // Grab copy of MetaPict // if (Helper.SrcAspectIconLSD) { Helper.MetaPictLSD = GetData(Data->lpSrcDataObj, CF_METAFILEPICT, 0, DVASPECT_ICON, &medium); } // // Retrieve icon from CLSID // if (!Helper.MetaPictLSD) { // // Retrieve 1.5 times width of iconbox // TRect rect; IconImage->GetClientRect(rect); int width = rect.Width() *3/2; // // Chop label to fit width // char label[MaxLabelLen]; strcpyn(label, Helper.SourceOfDataLSD, sizeof(label)); label[sizeof(label)-1] = 0; LPSTR lpszLabel = ChopText(*IconImage, width, label); // // Retrieve Icon // Helper.MetaPictLSD = GetIconFromClass(Helper.ClsIdLSD, lpszLabel, FALSE); } } // // We have a non-OLE object // if (!Helper.ObjDesc && !Helper.LinkSrcDesc) { Helper.FullUserTypeNameLSD = Helper.FullUserTypeNameOD = Helper.UnknownType; Helper.SourceOfDataLSD = Helper.SourceOfDataOD = Helper.UnknownSource; Helper.MetaPictLSD = Helper.MetaPictOD = 0; } // // Update Flags: paste vs. pastelink // if (Helper.Flags & psSelectPasteLink) Helper.Flags = (Helper.Flags & ~psSelectPaste) | psSelectPasteLink; else Helper.Flags = (Helper.Flags & ~psSelectPasteLink) | psSelectPaste; // // Mark which PasteEntry formats are available from source data object // MarkPasteEntryList(Data->lpSrcDataObj, Data->ArrayPasteEntries, Data->cPasteEntries); // // Check if items are available for pasting // bool pasteAvailable = FillPasteList(); if (!pasteAvailable) { Helper.Flags &= ~psSelectPaste; Paste->EnableWindow(false); } // // Check if items are available for paste-linking // bool pasteLinkAvailable = FillPasteLinkList(); if (!pasteLinkAvailable) { Helper.Flags &= ~psSelectPasteLink; PasteLink->EnableWindow(false); } // // Validate flags base on paste availability // if (pasteAvailable && !pasteLinkAvailable) Helper.Flags |= psSelectPaste; if (pasteLinkAvailable && !pasteAvailable) Helper.Flags |= psSelectPasteLink; if (Helper.Flags & psSelectPaste) { CheckRadioButton(IDC_PASTE, IDC_PASTELINK, IDC_PASTE); // // TogglePaste will set paste flag, so clear it first // Helper.Flags &= ~psSelectPaste; TogglePasteType(psSelectPaste); } else if (Helper.Flags & psSelectPasteLink) { CheckRadioButton(IDC_PASTE, IDC_PASTELINK, IDC_PASTELINK); // // TogglePaste will set pasteLink flag, so clear it first // Helper.Flags &= psSelectPasteLink; TogglePasteType(psSelectPasteLink); } else { EnableDisplayAsIcon(); SetPasteSpecialHelpResults(); } // // Set Focus to ListBox // DisplayList->SetFocus(); // // Set property to handle clipboard change notifications // SetProp(NEXTCBVIEWER, HWND_BROADCAST); SetProp(NEXTCBVIEWER, SetClipboardViewer(*this)); Helper.ClipboardChanged = false; // // Restore previous cursor // HourGlassOff(oldCursor); return false; } // // // void TPasteSpecialDlg::CleanupWindow() { // // Free metafile of non-selected option // if (Helper.Link) TOleMetaPict::Free(Helper.MetaPictOD); else TOleMetaPict::Free(Helper.MetaPictLSD); // // Free listbox entries // FreeListData(*PasteList); FreeListData(*PasteLinkList); // // Free memory allocations // if (Helper.ObjDesc) GlobalFree(Helper.ObjDesc); if (Helper.LinkSrcDesc) GlobalFree(Helper.LinkSrcDesc); // // Remove ourselves from Clipboard notification chain // HWND hwndNextViewer; hwndNextViewer = (HWND)GetProp(NEXTCBVIEWER); if (hwndNextViewer != HWND_BROADCAST) { SetProp(NEXTCBVIEWER, HWND_BROADCAST); ChangeClipboardChain(*this, hwndNextViewer); } RemoveProp(NEXTCBVIEWER); } // // Handles User activating OK button by retrieving the current // selection and updating the TPasteSpecialInfo and TOcInitInfo // structures. // bool TPasteSpecialDlg::OleDlgOk() { // // Copy Helper information to Data structure // bool fDestAspectIcon = (Helper.Flags & psCheckDisplayAsIcon) ? true : false; Data->Flags = Helper.Flags; Data->SelectedIndex = Helper.SelectedIndex; Data->fLink = Helper.Link; if (Helper.Link) { if (Helper.SrcAspectIconLSD == fDestAspectIcon) Data->SizeL = Helper.SizeLLSD; else Data->SizeL.cx = Data->SizeL.cy = 0; } else { if (Helper.SrcAspectIconOD == fDestAspectIcon) Data->SizeL = Helper.SizeLOD; else Data->SizeL.cx = Data->SizeL.cy = 0; } // // Grab selected metafile // Data->MetaPict = IconImage->GetMetaPict(); // // Update TOcInitInfo data // if (Data->Flags & psCheckDisplayAsIcon) InitInfo.HIcon = (HICON)Data->MetaPict; LPDATAOBJECT pDataObj = Data->lpSrcDataObj; int i = Data->SelectedIndex; // // Retrieve selected clipboard format - If we have the BOleFormat handy, // go there since it's 'nearer' - otherwise use the Data data // CLIPFORMAT cf; if (pBOleEntries) cf = pBOleEntries[i].Id; else cf = Data->ArrayPasteEntries[i].fmtetc.cfFormat; if (cf == cfEmbeddedObject) { InitInfo.How = ihEmbed; InitInfo.Where = iwDataObject; InitInfo.Data = pDataObj; } else if (cf == cfEmbedSource) { InitInfo.How = ihEmbed; InitInfo.Where = iwDataObject; InitInfo.Data = pDataObj; InitInfo.Storage = 0; } else if (cf == cfLinkSource) { InitInfo.How = ihLink; InitInfo.Where = iwDataObject; InitInfo.Data = pDataObj; } else { STGMEDIUM medium; InitInfo.How = Data->fLink ? ihLink : ihEmbed; InitInfo.Where = iwHandle; InitInfo.Handle.DataFormat = cf; if (!Data->fLink) InitInfo.Handle.Data = GetData(pDataObj, cf, 0, DVASPECT_CONTENT, &medium); // // Release data object since we're only passing back a handle [not // the data object] // pDataObj->Release(); } return true; } // // Allocate and Initialize a TPasteSpecialData structure [used if no // TPasteSpecialData pointer was specified with constructing dialog] // bool TPasteSpecialDlg::GetDefaultPasteSpecialData() { // // Should be called only if user did not specify a TPasteSpecialInfo ptr. // PRECONDITION(Data == 0); // // Find container we'll be pasting in // IBContainer far* pCont = 0; if (InitInfo.Container) pCont = InitInfo.Container; else { TRACEX(OwlOleDlg, 1, "Container to paste in not found"); return false; } // // Find data consumer from container // IBDataConsumer far* pConsumer = 0; HRESULT hRes = pCont->QueryInterface(IID_IBDataConsumer, &(LPVOID)pConsumer); if (!SUCCEEDED(hRes)) { TRACEX(OwlOleDlg, 1, "Container data consumer not found"); return false; } else { pConsumer->Release(); } // // Check if clipboard is empty or (maybe) unavailable // LPDATAOBJECT pDataObj = 0; if (OleGetClipboard(&pDataObj) != S_OK) { TRACEX(OwlOleDlg, 1, "Clipboard's unavailable to paste from"); return false; } // // Retrieve acceptable formats // uint nAcceptableFormats = 0; nAcceptableFormats = pConsumer->CountFormats(); if (!nAcceptableFormats) { TRACEX(OwlOleDlg, 1, "No acceptable formats from consumer"); return false; } // // Allocate Dialog parameter information // pOleUIEntries = new TPasteEntry[nAcceptableFormats]; pBOleEntries = new TOcFormatInfo[nAcceptableFormats]; pBOleLinkEntries = new uint[nAcceptableFormats]; Data = new TData; DeleteData = true; // // Iterate through formats to initialize structures and track // linkable formats // uint nLinkableFormats = 0; for (int i=0; iGetFormat(i, &pBOleEntries[i]); InitFormatEtc(pOleUIEntries[i].fmtetc, pBOleEntries[i].Id, pBOleEntries[i].Medium); pOleUIEntries[i].lpstrFormatName = pBOleEntries[i].Name[0] ? OleStr(pBOleEntries[i].Name) : OleText("%s"); pOleUIEntries[i].lpstrResultText = pBOleEntries[i].ResultName[0] ? OleStr(pBOleEntries[i].ResultName) : OleText("%s"); pOleUIEntries[i].dwFlags = pBOleEntries[i].IsLinkable ? pfPaste : pfPasteOnly; if (pBOleEntries[i].Id == cfEmbeddedObject || pBOleEntries[i].Id == cfLinkSource || pBOleEntries[i].Id == cfEmbedSource ) { // // PasteOnly and EnableIcon are mutually exclusive // if (pOleUIEntries[i].dwFlags == pfPaste) pOleUIEntries[i].dwFlags |= pfEnableIcon; } if (pBOleEntries[i].IsLinkable) { pBOleLinkEntries[nLinkableFormats] = pBOleEntries[i].Id; DWORD flag; switch(nLinkableFormats) { case 0: flag = pfLinkType1; break; case 1: flag = pfLinkType2; break; case 2: flag = pfLinkType2; break; case 3: flag = pfLinkType2; break; case 4: flag = pfLinkType2; break; case 5: flag = pfLinkType2; break; case 6: flag = pfLinkType2; break; case 7: flag = pfLinkType2; break; } pOleUIEntries[i].dwFlags |= flag; nLinkableFormats++; } } // // Store all relevant PasteSpecial Initialization information // Data->ArrayPasteEntries = pOleUIEntries; Data->cPasteEntries = nAcceptableFormats; Data->lpSrcDataObj = pDataObj; Data->ArrayLinkTypes = pBOleLinkEntries; Data->cLinkTypes = nLinkableFormats; Data->cClsIdExclude = 0; return true; } // // Mark each entry in the PasteEntryList if its format is available from // the source IDataObject*. the dwScratchSpace field of each PasteEntry // is set to TRUE if available, else FALSE. // void TPasteSpecialDlg::MarkPasteEntryList(LPDATAOBJECT lpSrcDataObj, TPasteEntry far* lpPriorityList, int cEntries) { LPENUMFORMATETC lpEnumFmtEtc = NULL; FORMATETC rgfmtetc[MaxFormatEtc]; int i; HRESULT hrErr; long j, cFetched; // // Clear all marks // for (i = 0; i < cEntries; i++) { lpPriorityList[i].dwScratchSpace = FALSE; if (! lpPriorityList[i].fmtetc.cfFormat) { // // Caller wants this item always considered available // (by specifying a NULL format) // lpPriorityList[i].dwScratchSpace = TRUE; } else if (lpPriorityList[i].fmtetc.cfFormat == cfEmbeddedObject || lpPriorityList[i].fmtetc.cfFormat == cfEmbedSource || lpPriorityList[i].fmtetc.cfFormat == cfFileName) { // // If there is an OLE object format, then handle it // specially by calling OleQueryCreateFromData. the caller // need only specify one object type format. // TRACEX(OwlOleDlg, 1, "OleQueryCreateFromData called"); hrErr = OleQueryCreateFromData(lpSrcDataObj); if(NOERROR == hrErr) { lpPriorityList[i].dwScratchSpace = TRUE; } } else if (lpPriorityList[i].fmtetc.cfFormat == cfLinkSource) { // // If there is OLE 2.0 LinkSource format, then handle it // specially by calling OleQueryLinkFromData. // TRACEX(OwlOleDlg, 1, "OleQueryLinkFromData called"); hrErr = OleQueryLinkFromData(lpSrcDataObj); if(NOERROR == hrErr) { lpPriorityList[i].dwScratchSpace = TRUE; } } } TRACEX(OwlOleDlg, 1, "IDataObject::EnumFormatEtc called" ); hrErr = lpSrcDataObj->EnumFormatEtc(DATADIR_GET, (LPENUMFORMATETC FAR*)&lpEnumFmtEtc); if (hrErr != NOERROR) { TRACEX(OwlOleDlg, 1, "Unable to get format enumerator." ); return; } // // Enumerate the formats offered by the source // Loop over all formats offered by the source // cFetched = 0; memset(rgfmtetc, 0, sizeof(rgfmtetc[MaxFormatEtc])); if (lpEnumFmtEtc->Next(MaxFormatEtc, rgfmtetc, (ULONG*)&cFetched) == NOERROR || (cFetched > 0 && cFetched <= MaxFormatEtc) ) { for (j = 0; j < cFetched; j++) { for (i = 0; i < cEntries; i++) { if (! lpPriorityList[i].dwScratchSpace && CompareFormatEtc(&rgfmtetc[(int)j], &lpPriorityList[i].fmtetc)==0) { lpPriorityList[i].dwScratchSpace = TRUE; } } } } // // Clean up // if (lpEnumFmtEtc) lpEnumFmtEtc->Release(); } // // Toggles between Paste and PasteLink. NOTE: The Paste and PasteLink // ListBoxes are always invisible. The third visible listbox [displayListBox] // is filled with the contents of the Paste or PasteLink Listbox // bool TPasteSpecialDlg::TogglePasteType(TPasteSpecialFlags flag) { PRECONDITION(flag == psSelectPaste || flag == psSelectPasteLink); // // Skip if option's already selected // if (Helper.Flags & flag) return true; // // Update Flags // Helper.Flags= (Helper.Flags & ~(psSelectPaste | psSelectPasteLink)) | flag; // // Prevent icon display flashes // Activate(IconImage, false); // // Update Source and Icon displays and save index // TListBox *fromList = 0; if (Helper.Flags & psSelectPaste) { // // Set source of object in clipboard // SourceText->SetText(Helper.SourceOfDataOD); // // Update Icon is one's available // if (Helper.MetaPictOD) IconImage->SetMetaPict(Helper.MetaPictOD); // // Save current PasteLink index // Helper.PasteLinkListCurSel = DisplayList->GetSelIndex(); if (Helper.PasteLinkListCurSel == LB_ERR) Helper.PasteLinkListCurSel = 0; // // Clear link flag // Helper.Link = false; fromList = PasteList; } else { // PasteLink selected // // Update source of object in clipboard // SourceText->SetText(Helper.SourceOfDataLSD); // // Update Icon if one's available // if (Helper.MetaPictLSD) IconImage->SetMetaPict(Helper.MetaPictLSD); // // Save current Paste index // Helper.PasteListCurSel = DisplayList->GetSelIndex(); if (Helper.PasteListCurSel == LB_ERR) Helper.PasteListCurSel = 0; // // Set Link Flag // Helper.Link = true; fromList = PasteLinkList; } // // Refill display list // DisplayList->SetRedraw(false); DisplayList->ClearList(); int itemCount = fromList->GetCount(); TPointer buff = new char[GenericBufferLen]; for (int i=0; iGetString(buff, i); DisplayList->InsertString(buff, i); // // Store item data // DisplayList->SetItemData(i, fromList->GetItemData(i)); } // // Retore saved index // if (Helper.Flags & psSelectPaste) DisplayList->SetSelIndex(Helper.PasteListCurSel); else DisplayList->SetSelIndex(Helper.PasteLinkListCurSel); // // Update Display Listbox // DisplayList->SetRedraw(true); DisplayList->Invalidate(); DisplayList->UpdateWindow(); // // Focus on Display Listbox // DisplayList->SetFocus(); // // Allow updating of 'displayAsIcon', help result and bitmap // according to the new selection // ChangeListSelection(); return false; } // // Called when user changes the selection in the Listbox to enable/disable // 'DisplayAsIcon' and update the result text and bitmap. // void TPasteSpecialDlg::ChangeListSelection() { // // Update result text&bitmap and enable/disable 'DisplayAsIcon' // EnableDisplayAsIcon(); SetPasteSpecialHelpResults(); // // Retrieve selected index // int curSel = DisplayList->GetSelIndex(); if (curSel == LB_ERR) return; // // Retrieve item data associated with index // TPasteListItemData FAR* itemData; itemData = (TPasteListItemData FAR*)DisplayList->GetItemData(curSel); if ((long)itemData == LB_ERR) return; // // Save index // Helper.SelectedIndex = itemData->nPasteEntriesIndex; } // // Enables/Disables 'DisplayAsIcon' based on the current source selection // container's specification as outlined in table below: // //------------------------------------------------------------------------+ // Src. specifies | Src specifies | Contnr specifies| NET RESULTS | // DVASPECT_ICON | OLEMISC_ONLYICONIC | pfEnableIcon | Check - Enable | // ===============+====================+=================+================+ // N/A | N/A | N | N N | // ---------------+--------------------+-----------------+----------------| // N/A | Y | Y | Y N | // ---------------+--------------------+-----------------+----------------| // Y | N | Y | Y Y | // ---------------+--------------------+-----------------+----------------| // N | N | Y | N Y | // ---------------+--------------------+-----------------+----------------| // void TPasteSpecialDlg::EnableDisplayAsIcon() { bool srcOnlyIconic = (Helper.Link) ? Helper.SrcOnlyIconicLSD : Helper.SrcOnlyIconicOD; bool srcAspectIcon = (Helper.Link) ? Helper.SrcAspectIconLSD : Helper.SrcAspectIconOD; HGLOBAL metaPict = (Helper.Link) ? Helper.MetaPictLSD : Helper.MetaPictOD; bool cntrEnableIcon = false;; int index = DisplayList->GetSelIndex(); // // Get data of current selection // if (index != LB_ERR) { TPasteListItemData FAR* itemData; itemData = (TPasteListItemData FAR*)DisplayList->GetItemData(index); if ((long)itemData != LB_ERR) { cntrEnableIcon = itemData->fCntrEnableIcon; } else { cntrEnableIcon = false; } } // // If there's an icon available // if (metaPict) { // // Does container specify pfEnableIcon (OLEUIPASTE_ENABLEICON)? // if (!cntrEnableIcon) { // // Uncheck and disable 'DisplayAsIcon' // Helper.Flags &= ~psCheckDisplayAsIcon; DisplayAsIcon->Uncheck(); DisplayAsIcon->EnableWindow(false); // // Hide the icon image and 'ChangeIcon' // Activate(ChangeIcon, false); Activate(IconImage, false); } else if (srcOnlyIconic) { // Does SOURCE specify OLEMISC_ONLYICONIC // // Check and Disable 'DisplayAsIcon' // Helper.Flags |= psCheckDisplayAsIcon; DisplayAsIcon->Check(); DisplayAsIcon->EnableWindow(false); // // Show iconImage and ChangeIcon button // Activate(ChangeIcon, true); Activate(IconImage, true); } else if (srcAspectIcon) { // Does SOURCE specify DVASPECT_ICON // // Check and Enable 'DisplayAsIcon' // Helper.Flags |= psCheckDisplayAsIcon; DisplayAsIcon->Check(); DisplayAsIcon->EnableWindow(true); // // Show iconImage and ChangeIcon button // Activate(ChangeIcon, true); Activate(IconImage, true); } else { // // Uncheck and Enable DisplayAsIcon // Helper.Flags &= ~psCheckDisplayAsIcon; DisplayAsIcon->Uncheck(); DisplayAsIcon->EnableWindow(true); // // Hide IconImage and ChangeIcon button // Activate(ChangeIcon, false); Activate(IconImage, false); } } else { // No Icon is available // // Uncheck and Disable displayAsIcon // Helper.Flags &= ~psCheckDisplayAsIcon; DisplayAsIcon->Uncheck(); DisplayAsIcon->EnableWindow(false); // // Hide iconImage and ChangeIcon button // Activate(ChangeIcon, false); Activate(IconImage, false); } } // // Updates the flags; Hides/Shows the IconImage control and the // ChangeIcon Button - Also updates the help result text and bitmap. // void TPasteSpecialDlg::ToggleDisplayAsIcon() { bool checked = IsDlgButtonChecked(IDC_DISPLAYASICON) ? true : false; // // Update Flags // if (checked) Helper.Flags |= psCheckDisplayAsIcon; else Helper.Flags &= ~psCheckDisplayAsIcon; // // Set result text and bitmap // SetPasteSpecialHelpResults(); // // Show/hide Icon and ChgIcon button // Activate(IconImage, checked); Activate(ChangeIcon, checked); } // // // bool TPasteSpecialDlg::HasPercentS(const char far* str) { if (!str) return false; // // Copy passed string to local buffer // TPointer buff = new char[GenericBufferLen]; strcpy(buff, str); char* pBuff = buff; while(*pBuff) { if (*pBuff == '%') { pBuff = AnsiNext(pBuff); if (*pBuff == 's') { return true; } else if (*pBuff == '%') { pBuff = AnsiNext(pBuff); } } else { pBuff = AnsiNext(pBuff); } } return false; } // // // void TPasteSpecialDlg::SetPasteSpecialHelpResults() { int selIndex = DisplayList->GetSelIndex(); if (selIndex == LB_ERR) { TRACEX(OwlOleDlg, 1, "No item selected to display HelpResults"); return; } TPasteListItemData FAR *lpItemData; lpItemData = (TPasteListItemData FAR*)DisplayList->GetItemData(selIndex); if ((LRESULT)lpItemData == LB_ERR) { TRACEX(OwlOleDlg, 1, "No PasteListItemData found at " << selIndex); return; } int nPasteEntriesIndex = lpItemData->nPasteEntriesIndex; bool fIsObject = HasPercentS( Data->ArrayPasteEntries[nPasteEntriesIndex].lpstrFormatName ); bool fDisplayAsIcon = (Helper.Flags & psCheckDisplayAsIcon) ? true : false; LPSTR lpszFullUserTypeName = Helper.Link ? Helper.FullUserTypeNameLSD : Helper.FullUserTypeNameOD; LPSTR lpszInsert = lpszFullUserTypeName; uint iString = 0; uint iImage = 0; if (Helper.Flags & psSelectPaste) { if (fIsObject) { iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT; iImage = fDisplayAsIcon ? riEmbedIcon : riEmbed; lpszInsert = Helper.AppName; } else { iString = IDS_PSPASTEDATA; iImage = riPaste; } } else if (Helper.Flags & psSelectPasteLink) { if (fIsObject) { iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT; iImage = fDisplayAsIcon ? riLinkIcon : riLink; } else { iString = IDS_PSPASTELINKDATA; iImage = riLink; } } else { TRACEX(OwlOleDlg, 1, "Non-OLE object - Error!"); iString = IDS_PSNONOLE; iImage = riPaste; } // // Allocator buffers to build help text // TPointer pstr1 = new char[GenericBufferLen]; TPointer pstr2 = new char[GenericBufferLen]; TPointer pstr3 = new char[GenericBufferLen]; TPointer pstr4 = new char[GenericBufferLen]; // // Build String from resource. // *((char*)pstr1) = 0; // Default to empty string if (GetModule()->LoadString(iString, (LPSTR)(char*)pstr1, GenericBufferLen)) { wsprintf((LPSTR)(char*)pstr3, Data->ArrayPasteEntries[nPasteEntriesIndex].lpstrResultText, lpszInsert); wsprintf((LPSTR)(char*)pstr4, (LPSTR)(char*)pstr1, (LPSTR)(char*)pstr3); strcpy(pstr1, pstr4); } // // Update Display // ResultText->SetText(pstr1); ResultImage->SetBitmapIndex(iImage); } // // Adds the name of an object to the Paste or PasteLink listboxes. // bool TPasteSpecialDlg::AddPasteListItem(TListBox &list, bool insertFirst, int pasteEntryIndex, const char far* fullUserTypeName) { TPointer buff = new char[GenericBufferLen]; TPasteListItemData FAR* pItemData = new TPasteListItemData; // // Initialize PasteList Item Data // pItemData->nPasteEntriesIndex = pasteEntryIndex; if (Data->ArrayPasteEntries[pasteEntryIndex].dwFlags & pfEnableIcon) { pItemData->fCntrEnableIcon = TRUE; } else { pItemData->fCntrEnableIcon = FALSE; } // // Build the listbox entry string // wsprintf((LPSTR)(char*)buff, Data->ArrayPasteEntries[pasteEntryIndex].lpstrFormatName, (LPSTR)fullUserTypeName); // // Add data if it's not a duplicate // if (list.FindString(buff, 0) == LB_ERR) { int index = insertFirst ? list.InsertString(buff, 0) : list.AddString(buff); list.SetItemData(index, (LPARAM)pItemData); } else { delete pItemData; } return true; } // // Fill the (invisible) Paste listbox with the formats offered by the // Clipboard object and asked form by the container // bool TPasteSpecialDlg::FillPasteList() { int items = 0; int defFormat = -1; bool insertFirst = false; bool tryObjFmt = false; bool exclude = false; // // Loop through target's priority list of formats // for (int i=0; icPasteEntries; i++) { if (Data->ArrayPasteEntries[i].dwFlags != pfPasteOnly && !(Data->ArrayPasteEntries[i].dwFlags & pfPaste)) continue; insertFirst = false; if (Data->ArrayPasteEntries[i].fmtetc.cfFormat == cfFileName || Data->ArrayPasteEntries[i].fmtetc.cfFormat == cfEmbeddedObject || Data->ArrayPasteEntries[i].fmtetc.cfFormat == cfEmbedSource) { if (!tryObjFmt) { tryObjFmt = true; // Only use first object format insertFirst = true; // OLE obj. format should always be first // // Check exclusion list // exclude = false; for( int j=0; j < (int)Data->cClsIdExclude; j++) { if (IsEqualCLSID(Helper.ClsIdOD, *(Data->lpClsIdExclude+j))) { exclude = true; break; } } // // Skip object if in exclusion list // if (exclude) continue; } else { // // Already added an object format to list // continue; } } // // Ass to list if entry is marked true // if (Data->ArrayPasteEntries[i].dwScratchSpace) { if (defFormat < 0) { defFormat = insertFirst ? 0 : items; } else if (insertFirst) { defFormat++; } if (AddPasteListItem(*PasteList, insertFirst, i, Helper.FullUserTypeNameOD)) { items++; } else { FreeListData(*PasteList); return false; } } } // // Initialize select to first matching format // if (defFormat >= 0) Helper.PasteListCurSel = defFormat; return (items > 0) ? true : false; } // // Fill the (invisible) PasteLink listbox with the formats offered by the // Clipboard object and asked form by the container // bool TPasteSpecialDlg::FillPasteLinkList() { int items = 0; int defFormat = -1; bool tryObjFmt = false; bool insertFirst = true; LPDATAOBJECT lpSrcDataObj = Data->lpSrcDataObj; FORMATETC fmtetc; memset(&fmtetc, 0, sizeof(fmtetc)); // // Array of flags indicating which link types are supported // bool arrayLinkTypesSupported[MaxLinkTypes]; bool linkTypeSupported = false; for (int i=0; icLinkTypes; i++) { if (Data->ArrayLinkTypes[i] == cfLinkSource) { TRACEX(OwlOleDlg, 1, "Calling OleQueryLinkFromData."); if (OleQueryLinkFromData(lpSrcDataObj) == S_OK) { arrayLinkTypesSupported[i] = true; linkTypeSupported = true; } else { arrayLinkTypesSupported[i] = false; }; } else { fmtetc.cfFormat = Data->ArrayLinkTypes[i]; fmtetc.dwAspect = DVASPECT_CONTENT; fmtetc.tymed = 0xFFFFFFFFL; // All tymed values fmtetc.lindex = -1; TRACEX(OwlOleDlg, 1, "IDataObject::QueryGetData called."); if (lpSrcDataObj->QueryGetData(&fmtetc) == S_OK) { arrayLinkTypesSupported[i] = true; linkTypeSupported = true; } else { arrayLinkTypesSupported[i] = false; } } } // // Check if link types are offered by SourceDataObject // if (!linkTypeSupported) { TRACEX(OwlOleDlg, 1, "No link types are offered by data source."); items = 0; return false; } // // Iterate through acceptable formats // for(i=0; icPasteEntries; i++) { linkTypeSupported = false; // // Does container accept an link type offered by source object // if (Data->ArrayPasteEntries[i].dwFlags & pfLinkAnyType) linkTypeSupported = true; else { // // Checked if link types offered by source are acceptable // int j=0; uint32 pasteFlag; for (pasteFlag = pfLinkType1, j=0; j < Data->cLinkTypes; pasteFlag *=2, j++) { if ((Data->ArrayPasteEntries[i].dwFlags & pasteFlag) && arrayLinkTypesSupported[i]) { linkTypeSupported = true; break; } } insertFirst = false; if ((Data->ArrayPasteEntries[i].fmtetc.cfFormat == cfFileName) || (Data->ArrayPasteEntries[i].fmtetc.cfFormat == cfLinkSource)) { if (!tryObjFmt) { tryObjFmt = true; // Only use first object format insertFirst = true; // OLE object format should be first } else { continue; // Already added object format to list } } // // Add to list if entry's marked true // if (linkTypeSupported && Data->ArrayPasteEntries[i].dwScratchSpace) { if (defFormat < 0) { defFormat = insertFirst ? 0 : items; } else if (insertFirst) { defFormat++; } if (AddPasteListItem(*PasteLinkList, insertFirst, i, Helper.FullUserTypeNameLSD)) { items++; } else { FreeListData(*PasteLinkList); return false; } } } } // // Initialize selection to first matching format // if (defFormat >= 0) Helper.PasteLinkListCurSel = defFormat; items = PasteLinkList->GetCount(); return (items > 0) ? true : false; } // // Frees PasteListItem data memory associated with each listbox entry. // void TPasteSpecialDlg::FreeListData(TListBox &list) { TPasteListItemData FAR *lpItemData; int items = list.GetCount(); for (int i=0; i _cln1(&data); data.MetaPict = IconImage->GetMetaPict(); data.Flags = ciSelectCurrent; data.ClsId = Helper.Link ? Helper.ClsIdLSD : Helper.ClsIdOD; if (Helper.Flags & ioShowHelp) data.Flags |= ciShowHelp; // // Allocate dialog and execute // TChangeIconDlg &chgIconDlg = *new TChangeIconDlg(this, data); TPointer _cln2(&chgIconDlg); if (chgIconDlg.Execute() == IDOK){ // // Update display with new icon // IconImage->SetMetaPict(data.MetaPict); // // Save away new icon // if (Helper.Link) Helper.MetaPictLSD = data.MetaPict; else Helper.MetaPictOD = data.MetaPict; } } CATCH( (xmsg& msg){ GetModule()->Error(msg, 0); } ) } // // Switches to the PasteList // void TPasteSpecialDlg::PasteClicked() { TogglePasteType(psSelectPaste); } // // Switches to the PasteLink List // void TPasteSpecialDlg::PasteLinkClicked() { TogglePasteType(psSelectPasteLink); } // // Handles request to display Paste/Link as Icon // void TPasteSpecialDlg::DisplayAsIconClicked() { ToggleDisplayAsIcon(); } // // Handles change in selection of items to paste/pasteLink // void TPasteSpecialDlg::DisplayListSelChange() { ChangeListSelection(); } // // A double click on the Paste/PasteLink listbox is treated // similar to hitting the OK button. // void TPasteSpecialDlg::DisplayListDblClk() { SendNotification(IDOK, BN_CLICKED, GetDlgItem(IDOK)); } // // Handles notification that Clipboard content has changed. // This basically means bad news since the data we're currently // displaying to the user for Pasting/PasteLinking is now inaccurate. // void TPasteSpecialDlg::EvDrawClipboard() { HWND hwndSaved = (HWND)GetProp(NEXTCBVIEWER); if (hwndSaved == HWND_BROADCAST) return; // // Take ourselves out of the loop // SetProp(NEXTCBVIEWER, HWND_BROADCAST); ::ChangeClipboardChain(*this, hwndSaved); // // Bring down the dialog // } // // Handle notification that a Window is being removed from // Clipboard chain. // void TPasteSpecialDlg::EvChangeCBChain(HWND hwndRemoved, HWND hwndNext) { // // If the one after us is going, save the one following it. // HWND hwndSaved = (HWND)GetProp(NEXTCBVIEWER); if (hwndRemoved == hwndSaved) { SetProp(NEXTCBVIEWER, hwndNext); // // Otherwise pass the buck along // } else if (hwndSaved && hwndSaved != HWND_BROADCAST) { ::SendMessage(hwndSaved, WM_CHANGECBCHAIN, (WPARAM)hwndRemoved, (LPARAM)hwndNext); } }