1. more drag and drop and clipboard changes:

a) OLE clipboard works fine
 b) wxBitmapDataObject now accepts DIBs (but doesn't give them back :-( )
 c) bugs in sample corrected
2. wxFatalExit() replaced with wxFAIL_MSG() in bitmap.cpp and dcmemory.cpp
3. wxFrame::ClientToScreen and ScreenToClient() replaced with DoXXX() - like
   this, they don't hide the base class versions


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4039 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-10-18 00:08:40 +00:00
parent 23d277e683
commit d59ceba572
9 changed files with 820 additions and 333 deletions

View File

@@ -57,14 +57,24 @@
#include "wx/msw/private.h"
#include "wx/msw/dib.h"
// wxDataObject is tied to OLE/drag and drop implementation,
// therefore so is wxClipboard :-(
#if wxUSE_DRAG_AND_DROP
// wxDataObject is tied to OLE/drag and drop implementation, therefore so are
// the functions using wxDataObject in wxClipboard
#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP
#if wxUSE_DATAOBJ
#include "wx/dataobj.h"
static bool wxSetClipboardData(wxDataObject *data);
// use OLE clipboard
#define wxUSE_OLE_CLIPBOARD 1
#else // !wxUSE_DATAOBJ
// use Win clipboard API
#define wxUSE_OLE_CLIPBOARD 0
#endif
#if wxUSE_OLE_CLIPBOARD
#include <ole2.h>
#endif // wxUSE_OLE_CLIPBOARD
#ifdef __WIN16__
#define memcpy hmemcpy
#endif
@@ -136,41 +146,12 @@ bool wxIsClipboardOpened()
bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
{
return ::IsClipboardFormatAvailable(dataFormat) != 0;
// for bitmaps, DIBs will also do
return (::IsClipboardFormatAvailable(dataFormat) != 0) ||
(dataFormat.GetFormatId() == CF_BITMAP &&
::IsClipboardFormatAvailable(CF_DIB));
}
#if wxUSE_DRAG_AND_DROP
static bool wxSetClipboardData(wxDataObject *data)
{
wxDataFormat format = data->GetPreferredFormat();
size_t size = data->GetDataSize(format);
HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
if ( !hGlobal )
{
wxLogSysError(_("Failed to allocate %dKb of memory for clipboard "
"transfer."), size / 1024);
return FALSE;
}
LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
data->GetDataHere(format, lpGlobalMemory);
GlobalUnlock(hGlobal);
if ( !::SetClipboardData(format, hGlobal) )
{
wxLogSysError(_("Failed to set clipboard data in format %s"),
wxDataObject::GetFormatName(format));
return FALSE;
}
return TRUE;
}
#endif // wxUSE_DRAG_AND_DROP
bool wxSetClipboardData(wxDataFormat dataFormat,
const void *data,
int width, int height)
@@ -223,7 +204,7 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
// NULL palette means to use the system one
HANDLE hDIB = wxBitmapToDIB(hBitmap, (HPALETTE)NULL);
handle = SetClipboardData(CF_DIB, hDIB);
#endif
#endif // wxUSE_IMAGE_LOADING_IN_MSW
break;
}
@@ -442,20 +423,51 @@ wxClipboard* wxTheClipboard = (wxClipboard *)NULL;
wxClipboard::wxClipboard()
{
m_clearOnExit = FALSE;
}
wxClipboard::~wxClipboard()
{
Clear();
if ( m_clearOnExit )
{
Clear();
}
}
void wxClipboard::Clear()
{
#if wxUSE_OLE_CLIPBOARD
if ( FAILED(OleSetClipboard(NULL)) )
{
wxLogLastError("OleSetClipboard(NULL)");
}
#endif
}
bool wxClipboard::Flush()
{
if ( FAILED(OleFlushClipboard()) )
{
wxLogLastError("OleFlushClipboard");
return FALSE;
}
else
{
m_clearOnExit = FALSE;
return TRUE;
}
}
bool wxClipboard::Open()
{
// OLE opens clipboard for us
#if wxUSE_OLE_CLIPBOARD
return TRUE;
#else
return wxOpenClipboard();
#endif
}
bool wxClipboard::SetData( wxDataObject *data )
@@ -472,7 +484,32 @@ bool wxClipboard::AddData( wxDataObject *data )
{
wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
#if wxUSE_DRAG_AND_DROP
#if wxUSE_OLE_CLIPBOARD
HRESULT hr = OleSetClipboard(data->GetInterface());
if ( FAILED(hr) )
{
wxLogSysError(hr, _("Failed to put data on the clipboard"));
// don't free anything in this case
return FALSE;
}
// we have a problem here because we should delete wxDataObject, but we
// can't do it because IDataObject which we just gave to the clipboard
// would try to use it when it will need the data. IDataObject is ref
// counted and so doesn't suffer from such problem, so we release it now
// and tell it to delete wxDataObject when it is deleted itself.
data->SetAutoDelete();
// we have to call either OleSetClipboard(NULL) or OleFlushClipboard() when
// using OLE clipboard when the app terminates - by default, we call
// OleSetClipboard(NULL) which won't waste RAM, but the app can call
// wxClipboard::Flush() to chaneg this
m_clearOnExit = TRUE;
return TRUE;
#elif wxUSE_DATAOBJ
wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
wxDataFormat format = data->GetFormat();
@@ -510,14 +547,17 @@ bool wxClipboard::AddData( wxDataObject *data )
default:
return wxSetClipboardData(data);
}
#else // !wxUSE_DRAG_AND_DROP
#else // !wxUSE_DATAOBJ
return FALSE;
#endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
#endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
}
void wxClipboard::Close()
{
// OLE closes clipboard for us
#if !wxUSE_OLE_CLIPBOARD
wxCloseClipboard();
#endif
}
bool wxClipboard::IsSupported( wxDataFormat format )
@@ -527,9 +567,145 @@ bool wxClipboard::IsSupported( wxDataFormat format )
bool wxClipboard::GetData( wxDataObject *data )
{
wxCHECK_MSG( data, FALSE, wxT("invalid data object") );
#if wxUSE_OLE_CLIPBOARD
IDataObject *pDataObject = NULL;
HRESULT hr = OleGetClipboard(&pDataObject);
if ( FAILED(hr) || !pDataObject )
{
wxLogSysError(hr, _("Failed to get data from the clipboard"));
return FALSE;
}
// build the list of supported formats
size_t nFormats = data->GetFormatCount(FALSE /* for SetData() */);
wxDataFormat format, *formats;
if ( nFormats == 1 )
{
// the most common case
formats = &format;
}
else
{
// bad luck, need to alloc mem
formats = new wxDataFormat[nFormats];
}
data->GetAllFormats(formats, FALSE);
// get the format enumerator
bool result = FALSE;
wxArrayInt supportedFormats;
IEnumFORMATETC *pEnumFormatEtc = NULL;
hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormatEtc);
if ( FAILED(hr) || !pEnumFormatEtc )
{
wxLogSysError(hr,
_("Failed to retrieve the supported clipboard formats"));
}
else
{
// ask for the supported formats and see if there are any we support
FORMATETC formatEtc;
for ( ;; )
{
ULONG nCount;
hr = pEnumFormatEtc->Next(1, &formatEtc, &nCount);
// don't use FAILED() because S_FALSE would pass it
if ( hr != S_OK )
{
// no more formats
break;
}
CLIPFORMAT cf = formatEtc.cfFormat;
#ifdef __WXDEBUG__
wxLogTrace(wxTRACE_OleCalls,
wxT("Object on the clipboard supports format %s."),
wxDataObject::GetFormatName(cf));
#endif // Debug
// is supported?
for ( size_t n = 0; n < nFormats; n++ )
{
if ( formats[n].GetFormatId() == cf )
{
if ( supportedFormats.Index(cf) == wxNOT_FOUND )
{
supportedFormats.Add(cf);
}
}
}
}
pEnumFormatEtc->Release();
}
if ( formats != &format )
{
delete [] formats;
}
//else: we didn't allocate any memory
if ( !supportedFormats.IsEmpty() )
{
FORMATETC formatEtc;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.tymed = TYMED_HGLOBAL;
size_t nSupportedFormats = supportedFormats.GetCount();
for ( size_t n = 0; !result && (n < nSupportedFormats); n++ )
{
STGMEDIUM medium;
formatEtc.cfFormat = supportedFormats[n];
// try to get data
hr = pDataObject->GetData(&formatEtc, &medium);
if ( FAILED(hr) )
{
// try other tymed for GDI objects
if ( formatEtc.cfFormat == CF_BITMAP )
{
formatEtc.tymed = TYMED_HGLOBAL;
hr = pDataObject->GetData(&formatEtc, &medium);
}
}
if ( SUCCEEDED(hr) )
{
// pass the data to the data object
hr = data->GetInterface()->SetData(&formatEtc, &medium, TRUE);
if ( FAILED(hr) )
{
wxLogDebug(wxT("Failed to set data in wxIDataObject"));
// IDataObject only takes the ownership of data if it
// successfully got it - which is not the case here
ReleaseStgMedium(&medium);
}
else
{
result = TRUE;
}
}
//else: unsupported tymed?
}
}
//else: unsupported format
// clean up and return
pDataObject->Release();
return result;
#elif wxUSE_DATAOBJ
wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
#if wxUSE_DRAG_AND_DROP
wxDataFormat format = data->GetFormat();
switch ( format )
{
@@ -593,9 +769,9 @@ bool wxClipboard::GetData( wxDataObject *data )
return FALSE;
}
#else
#else // !wxUSE_DATAOBJ
return FALSE;
#endif
#endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
}
//-----------------------------------------------------------------------------