/// <summary> /// Helper function to populate the contents of a FORMATETC structure /// using the passed clipboard format and type(s). /// </summary> /// <param name="lindex">Index of item to retreive</param> /// <param name="clipFormat">Name of clipboard format requested</param> /// <param name="types">type(s) requested</param> /// <param name="formatEtc">FORMATETC structure to be populated</param> public static void PopulateFORMATETC( int lindex, string clipFormat, TYMED types, ref FORMATETC formatEtc) { // populate contents of FORMATETC structure formatEtc.cfFormat = (ushort)User32.RegisterClipboardFormat(clipFormat); formatEtc.ptd = IntPtr.Zero; formatEtc.dwAspect = DVASPECT.CONTENT; formatEtc.lindex = lindex; formatEtc.tymed = types; }
/// <summary> /// Renders the data described in a FORMATETC structure and transfers it /// through the STGMEDIUM structure. /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure that defines /// the format, medium, and target device to use when passing the data. It is /// possible to specify more than one medium by using the Boolean OR operator, /// allowing the method to choose the best medium among those specified</param> /// <param name="pMedium">Pointer to the STGMEDIUM structure that indicates /// the storage medium containing the returned data through its tymed member, /// and the responsibility for releasing the medium through the value of its /// pUnkForRelease member. If pUnkForRelease is NULL, the receiver of the medium /// is responsible for releasing it; otherwise, pUnkForRelease points to the /// IUnknown on the appropriate object so its Release method can be called. /// The medium must be allocated and filled in by IDataObject::GetData</param> public int GetData(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium) { // check to see if we have data of the requested type int dataFormatIndex; int result = FindDataFormat(ref pFormatEtc, out dataFormatIndex); // if we do then return a clone of it (returns error code if an // error occurs during the clone) if (result == HRESULT.S_OK) { // lookup the entry OleDataEntry dataEntry = (OleDataEntry)oleDataEntries[dataFormatIndex]; // clone the storage and return return CloneStgMedium(dataEntry.stgm, ref pMedium); } // don't have the data, return the error code passed back to us // from FindDataFormat else { return result; } }
/// <summary> /// Provides data to the client as it becomes available during asynchronous bind operations. /// </summary> void IBindStatusCallback.OnDataAvailable(BSCF grfBSCF, uint dwSize, ref FORMATETC pformatetc, ref STGMEDIUM pstgmed) { // never called by URLDownloadToFile LOG_UN("IBindStatusCallback", "OnDataAvailable"); }
/// <summary> /// Helper function to populate the contents of a FORMATETC structure /// using the passed clipboard format and type(s). /// </summary> /// <param name="clipFormat">Name of clipboard format requested</param> /// <param name="types">type(s) requested</param> /// <param name="formatEtc">FORMATETC structure to be populated</param> public static void PopulateFORMATETC( string clipFormat, TYMED types, ref FORMATETC formatEtc) { OleDataObjectHelper.PopulateFORMATETC(-1, clipFormat, types, ref formatEtc); }
/// <summary> /// Extract the date from within an OleDataObject. Pass in the requested /// clipboard format and type (or types ORed together) that you want /// the data in. The method will return an OleStgMedium for the type(s) /// requested if it is available, otherwise it will return null. /// If a single type is requested then the return value can be safely /// cast to the requested OleStgMedium subclasss. If multiple types /// are requested then the return value will represent the object's /// preferred storage representation and client code will need to use /// the 'is' operator to determine what type was returned. /// </summary> /// <param name="lindex">Index of item to retreive</param> /// <param name="clipFormat">Name of clipboard format requested</param> /// <param name="types">type(s) requested</param> /// <returns>OleStgMedium instance if format and requested storage type /// are available, otherwise null</returns> public OleStgMedium GetData(int lindex, string clipFormat, TYMED types) { // populate contents of FORMATETC structure FORMATETC formatEtc = new FORMATETC(); OleDataObjectHelper.PopulateFORMATETC(lindex, clipFormat, types, ref formatEtc); // attempt to get the data using the requested format STGMEDIUM stgMedium = new STGMEDIUM(); if (m_dataObject != null) { int result = m_dataObject.GetData(ref formatEtc, ref stgMedium); // check for errors if (result != HRESULT.S_OK) { // data format not supported (expected error condition) if (result == DV_E.FORMATETC) return null; // unexpected error condition else Marshal.ThrowExceptionForHR(result); } // return the correct OleStgMedium subclass depending upon the type switch (stgMedium.tymed) { case TYMED.NULL: return null; case TYMED.HGLOBAL: return new OleStgMediumHGLOBAL(stgMedium); case TYMED.FILE: return new OleStgMediumFILE(stgMedium); case TYMED.GDI: return new OleStgMediumGDI(stgMedium); case TYMED.MFPICT: return new OleStgMediumMFPICT(stgMedium); case TYMED.ENHMF: return new OleStgMediumENHMF(stgMedium); case TYMED.ISTREAM: return new OleStgMediumISTREAM(stgMedium); case TYMED.ISTORAGE: return new OleStgMediumISTORAGE(stgMedium); default: Debug.Assert(false, "Invalid TYMED value"); return null; } } else return null; }
/// <summary> /// Determines whether the data object is capable of rendering the data described /// in the passed clipboard format and storage type(s). Objects attempting a /// paste or drop operation can call this method before calling GetData /// to get an indication of whether the operation may be successful /// </summary> /// <param name="clipFormat">Name of clipboard format requested</param> /// <param name="types">type(s) requested</param> /// <returns>true if the subseqent call to GetData would likely be /// successful, otherwise false</returns> public bool QueryGetData(string clipFormat, TYMED types) { // populate contents of FORMATETC structure FORMATETC formatEtc = new FORMATETC(); OleDataObjectHelper.PopulateFORMATETC(clipFormat, types, ref formatEtc); // try to successfully query for the data int result = m_dataObject.QueryGetData(ref formatEtc); // data is available if (result == HRESULT.S_OK) return true; // data is not available else if (result == DV_E.FORMATETC) return false; // unexpected error else { Marshal.ThrowExceptionForHR(result); return false; // keep compiler happy } }
/// <summary> /// Get the next celt entries from the enumeration /// </summary> /// <param name="celt">entries to fetch</param> /// <param name="rgelt">array to fetch into (allocated by caller)</param> /// <param name="pceltFetched">number of entries fetched</param> /// <returns>S_OK if celt entries are supplied, otherwise S_FALSE</returns> public int Next(uint celt, FORMATETC[] rgelt, IntPtr pceltFetched) { // see how many of the requested items we can serve int itemsRequested = Convert.ToInt32(celt); int itemsToReturn = Math.Min(itemsRequested, oleDataEntries.Count - (currentItem + 1)); // copy the format structures into the caller's array of structures for (int i = 0; i < itemsToReturn; i++) { OleDataEntry dataEntry = (OleDataEntry)oleDataEntries[++currentItem]; rgelt[i] = dataEntry.format; } // update the fetch parameter if requested if (pceltFetched != IntPtr.Zero) Marshal.WriteInt32(pceltFetched, itemsToReturn); // return the correct status code depending upon whether we // returned all of the items requested if (itemsToReturn == itemsRequested) return HRESULT.S_OK; else return HRESULT.S_FALSE; }
/// <summary> /// Private helper method to find an existing data format /// </summary> /// <param name="pFormatEtc">format spec</param> /// <param name="dataIndex">returned index of data format if we've got it, /// -1 if we don't have it</param> /// <returns>S_OK if the data format was found, otherwise the appropriate /// OLE error code (see QueryGetData for documentation on error codes)</returns> private int FindDataFormat(ref FORMATETC pFormatEtc, out int dataIndex) { // default to data not found dataIndex = -1; // no support for comparing target devices if (pFormatEtc.ptd != IntPtr.Zero) return DV_E.TARGETDEVICE; // iterate through our FORMATETC structures to see if one matches // this format spec for (int i = 0; i < oleDataEntries.Count; i++) { // get the data entry OleDataEntry dataEntry = (OleDataEntry)oleDataEntries[i]; // check for matching format spec if ((dataEntry.format.cfFormat == pFormatEtc.cfFormat) && (dataEntry.format.dwAspect == pFormatEtc.dwAspect) && (dataEntry.format.lindex == pFormatEtc.lindex)) { // check for matching data type if ((dataEntry.format.tymed & pFormatEtc.tymed) > 0) { dataIndex = i; return HRESULT.S_OK; } else return DV_E.TYMED; } } // no matching format found return DV_E.FORMATETC; }
public OleDataEntry(FORMATETC fmt, STGMEDIUM stg) { format = fmt; stgm = stg; }
/// <summary> /// Creates a connection between a data object and an advise sink so the /// advise sink can receive notifications of changes in the data object /// </summary> /// <param name="pFormatEtc">Pointer to a FORMATETC structure that defines the /// format, target device, aspect, and medium that will be used for future /// notifications. For example, one sink may want to know only when the bitmap /// representation of the data in the data object changes. Another sink may be /// interested in only the metafile format of the same object. Each advise sink /// is notified when the data of interest changes. This data is passed back to /// the advise sink when notification occurs</param> /// <param name="advf">DWORD that specifies a group of flags for controlling /// the advisory connection. Valid values are from the enumeration ADVF. /// However, only some of the possible ADVF values are relevant for this /// method (see MSDN documentation for more details).</param> /// <param name="pAdvSink">Pointer to the IAdviseSink interface on the advisory /// sink that will receive the change notification</param> /// <param name="pdwConnection">Pointer to a DWORD token that identifies this /// connection. You can use this token later to delete the advisory connection /// (by passing it to IDataObject::DUnadvise). If this value is zero, the /// connection was not established</param> public int DAdvise(ref FORMATETC pFormatEtc, uint advf, IntPtr pAdvSink, ref uint pdwConnection) { return OLE_E.ADVISENOTSUPPORTED; }
/// <summary> /// Provides the source data object with data described by a FORMATETC /// structure and an STGMEDIUM structure /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure defining the /// format used by the data object when interpreting the data contained in the /// storage medium</param> /// <param name="pMedium">Pointer to the STGMEDIUM structure defining the storage /// medium in which the data is being passed</param> /// <param name="fRelease">If TRUE, the data object called, which implements /// IDataObject::SetData, owns the storage medium after the call returns. This /// means it must free the medium after it has been used by calling the /// ReleaseStgMedium function. If FALSE, the caller retains ownership of the /// storage medium and the data object called uses the storage medium for the /// duration of the call only</param> public int SetData(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium, bool fRelease) { // check and see if we have an existing format of this type int dataFormatIndex; int result = FindDataFormat(ref pFormatEtc, out dataFormatIndex); // if we have an existing format of this type then free it and // remove it from the list if (result == HRESULT.S_OK) { OleDataEntry oleDataEntry = (OleDataEntry)oleDataEntries[dataFormatIndex]; Ole32.ReleaseStgMedium(ref oleDataEntry.stgm); oleDataEntries.RemoveAt(dataFormatIndex); } // create an entry to add to our internal list OleDataEntry dataEntry; // if the caller is releasing the data that is being set then just // copy bit for bit (we are now responsible for freeing the storage) if (fRelease) { dataEntry = new OleDataEntry(pFormatEtc, pMedium); } // if the caller is not releasing the data object to us then // we only get to use it for the duration of the call -- we need // to therefore clone the storage so that we have our own // copy/reference else { // attempt to clone the storage medium STGMEDIUM mediumClone = new STGMEDIUM(); result = CloneStgMedium(pMedium, ref mediumClone); if (result != HRESULT.S_OK) return result; // cloned it, initialize the data entry using the cloned storage dataEntry = new OleDataEntry(pFormatEtc, mediumClone); } // add the entry to our internal list oleDataEntries.Add(dataEntry); // return OK return HRESULT.S_OK; }
/// <summary> /// Provides a standard FORMATETC structure that is logically equivalent /// to one that is more complex. You use this method to determine whether /// two different FORMATETC structures would return the same data, removing /// the need for duplicate rendering /// </summary> /// <param name="pFormatEtcIn">Pointer to the FORMATETC structure that /// defines the format, medium, and target device that the caller would /// like to use to retrieve data in a subsequent call such as /// IDataObject::GetData. The TYMED member is not significant in this case /// and should be ignored</param> /// <param name="pFormatEtcOut">Pointer to a FORMATETC structure that contains /// the most general information possible for a specific rendering, making it /// canonically equivalent to pFormatetcIn. The caller must allocate this /// structure and the GetCanonicalFormatEtc method must fill in the data. /// To retrieve data in a subsequent call like IDataObject::GetData, the /// caller uses the supplied value of pFormatetcOut, unless the value supplied /// is NULL. This value is NULL if the method returns DATA_S_SAMEFORMATETC. /// The TYMED member is not significant in this case and should be ignored</param> /// <returns>S_OK if the logically equivilant structure was provided, /// otherwise returns DATA_S_SAMEFORMATETC indicating the structures /// are the same (in this case pFormatEtcOut is NULL)</returns> public int GetCanonicalFormatEtc(ref FORMATETC pFormatEtcIn, ref FORMATETC pFormatEtcOut) { return DATA_S.SAMEFORMATETC; }
/// <summary> /// Determines whether the data object is capable of rendering the data /// described in the FORMATETC structure. /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure defining /// the format, medium, and target device to use for the query</param> public int QueryGetData(ref FORMATETC pFormatEtc) { int dataFormatIndex; return FindDataFormat(ref pFormatEtc, out dataFormatIndex); }
/// <summary> /// Renders the data described in a FORMATETC structure and transfers it /// through the STGMEDIUM structure allocated by the caller. /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure that defines /// the format, medium, and target device to use when passing the data. It is /// possible to specify more than one medium by using the Boolean OR operator, /// allowing the method to choose the best medium among those specified</param> /// <param name="pMedium">Pointer to the STGMEDIUM structure that defines the /// storage medium containing the data being transferred. The medium must be /// allocated by the caller and filled in by IDataObject::GetDataHere. The /// caller must also free the medium. The implementation of this method must /// always supply a value of NULL for the punkForRelease member of the /// STGMEDIUM structure to which this parameter points</param> public int GetDataHere(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium) { // For now we don't support this method. MFC uses the internal method // AfxCopyStgMedium to implement this -- if we absolutely positively // need to suppport this then we should base are implementation on // that code (source is the file atlmfc\src\mfc\olemisc.cpp) return HRESULT.E_NOTIMPL; }