Mercurial > foo_out_sdl
view foosdk/sdk/libPPUI/IDataObjectUtils.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line source
#pragma once #include <shlobj.h> #include <ShlDisp.h> // IAsyncOperation #include "pp-COM-macros.h" namespace IDataObjectUtils { class ReleaseStgMediumScope { public: ReleaseStgMediumScope(STGMEDIUM * medium) : m_medium(medium) {} ~ReleaseStgMediumScope() {if (m_medium != NULL) ReleaseStgMedium(m_medium);} private: STGMEDIUM * m_medium; PFC_CLASS_NOT_COPYABLE_EX(ReleaseStgMediumScope) }; static constexpr DWORD DataBlockToSTGMEDIUM_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL; static constexpr DWORD ExtractDataObjectContent_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL; HRESULT DataBlockToSTGMEDIUM(const void * blockPtr, t_size blockSize, STGMEDIUM * medium, DWORD tymed, bool bHere) throw(); HGLOBAL HGlobalFromMemblock(const void * ptr,t_size size); HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, pfc::array_t<t_uint8> & out); HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, pfc::array_t<t_uint8> & out); HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index); HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format); HRESULT ExtractDataObjectString(pfc::com_ptr_t<IDataObject> obj, pfc::string_base & out); HRESULT SetDataObjectString(pfc::com_ptr_t<IDataObject> obj, const char * str); HRESULT SetDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, const void * data, t_size dataSize); HRESULT STGMEDIUMToDataBlock(const STGMEDIUM & med, pfc::array_t<t_uint8> & out); HRESULT ExtractDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD & val); HRESULT SetDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD val); HRESULT PasteSucceeded(pfc::com_ptr_t<IDataObject> obj, DWORD effect); class comparator_FORMATETC { public: static int compare(const FORMATETC & v1, const FORMATETC & v2) { int val; val = pfc::compare_t(v1.cfFormat,v2.cfFormat); if (val != 0) return val; val = pfc::compare_t(v1.dwAspect,v2.dwAspect); if (val != 0) return val; val = pfc::compare_t(v1.lindex, v2.lindex ); if (val != 0) return val; return 0; } }; class CDataObjectBase : public IDataObject { public: COM_QI_SIMPLE(IDataObject) HRESULT STDMETHODCALLTYPE GetData(FORMATETC * formatetc, STGMEDIUM * medium) override { return GetData_internal(formatetc,medium,false); } HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC * formatetc, STGMEDIUM * medium) override { return GetData_internal(formatetc,medium,true); } HRESULT STDMETHODCALLTYPE QueryGetData(FORMATETC * formatetc) override { if (formatetc == NULL) return E_INVALIDARG; if ((DataBlockToSTGMEDIUM_SupportedTymeds & formatetc->tymed) == 0) return DV_E_TYMED; try { return RenderDataTest(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex); } PP_COM_CATCH; } HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(FORMATETC * in, FORMATETC * out) override { //check this again if (in == NULL || out == NULL) return E_INVALIDARG; *out = *in; return DATA_S_SAMEFORMATETC; } HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD dwDirection,IEnumFORMATETC ** ppenumFormatetc) override { if (dwDirection == DATADIR_GET) { if (ppenumFormatetc == NULL) return E_INVALIDARG; return CreateIEnumFORMATETC(ppenumFormatetc); } else if (dwDirection == DATADIR_SET) { return E_NOTIMPL; } else { return E_INVALIDARG; } } HRESULT STDMETHODCALLTYPE SetData(FORMATETC * pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) override { try { ReleaseStgMediumScope relScope(fRelease ? pmedium : NULL); if (pFormatetc == NULL || pmedium == NULL) return E_INVALIDARG; /*TCHAR buf[256]; if (GetClipboardFormatName(pFormatetc->cfFormat,buf,PFC_TABSIZE(buf)) > 0) { buf[PFC_TABSIZE(buf)-1] = 0; OutputDebugString(TEXT("SetData: ")); OutputDebugString(buf); OutputDebugString(TEXT("\n")); } else { OutputDebugString(TEXT("SetData: unknown clipboard format.\n")); }*/ pfc::array_t<t_uint8> temp; HRESULT state = STGMEDIUMToDataBlock(*pmedium,temp); if (FAILED(state)) return state; m_entries.set(*pFormatetc,temp); return S_OK; } PP_COM_CATCH; } HRESULT STDMETHODCALLTYPE DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection) override { (void)pFormatetc; (void)advf; (void)pAdvSink; (void)pdwConnection; return OLE_E_ADVISENOTSUPPORTED; } HRESULT STDMETHODCALLTYPE DUnadvise(DWORD dwConnection) override { (void)dwConnection; return OLE_E_ADVISENOTSUPPORTED; } HRESULT STDMETHODCALLTYPE EnumDAdvise(IEnumSTATDATA** ppenumAdvise) override { (void)ppenumAdvise; return OLE_E_ADVISENOTSUPPORTED; } protected: typedef pfc::array_t<uint8_t> data_t; virtual HRESULT RenderData(UINT format,DWORD aspect,LONG dataIndex, data_t & out) const { FORMATETC fmt = {}; fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex; const pfc::array_t<t_uint8> * entry = m_entries.query_ptr(fmt); if (entry != NULL) { out = * entry; return S_OK; } return DV_E_FORMATETC; } virtual HRESULT RenderDataTest(UINT format,DWORD aspect,LONG dataIndex) const { FORMATETC fmt = {}; fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex; if (m_entries.have_item(fmt)) return S_OK; return DV_E_FORMATETC; } typedef pfc::list_base_t<FORMATETC> TFormatList; static void AddFormat(TFormatList & out,UINT code) { FORMATETC fmt = {}; fmt.dwAspect = DVASPECT_CONTENT; fmt.lindex = -1; fmt.cfFormat = (CLIPFORMAT)code; for(t_size medWalk = 0; medWalk < 32; ++medWalk) { const DWORD med = 1 << medWalk; if ((DataBlockToSTGMEDIUM_SupportedTymeds & med) != 0) { fmt.tymed = med; out.add_item(fmt); } } } virtual void EnumFormats(TFormatList & out) const { pfc::avltree_t<UINT> formats; for(auto walk = m_entries.cfirst(); walk.is_valid(); ++walk) { formats.add_item( walk->m_key.cfFormat ); } for(auto walk = formats.cfirst(); walk.is_valid(); ++walk) { AddFormat(out, *walk); } } HRESULT CreateIEnumFORMATETC(IEnumFORMATETC ** outptr) const throw() { try { pfc::list_t<FORMATETC> out; EnumFormats(out); return SHCreateStdEnumFmtEtc((UINT)out.get_count(), out.get_ptr(), outptr); } PP_COM_CATCH; } private: HRESULT GetData_internal(FORMATETC * formatetc, STGMEDIUM * medium,bool bHere) { if (formatetc == NULL || medium == NULL) return E_INVALIDARG; try { data_t out; HRESULT hr = RenderData(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex,out); if (FAILED(hr)) return hr; return DataBlockToSTGMEDIUM(out.get_ptr(),out.get_size(),medium,formatetc->tymed,bHere); } PP_COM_CATCH; } typedef pfc::map_t<FORMATETC, pfc::array_t<t_uint8>, comparator_FORMATETC> t_entries; t_entries m_entries; }; #ifdef __IDataObjectAsyncCapability_INTERFACE_DEFINED__ typedef IDataObjectAsyncCapability IDataObjectAsyncCapability_t; #else typedef IAsyncOperation IDataObjectAsyncCapability_t; #endif class CAsyncDataObjectBase : public CDataObjectBase, public IDataObjectAsyncCapability_t { BOOL m_inOperation = FALSE; BOOL m_asyncMode = TRUE; protected: COM_QI_BEGIN() COM_QI_CHAIN(CDataObjectBase) COM_QI_ENTRY(IDataObjectAsyncCapability_t) COM_QI_END() public: HRESULT STDMETHODCALLTYPE SetAsyncMode(BOOL fDoOpAsync) override { m_asyncMode = fDoOpAsync; return S_OK; } HRESULT STDMETHODCALLTYPE GetAsyncMode(BOOL *pfIsOpAsync) override { if ( pfIsOpAsync == nullptr ) return E_INVALIDARG; *pfIsOpAsync = m_asyncMode; return S_OK; } HRESULT STDMETHODCALLTYPE StartOperation(IBindCtx *pbcReserved) override { (void)pbcReserved; m_inOperation = TRUE; return S_OK; } HRESULT STDMETHODCALLTYPE InOperation(BOOL *pfInAsyncOp) override { if ( pfInAsyncOp == nullptr ) return E_INVALIDARG; *pfInAsyncOp = m_inOperation; return S_OK; } HRESULT STDMETHODCALLTYPE EndOperation(HRESULT hResult,IBindCtx *pbcReserved,DWORD dwEffects) override { (void)hResult; (void)pbcReserved; (void)dwEffects; m_inOperation = FALSE; return S_OK; } }; }
