// set data functions STDMETHODIMP 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_ISTREAM: // check if this format is supported if ( !m_pDataObject->IsSupported(pformatetc->cfFormat, wxDataObject::Set) ) { // As this is not a supported format (content data), assume it // is system data and save it. return SaveSystemData(pformatetc, pmedium, fRelease); } break; case TYMED_MFPICT: // fall through - we pass METAFILEPICT through HGLOBAL case TYMED_HGLOBAL: { wxDataFormat format = pformatetc->cfFormat; format = HtmlFormatFixup(format); // check if this format is supported if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) { // As above, assume that unsupported format must be system // data and just save it. return SaveSystemData(pformatetc, pmedium, fRelease); } // 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 wxDF_HTML: 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) ) 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; }
// get data functions STDMETHODIMP 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; format = HtmlFormatFixup(format); // is this system data? if ( GetSystemData(format, pmedium) ) { // pmedium is already filled with corresponding data, so we're ready. return S_OK; } 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; }