📄 dataobj.cpp
字号:
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;
}
// copy data
const void *pBuf = GlobalLock(pmedium->hGlobal);
if ( pBuf == NULL ) {
wxLogLastError(wxT("GlobalLock"));
return E_OUTOFMEMORY;
}
// we've got a problem with SetData() here because the base
// class version requires the size parameter which we don't
// have anywhere in OLE data transfer - so we need to
// synthetise it for known formats and we suppose that all data
// in custom formats starts with a DWORD containing the size
size_t size;
switch ( format )
{
case CF_TEXT:
case CF_OEMTEXT:
size = strlen((const char *)pBuf);
break;
#if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500))
case CF_UNICODETEXT:
#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \
|| ( defined(__MWERKS__) && defined(__WXMSW__) )
size = std::wcslen((const wchar_t *)pBuf) * sizeof(wchar_t);
#else
size = wxWcslen((const wchar_t *)pBuf) * sizeof(wchar_t);
#endif
break;
#endif
case CF_BITMAP:
#ifndef __WXWINCE__
case CF_HDROP:
// these formats don't use size at all, anyhow (but
// pass data by handle, which is always a single DWORD)
size = 0;
break;
#endif
case CF_DIB:
// the handler will calculate size itself (it's too
// complicated to do it here)
size = 0;
break;
#ifndef __WXWINCE__
case CF_METAFILEPICT:
size = sizeof(METAFILEPICT);
break;
#endif
default:
pBuf = m_pDataObject->
GetSizeFromBuffer(pBuf, &size, format);
size -= m_pDataObject->GetBufferOffset(format);
}
bool ok = m_pDataObject->SetData(format, size, pBuf);
GlobalUnlock(pmedium->hGlobal);
if ( !ok ) {
return E_UNEXPECTED;
}
}
break;
default:
return DV_E_TYMED;
}
if ( fRelease ) {
// we own the medium, so we must release it - but do *not* free any
// data we pass by handle because we have copied it elsewhere
switch ( pmedium->tymed )
{
case TYMED_GDI:
pmedium->hBitmap = 0;
break;
case TYMED_MFPICT:
pmedium->hMetaFilePict = 0;
break;
case TYMED_ENHMF:
pmedium->hEnhMetaFile = 0;
break;
}
ReleaseStgMedium(pmedium);
}
return S_OK;
}
// information functions
STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
{
// do we accept data in this format?
if ( pformatetc == NULL ) {
wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: invalid ptr."));
return E_INVALIDARG;
}
// the only one allowed by current COM implementation
if ( pformatetc->lindex != -1 ) {
wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: bad lindex %ld"),
pformatetc->lindex);
return DV_E_LINDEX;
}
// we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"),
pformatetc->dwAspect);
return DV_E_DVASPECT;
}
// and now check the type of data requested
wxDataFormat format = pformatetc->cfFormat;
if ( m_pDataObject->IsSupportedFormat(format) ) {
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
wxGetFormatName(format));
}
else {
wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: %s unsupported"),
wxGetFormatName(format));
return DV_E_FORMATETC;
}
// we only transfer data by global memory, except for some particular cases
DWORD tymed = pformatetc->tymed;
if ( (format == wxDF_BITMAP && !(tymed & TYMED_GDI)) &&
!(tymed & TYMED_HGLOBAL) ) {
// it's not what we're waiting for
wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: %s != %s"),
GetTymedName(tymed),
GetTymedName(format == wxDF_BITMAP ? TYMED_GDI
: TYMED_HGLOBAL));
return DV_E_TYMED;
}
return S_OK;
}
STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *WXUNUSED(pFormatetcIn),
FORMATETC *pFormatetcOut)
{
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetCanonicalFormatEtc"));
// TODO we might want something better than this trivial implementation here
if ( pFormatetcOut != NULL )
pFormatetcOut->ptd = NULL;
return DATA_S_SAMEFORMATETC;
}
STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDir,
IEnumFORMATETC **ppenumFormatEtc)
{
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
wxDataObject::Direction dir = dwDir == DATADIR_GET ? wxDataObject::Get
: wxDataObject::Set;
ULONG nFormatCount = wx_truncate_cast(ULONG, m_pDataObject->GetFormatCount(dir));
wxDataFormat format;
wxDataFormat *formats;
formats = nFormatCount == 1 ? &format : new wxDataFormat[nFormatCount];
m_pDataObject->GetAllFormats(formats, dir);
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
pEnum->AddRef();
*ppenumFormatEtc = pEnum;
if ( formats != &format ) {
delete [] formats;
}
return S_OK;
}
// ----------------------------------------------------------------------------
// advise sink functions (not implemented)
// ----------------------------------------------------------------------------
STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *WXUNUSED(pformatetc),
DWORD WXUNUSED(advf),
IAdviseSink *WXUNUSED(pAdvSink),
DWORD *WXUNUSED(pdwConnection))
{
return OLE_E_ADVISENOTSUPPORTED;
}
STDMETHODIMP wxIDataObject::DUnadvise(DWORD WXUNUSED(dwConnection))
{
return OLE_E_ADVISENOTSUPPORTED;
}
STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **WXUNUSED(ppenumAdvise))
{
return OLE_E_ADVISENOTSUPPORTED;
}
// ----------------------------------------------------------------------------
// wxDataObject
// ----------------------------------------------------------------------------
wxDataObject::wxDataObject()
{
m_pIDataObject = new wxIDataObject(this);
m_pIDataObject->AddRef();
}
wxDataObject::~wxDataObject()
{
ReleaseInterface(m_pIDataObject);
}
void wxDataObject::SetAutoDelete()
{
((wxIDataObject *)m_pIDataObject)->SetDeleteFlag();
m_pIDataObject->Release();
// so that the dtor doesnt' crash
m_pIDataObject = NULL;
}
size_t wxDataObject::GetBufferOffset(const wxDataFormat& format )
{
// if we prepend the size of the data to the buffer itself, account for it
return NeedsVerbatimData(format) ? 0 : sizeof(size_t);
}
const void* wxDataObject::GetSizeFromBuffer( const void* buffer, size_t* size,
const wxDataFormat& format )
{
size_t realsz = ::HeapSize(::GetProcessHeap(), 0, buffer);
if ( realsz == (size_t)-1 )
{
// note that HeapSize() does not set last error
wxLogApiError(wxT("HeapSize"), 0);
return NULL;
}
*size = realsz;
// check if this data has its size prepended (as it was by default for wx
// programs prior 2.6.3):
size_t *p = (size_t *)buffer;
if ( *p == realsz )
{
if ( NeedsVerbatimData(format) )
wxLogDebug(wxT("Apparent data format mismatch: size not needed"));
p++; // this data has its size prepended; skip first DWORD
}
return p;
}
void* wxDataObject::SetSizeInBuffer( void* buffer, size_t size,
const wxDataFormat& format )
{
size_t* p = (size_t *)buffer;
if ( !NeedsVerbatimData(format) )
{
// prepend the size to the data and skip it
*p++ = size;
}
return p;
}
#ifdef __WXDEBUG__
const wxChar *wxDataObject::GetFormatName(wxDataFormat format)
{
// case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
#ifdef __VISUALC__
#pragma warning(disable:4063)
#endif // VC++
static wxChar s_szBuf[256];
switch ( format ) {
case CF_TEXT: return wxT("CF_TEXT");
case CF_BITMAP: return wxT("CF_BITMAP");
case CF_SYLK: return wxT("CF_SYLK");
case CF_DIF: return wxT("CF_DIF");
case CF_TIFF: return wxT("CF_TIFF");
case CF_OEMTEXT: return wxT("CF_OEMTEXT");
case CF_DIB: return wxT("CF_DIB");
case CF_PALETTE: return wxT("CF_PALETTE");
case CF_PENDATA: return wxT("CF_PENDATA");
case CF_RIFF: return wxT("CF_RIFF");
case CF_WAVE: return wxT("CF_WAVE");
case CF_UNICODETEXT: return wxT("CF_UNICODETEXT");
#ifndef __WXWINCE__
case CF_METAFILEPICT: return wxT("CF_METAFILEPICT");
case CF_ENHMETAFILE: return wxT("CF_ENHMETAFILE");
case CF_LOCALE: return wxT("CF_LOCALE");
case CF_HDROP: return wxT("CF_HDROP");
#endif
default:
if ( !::GetClipboardFormatName(format, s_szBuf, WXSIZEOF(s_szBuf)) )
{
// it must be a new predefined format we don't know the name of
wxSprintf(s_szBuf, wxT("unknown CF (0x%04x)"), format.GetFormatId());
}
return s_szBuf;
}
#ifdef __VISUALC__
#pragma warning(default:4063)
#endif // VC++
}
#endif // Debug
// ----------------------------------------------------------------------------
// wxBitmapDataObject supports CF_DIB format
// ----------------------------------------------------------------------------
// TODO: support CF_DIB under Windows CE as well
size_t wxBitmapDataObject::GetDataSize() const
{
#if wxUSE_WXDIB && !defined(__WXWINCE__)
return wxDIB::ConvertFromBitmap(NULL, GetHbitmapOf(GetBitmap()));
#else
return 0;
#endif
}
bool wxBitmapDataObject::GetDataHere(void *buf) const
{
#if wxUSE_WXDIB && !defined(__WXWINCE__)
BITMAPINFO * const pbi = (BITMAPINFO *)buf;
return wxDIB::ConvertFromBitmap(pbi, GetHbitmapOf(GetBitmap())) != 0;
#else
wxUnusedVar(buf);
return false;
#endif
}
bool wxBitmapDataObject::SetData(size_t WXUNUSED(len), const void *buf)
{
#if wxUSE_WXDIB && !defined(__WXWINCE__)
const BITMAPINFO * const pbmi = (const BITMAPINFO *)buf;
HBITMAP hbmp = wxDIB::ConvertToBitmap(pbmi);
wxCHECK_MSG( hbmp, FALSE, wxT("pasting/dropping invalid bitmap") );
const BITMAPINFOHEADER * const pbmih = &pbmi->bmiHeader;
wxBitmap bitmap(pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount);
bitmap.SetHBITMAP((WXHBITMAP)hbmp);
// TODO: create wxPalette if the bitmap has any
SetBitmap(bitmap);
return true;
#else
wxUnusedVar(buf);
return false;
#endif
}
// ----------------------------------------------------------------------------
// wxBitmapDataObject2 supports CF_BITMAP format
// ----------------------------------------------------------------------------
// the bitmaps aren't passed by value as other types of data (i.e. by copying
// the data into a global memory chunk and passing it to the clipboard or
// another application or whatever), but by handle, so these generic functions
// don't make much sense to them.
size_t wxBitmapDataObject2::GetDataSize() const
{
return 0;
}
bool wxBitmapDataObject2::GetDataHere(void *pBuf) const
{
// we put a bitmap handle into pBuf
*(WXHBITMAP *)pBuf = GetBitmap().GetHBITMAP();
return true;
}
bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len), const void *pBuf)
{
HBITMAP hbmp = *(HBITMAP *)pBuf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -