📄 dataobj.cpp
字号:
///////////////////////////////////////////////////////////////////////////////// Name: msw/ole/dataobj.cpp// Purpose: implementation of wx[I]DataObject class// Author: Vadim Zeitlin// Modified by:// Created: 10.05.98// RCS-ID: $Id: dataobj.cpp,v 1.98 2006/11/12 15:54:06 JS Exp $// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>// Licence: wxWindows licence///////////////////////////////////////////////////////////////////////////////// ============================================================================// declarations// ============================================================================// ----------------------------------------------------------------------------// headers// ----------------------------------------------------------------------------// For compilers that support precompilation, includes "wx.h".#include "wx/wxprec.h"#if defined(__BORLANDC__) #pragma hdrstop#endif#ifndef WX_PRECOMP #include "wx/intl.h" #include "wx/log.h" #include "wx/utils.h"#endif#include "wx/dataobj.h"#if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__)#include "wx/msw/private.h" // includes <windows.h>#ifdef __WXWINCE__#include <winreg.h>#endif// for some compilers, the entire ole2.h must be included, not only oleauto.h#if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__) #include <ole2.h>#endif#include <oleauto.h>#include <shlobj.h>#include "wx/msw/ole/oleutils.h"#include "wx/msw/dib.h"#ifndef CFSTR_SHELLURL#define CFSTR_SHELLURL _T("UniformResourceLocator")#endif// ----------------------------------------------------------------------------// functions// ----------------------------------------------------------------------------#ifdef __WXDEBUG__ static const wxChar *GetTymedName(DWORD tymed);#else // !Debug #define GetTymedName(tymed) wxEmptyString#endif // Debug/!Debug// ----------------------------------------------------------------------------// wxIEnumFORMATETC interface implementation// ----------------------------------------------------------------------------class wxIEnumFORMATETC : public IEnumFORMATETC{public: wxIEnumFORMATETC(const wxDataFormat* formats, ULONG nCount); virtual ~wxIEnumFORMATETC() { delete [] m_formats; } // IEnumFORMATETC STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched); STDMETHODIMP Skip(ULONG celt); STDMETHODIMP Reset(); STDMETHODIMP Clone(IEnumFORMATETC **ppenum); DECLARE_IUNKNOWN_METHODS;private: CLIPFORMAT *m_formats; // formats we can provide data in ULONG m_nCount, // number of formats we support m_nCurrent; // current enum position DECLARE_NO_COPY_CLASS(wxIEnumFORMATETC)};// ----------------------------------------------------------------------------// wxIDataObject implementation of IDataObject interface// ----------------------------------------------------------------------------class wxIDataObject : public IDataObject{public: wxIDataObject(wxDataObject *pDataObject); virtual ~wxIDataObject(); // normally, wxDataObject controls our lifetime (i.e. we're deleted when it // is), but in some cases, the situation is reversed, that is we delete it // when this object is deleted - setting this flag enables such logic void SetDeleteFlag() { m_mustDelete = true; } // IDataObject STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium); STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium); STDMETHODIMP QueryGetData(FORMATETC *pformatetc); STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut); STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease); STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc); STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw); STDMETHODIMP DUnadvise(DWORD dwConnection); STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise); DECLARE_IUNKNOWN_METHODS;private: wxDataObject *m_pDataObject; // pointer to C++ class we belong to bool m_mustDelete; DECLARE_NO_COPY_CLASS(wxIDataObject)};// ============================================================================// implementation// ============================================================================// ----------------------------------------------------------------------------// wxDataFormat// ----------------------------------------------------------------------------void wxDataFormat::SetId(const wxChar *format){ m_format = (wxDataFormat::NativeFormat)::RegisterClipboardFormat(format); if ( !m_format ) { wxLogError(_("Couldn't register clipboard format '%s'."), format); }}wxString wxDataFormat::GetId() const{ static const int max = 256; wxString s; wxCHECK_MSG( !IsStandard(), s, wxT("name of predefined format cannot be retrieved") ); int len = ::GetClipboardFormatName(m_format, wxStringBuffer(s, max), max); if ( !len ) { wxLogError(_("The clipboard format '%d' doesn't exist."), m_format); } return s;}// ----------------------------------------------------------------------------// wxIEnumFORMATETC// ----------------------------------------------------------------------------BEGIN_IID_TABLE(wxIEnumFORMATETC) ADD_IID(Unknown) ADD_IID(EnumFORMATETC)END_IID_TABLE;IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount){ m_nCurrent = 0; m_nCount = nCount; m_formats = new CLIPFORMAT[nCount]; for ( ULONG n = 0; n < nCount; n++ ) { m_formats[n] = formats[n].GetFormatId(); }}STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Next")); ULONG numFetched = 0; while (m_nCurrent < m_nCount && numFetched < celt) { FORMATETC format; format.cfFormat = m_formats[m_nCurrent++]; format.ptd = NULL; format.dwAspect = DVASPECT_CONTENT; format.lindex = -1; format.tymed = TYMED_HGLOBAL; *rgelt++ = format; numFetched++; } if (pceltFetched) *pceltFetched = numFetched; return numFetched == celt ? S_OK : S_FALSE;}STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Skip")); m_nCurrent += celt; if ( m_nCurrent < m_nCount ) return S_OK; // no, can't skip this many elements m_nCurrent -= celt; return S_FALSE;}STDMETHODIMP wxIEnumFORMATETC::Reset(){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Reset")); m_nCurrent = 0; return S_OK;}STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Clone")); // unfortunately, we can't reuse the code in ctor - types are different wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(NULL, 0); pNew->m_nCount = m_nCount; pNew->m_formats = new CLIPFORMAT[m_nCount]; for ( ULONG n = 0; n < m_nCount; n++ ) { pNew->m_formats[n] = m_formats[n]; } pNew->AddRef(); *ppenum = pNew; return S_OK;}// ----------------------------------------------------------------------------// wxIDataObject// ----------------------------------------------------------------------------BEGIN_IID_TABLE(wxIDataObject) ADD_IID(Unknown) ADD_IID(DataObject)END_IID_TABLE;IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)wxIDataObject::wxIDataObject(wxDataObject *pDataObject){ m_pDataObject = pDataObject; m_mustDelete = false;}wxIDataObject::~wxIDataObject(){ if ( m_mustDelete ) { delete m_pDataObject; }}// get data functionsSTDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetData")); // is data is in our format? HRESULT hr = QueryGetData(pformatetcIn); if ( FAILED(hr) ) return hr; // for the bitmaps and metafiles we use the handles instead of global memory // to pass the data wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat; switch ( format ) { case wxDF_BITMAP: pmedium->tymed = TYMED_GDI; break; case wxDF_ENHMETAFILE: pmedium->tymed = TYMED_ENHMF; break;#ifndef __WXWINCE__ case wxDF_METAFILE: pmedium->hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(METAFILEPICT)); if ( !pmedium->hGlobal ) { wxLogLastError(wxT("GlobalAlloc")); return E_OUTOFMEMORY; } pmedium->tymed = TYMED_MFPICT; break;#endif default: // alloc memory size_t size = m_pDataObject->GetDataSize(format); if ( !size ) { // it probably means that the method is just not implemented wxLogDebug(wxT("Invalid data size - can't be 0")); return DV_E_FORMATETC; } // we may need extra space for the buffer size size += m_pDataObject->GetBufferOffset( format ); HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size); if ( hGlobal == NULL ) { wxLogLastError(wxT("GlobalAlloc")); return E_OUTOFMEMORY; } // copy data pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = hGlobal; } pmedium->pUnkForRelease = NULL; // do copy the data hr = GetDataHere(pformatetcIn, pmedium); if ( FAILED(hr) ) { // free resources we allocated if ( pmedium->tymed & (TYMED_HGLOBAL | TYMED_MFPICT) ) { GlobalFree(pmedium->hGlobal); } return hr; } return S_OK;}STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetDataHere")); // put data in caller provided medium switch ( pmedium->tymed ) { case TYMED_GDI: if ( !m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap) ) return E_UNEXPECTED; break; case TYMED_ENHMF: if ( !m_pDataObject->GetDataHere(wxDF_ENHMETAFILE, &pmedium->hEnhMetaFile) ) return E_UNEXPECTED; break; case TYMED_MFPICT: // fall through - we pass METAFILEPICT through HGLOBAL case TYMED_HGLOBAL: { // copy data HGLOBAL hGlobal = pmedium->hGlobal; void *pBuf = GlobalLock(hGlobal); if ( pBuf == NULL ) { wxLogLastError(wxT("GlobalLock")); return E_OUTOFMEMORY; } wxDataFormat format = pformatetc->cfFormat; // possibly put the size in the beginning of the buffer pBuf = m_pDataObject->SetSizeInBuffer ( pBuf, ::GlobalSize(hGlobal), format ); if ( !m_pDataObject->GetDataHere(format, pBuf) ) return E_UNEXPECTED; GlobalUnlock(hGlobal); } break; default: return DV_E_TYMED; } return S_OK;}// set data functionsSTDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease){ wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData")); switch ( pmedium->tymed ) { case TYMED_GDI: m_pDataObject->SetData(wxDF_BITMAP, 0, &pmedium->hBitmap); break; case TYMED_ENHMF: m_pDataObject->SetData(wxDF_ENHMETAFILE, 0, &pmedium->hEnhMetaFile); break; case TYMED_MFPICT: // fall through - we pass METAFILEPICT through HGLOBAL case TYMED_HGLOBAL: { wxDataFormat format = pformatetc->cfFormat; // this is quite weird, but for file drag and drop, explorer // calls our SetData() with the formats we do *not* support! // // as we can't fix this bug in explorer (it's a bug because it // should only use formats returned by EnumFormatEtc), do the // check here if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) { // go away! return DV_E_FORMATETC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -