wxDataObject changes - ok for MSW, still not for GTK/Motif/...

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4090 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-10-21 01:58:57 +00:00
parent e1ee679c2e
commit 9e2896e5c8
17 changed files with 852 additions and 589 deletions

View File

@@ -115,7 +115,7 @@ class wxClipboardModule : public wxModule
{ {
public: public:
bool OnInit() bool OnInit()
{ wxTheClipboard = new wxClipboard; } { wxTheClipboard = new wxClipboard; return TRUE; }
void OnExit() void OnExit()
{ delete wxTheClipboard; wxTheClipboard = (wxClipboard *)NULL; } { delete wxTheClipboard; wxTheClipboard = (wxClipboard *)NULL; }

View File

@@ -134,7 +134,10 @@ public:
// get data from the buffer of specified length (in the given format), // get data from the buffer of specified length (in the given format),
// return TRUE if the data was read successfully, FALSE otherwise // return TRUE if the data was read successfully, FALSE otherwise
virtual bool SetData(const wxDataFormat& format, virtual bool SetData(const wxDataFormat& format,
size_t len, const void *buf) = 0; size_t len, const void *buf)
{
return FALSE;
}
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -334,31 +337,25 @@ private:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxFileDataObject contains a list of filenames // wxFileDataObject contains a list of filenames
//
// NB: notice that this is a "write only" object, it can only be filled with
// data from drag and drop operation.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxFileDataObjectBase : public wxDataObjectSimple class WXDLLEXPORT wxFileDataObjectBase : public wxDataObjectSimple
{ {
public: public:
// ctor: you can specify the bitmap here or in SetBitmap(), or override // ctor: use AddFile() later to fill the array
// GetBitmap()
wxFileDataObjectBase() : wxDataObjectSimple(wxDF_FILENAME) { } wxFileDataObjectBase() : wxDataObjectSimple(wxDF_FILENAME) { }
// get a reference to our array - you may modify it (i.e. add/remove // get a reference to our array
// filenames to it then) const wxArrayString& GetFilenames() { return m_filenames; }
wxArrayString& GetFilenames() { return m_filenames; }
// a helper function // the Get() functions do nothing for us
void AddFile(const wxString& filename) { m_filenames.Add(filename); } virtual size_t GetDataSize() const { return 0; }
virtual bool GetDataHere(void *WXUNUSED(buf)) const { return FALSE; }
// virtual functions which you may override if you want to provide data on protected:
// demand only - otherwise, the trivial default versions will be used.
//
// they work with a NUL-separated string of filenames, the base class
// versions concatenate/extract filenames from this string
virtual wxString GetFilenames() const;
virtual void SetFilenames(const wxChar* filenames);
private:
wxArrayString m_filenames; wxArrayString m_filenames;
}; };

View File

@@ -1243,29 +1243,29 @@ typedef enum
#define wxTOOL_LEFT 3 #define wxTOOL_LEFT 3
#define wxTOOL_RIGHT 4 #define wxTOOL_RIGHT 4
// the values of the format constants should be the same as correspondign
// tyhe ids of standard data formats // CF_XXX constants in Windows API
enum wxDataFormatId enum wxDataFormatId
{ {
wxDF_INVALID = 0, wxDF_INVALID = 0,
wxDF_TEXT = 1, /* CF_TEXT */ wxDF_TEXT = 1, /* CF_TEXT */
wxDF_BITMAP = 2, /* CF_BITMAP */ wxDF_BITMAP = 2, /* CF_BITMAP */
wxDF_METAFILE = 3, /* CF_METAFILEPICT */ wxDF_METAFILE = 3, /* CF_METAFILEPICT */
wxDF_SYLK = 4, wxDF_SYLK = 4,
wxDF_DIF = 5, wxDF_DIF = 5,
wxDF_TIFF = 6, wxDF_TIFF = 6,
wxDF_OEMTEXT = 7, /* CF_OEMTEXT */ wxDF_OEMTEXT = 7, /* CF_OEMTEXT */
wxDF_DIB = 8, /* CF_DIB */ wxDF_DIB = 8, /* CF_DIB */
wxDF_PALETTE = 9, wxDF_PALETTE = 9,
wxDF_PENDATA = 10, wxDF_PENDATA = 10,
wxDF_RIFF = 11, wxDF_RIFF = 11,
wxDF_WAVE = 12, wxDF_WAVE = 12,
wxDF_UNICODETEXT = 13, wxDF_UNICODETEXT = 13,
wxDF_ENHMETAFILE = 14, wxDF_ENHMETAFILE = 14,
wxDF_FILENAME = 15, /* CF_HDROP */ wxDF_FILENAME = 15, /* CF_HDROP */
wxDF_LOCALE = 16, wxDF_LOCALE = 16,
wxDF_PRIVATE = 20, wxDF_PRIVATE = 20,
wxDF_MAX wxDF_MAX
}; };
/* Virtual keycodes */ /* Virtual keycodes */

View File

@@ -49,7 +49,7 @@ public:
// start drag action, see enum wxDragResult for return value description // start drag action, see enum wxDragResult for return value description
// //
// if bAllowMove is TRUE, data can be moved, if not - only copied // if bAllowMove is TRUE, data can be moved, if not - only copied
virtual wxDragResult DoDragDrop( bool bAllowMove = FALSE ); virtual wxDragResult DoDragDrop(bool bAllowMove = FALSE) = 0;
// override to give feedback depending on the current operation result // override to give feedback depending on the current operation result
// "effect" // "effect"
@@ -65,7 +65,13 @@ protected:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxDropTarget should be associated with a window if it wants to be able to // wxDropTarget should be associated with a window if it wants to be able to
// receive data via drag and drop // receive data via drag and drop.
//
// To use this class, you should derive from wxDropTarget and implement
// OnData() pure virtual method. You may also wish to override OnDrop() if you
// want to accept the data only inside some region of the window (this may
// avoid having to copy the data to this application which happens only when
// OnData() is called)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxDropTargetBase class WXDLLEXPORT wxDropTargetBase
@@ -99,7 +105,7 @@ public:
// called after OnDrop() returns TRUE: you will usually just call // called after OnDrop() returns TRUE: you will usually just call
// GetData() from here and, probably, also refresh something to update the // GetData() from here and, probably, also refresh something to update the
// new data // new data
virtual bool OnData() = 0; virtual bool OnData(wxCoord x, wxCoord y) = 0;
// may be called *only* from inside OnData() and will fill m_dataObject // may be called *only* from inside OnData() and will fill m_dataObject
// with the data from the drop source if it returns TRUE // with the data from the drop source if it returns TRUE
@@ -109,12 +115,16 @@ protected:
wxDataObject *m_dataObject; wxDataObject *m_dataObject;
}; };
// ----------------------------------------------------------------------------
// the platform-specific headers also define standard wxDropTarget
// implementations wxTextDropTarget and wxFileDropTarget
// ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// include platform dependent class declarations // include platform dependent class declarations
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if defined(__WXMSW__) #if defined(__WXMSW__)
#include "wx/dataobj.h"
#include "wx/msw/ole/dropsrc.h" #include "wx/msw/ole/dropsrc.h"
#include "wx/msw/ole/droptgt.h" #include "wx/msw/ole/droptgt.h"
#elif defined(__WXMOTIF__) #elif defined(__WXMOTIF__)

View File

@@ -15,8 +15,6 @@
#pragma interface #pragma interface
#endif #endif
#include "wx/defs.h"
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
#include "wx/object.h" #include "wx/object.h"
@@ -46,87 +44,153 @@ class wxDropSource;
class wxDropTarget: public wxObject class wxDropTarget: public wxObject
{ {
public: public:
wxDropTarget( wxDataObject *data );
~wxDropTarget();
/* may be overridden to react to events */ wxDropTarget();
virtual bool OnEnter( int x, int y ); ~wxDropTarget();
virtual void OnLeave(); /* may be overridden to react to events */
virtual void OnEnter();
virtual void OnLeave();
/* may be overridden to reject certain formats or drops /* may be overridden to reject certain formats or drops
on certain areas. always returns TRUE by default on certain areas. always returns TRUE by default
indicating that you'd accept the data from the drag. */ indicating that you'd accept the data from the drag. */
virtual bool OnMove( int x, int y ); virtual bool OnMove( long x, long y );
/* has to be overridden to accept a drop event. call /* has to be overridden to accept a drop event. call
IsSupported() to ask which formats are available IsSupported() to ask which formats are available
and then call RequestData() to indicate the format and then call RequestData() to indicate the format
you request. */ you request. */
virtual bool OnDrop( int x, int y ); virtual bool OnDrop( long x, long y );
/* this gets called once the data has actually arrived. /* this gets called once the data has actually arrived. get
it will call GetData() to fill up its wxDataObject */ it with GetData(). this has to be overridden. */
virtual bool OnData( int x, int y ); virtual bool OnData( long x, long y );
/* fill data with data from the dragging source */ /* called from within OnDrop() to request a certain format
bool GetData(); from the drop event. */
bool RequestData( wxDataFormat format );
/* called to query what formats are available */
bool IsSupported( wxDataFormat format );
/* fill data with data from the dragging source */
bool GetData( wxDataObject *data );
virtual size_t GetFormatCount() const = 0;
virtual wxDataFormat GetFormat(size_t n) const = 0;
// implementation // implementation
GdkAtom GetMatchingPair(); void RegisterWidget( GtkWidget *widget );
void UnregisterWidget( GtkWidget *widget );
void RegisterWidget( GtkWidget *widget ); GdkDragContext *m_dragContext;
void UnregisterWidget( GtkWidget *widget ); GtkWidget *m_dragWidget;
GtkSelectionData *m_dragData;
guint m_dragTime;
bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
wxDataObject *m_data; void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
GdkDragContext *m_dragContext; void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
GtkWidget *m_dragWidget; void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
GtkSelectionData *m_dragData; void SetDragTime( guint time ) { m_dragTime = time; }
guint m_dragTime; };
bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; } //-------------------------------------------------------------------------
void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; } // wxTextDropTarget
void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; } //-------------------------------------------------------------------------
void SetDragTime( guint time ) { m_dragTime = time; }
class wxTextDropTarget: public wxDropTarget
{
public:
wxTextDropTarget() {}
virtual bool OnData( long x, long y );
/* you have to override OnDropData to get at the text */
virtual bool OnDropText( long x, long y, const wxChar *text ) = 0;
virtual size_t GetFormatCount() const
{ return 1; }
virtual wxDataFormat GetFormat(size_t n) const
{ return wxDF_TEXT; }
};
//-------------------------------------------------------------------------
// wxPrivateDropTarget
//-------------------------------------------------------------------------
/*
class wxPrivateDropTarget: public wxDropTarget
{
public:
wxPrivateDropTarget();
wxPrivateDropTarget( const wxString &id );
virtual bool OnMove( long x, long y );
virtual bool OnDrop( long x, long y );
virtual bool OnData( long x, long y );
virtual bool OnDropData( long x, long y, void *data, size_t size ) = 0;
void SetId( const wxString& id ) { m_id = id; }
wxString GetId() { return m_id; }
private:
wxString m_id;
};
*/
//----------------------------------------------------------------------------
// A drop target which accepts files (dragged from File Manager or Explorer)
//----------------------------------------------------------------------------
class wxFileDropTarget: public wxDropTarget
{
public:
wxFileDropTarget() {}
virtual bool OnData( long x, long y );
virtual bool OnDropFiles( long x, long y, size_t nFiles, const wxChar * const aszFiles[] ) = 0;
virtual size_t GetFormatCount() const
{ return 1; }
virtual wxDataFormat GetFormat(size_t n) const
{ return wxDF_FILENAME; }
}; };
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// wxDropSource // wxDropSource
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
enum wxDragResult
{
wxDragError, // error prevented the d&d operation from completing
wxDragNone, // drag target didn't accept the data
wxDragCopy, // the data was successfully copied
wxDragMove, // the data was successfully moved (MSW only)
wxDragCancel // the operation was cancelled by user (not an error)
};
class wxDropSource: public wxObject class wxDropSource: public wxObject
{ {
public: public:
/* constructor. set data later with SetData() */
wxDropSource( wxWindow *win,
const wxIcon &go = wxNullIcon,
const wxIcon &stop = wxNullIcon );
/* constructor. set data later with SetData() */ /* constructor for setting one data object */
wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); wxDropSource( wxDataObject& data,
wxWindow *win,
const wxIcon &go = wxNullIcon,
const wxIcon &stop = wxNullIcon );
wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); ~wxDropSource();
~wxDropSource();
void SetData( wxDataObject& data ); /* start drag action */
virtual wxDragResult DoDragDrop( bool bAllowMove = FALSE );
/* start drag action */ /* GTK implementation */
wxDragResult DoDragDrop( bool bAllowMove = FALSE ); void RegisterWindow();
void UnregisterWindow();
/* override to give feedback */
virtual bool GiveFeedback( wxDragResult WXUNUSED(effect), bool WXUNUSED(bScrolling) ) { return TRUE; }
/* GTK implementation */
void RegisterWindow();
void UnregisterWindow();
GtkWidget *m_widget; GtkWidget *m_widget;
wxWindow *m_window; wxWindow *m_window;

View File

@@ -15,8 +15,6 @@
#pragma interface #pragma interface
#endif #endif
#include "wx/defs.h"
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
#include "wx/object.h" #include "wx/object.h"
@@ -46,87 +44,153 @@ class wxDropSource;
class wxDropTarget: public wxObject class wxDropTarget: public wxObject
{ {
public: public:
wxDropTarget( wxDataObject *data );
~wxDropTarget();
/* may be overridden to react to events */ wxDropTarget();
virtual bool OnEnter( int x, int y ); ~wxDropTarget();
virtual void OnLeave(); /* may be overridden to react to events */
virtual void OnEnter();
virtual void OnLeave();
/* may be overridden to reject certain formats or drops /* may be overridden to reject certain formats or drops
on certain areas. always returns TRUE by default on certain areas. always returns TRUE by default
indicating that you'd accept the data from the drag. */ indicating that you'd accept the data from the drag. */
virtual bool OnMove( int x, int y ); virtual bool OnMove( long x, long y );
/* has to be overridden to accept a drop event. call /* has to be overridden to accept a drop event. call
IsSupported() to ask which formats are available IsSupported() to ask which formats are available
and then call RequestData() to indicate the format and then call RequestData() to indicate the format
you request. */ you request. */
virtual bool OnDrop( int x, int y ); virtual bool OnDrop( long x, long y );
/* this gets called once the data has actually arrived. /* this gets called once the data has actually arrived. get
it will call GetData() to fill up its wxDataObject */ it with GetData(). this has to be overridden. */
virtual bool OnData( int x, int y ); virtual bool OnData( long x, long y );
/* fill data with data from the dragging source */ /* called from within OnDrop() to request a certain format
bool GetData(); from the drop event. */
bool RequestData( wxDataFormat format );
/* called to query what formats are available */
bool IsSupported( wxDataFormat format );
/* fill data with data from the dragging source */
bool GetData( wxDataObject *data );
virtual size_t GetFormatCount() const = 0;
virtual wxDataFormat GetFormat(size_t n) const = 0;
// implementation // implementation
GdkAtom GetMatchingPair(); void RegisterWidget( GtkWidget *widget );
void UnregisterWidget( GtkWidget *widget );
void RegisterWidget( GtkWidget *widget ); GdkDragContext *m_dragContext;
void UnregisterWidget( GtkWidget *widget ); GtkWidget *m_dragWidget;
GtkSelectionData *m_dragData;
guint m_dragTime;
bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
wxDataObject *m_data; void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
GdkDragContext *m_dragContext; void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
GtkWidget *m_dragWidget; void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
GtkSelectionData *m_dragData; void SetDragTime( guint time ) { m_dragTime = time; }
guint m_dragTime; };
bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; } //-------------------------------------------------------------------------
void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; } // wxTextDropTarget
void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; } //-------------------------------------------------------------------------
void SetDragTime( guint time ) { m_dragTime = time; }
class wxTextDropTarget: public wxDropTarget
{
public:
wxTextDropTarget() {}
virtual bool OnData( long x, long y );
/* you have to override OnDropData to get at the text */
virtual bool OnDropText( long x, long y, const wxChar *text ) = 0;
virtual size_t GetFormatCount() const
{ return 1; }
virtual wxDataFormat GetFormat(size_t n) const
{ return wxDF_TEXT; }
};
//-------------------------------------------------------------------------
// wxPrivateDropTarget
//-------------------------------------------------------------------------
/*
class wxPrivateDropTarget: public wxDropTarget
{
public:
wxPrivateDropTarget();
wxPrivateDropTarget( const wxString &id );
virtual bool OnMove( long x, long y );
virtual bool OnDrop( long x, long y );
virtual bool OnData( long x, long y );
virtual bool OnDropData( long x, long y, void *data, size_t size ) = 0;
void SetId( const wxString& id ) { m_id = id; }
wxString GetId() { return m_id; }
private:
wxString m_id;
};
*/
//----------------------------------------------------------------------------
// A drop target which accepts files (dragged from File Manager or Explorer)
//----------------------------------------------------------------------------
class wxFileDropTarget: public wxDropTarget
{
public:
wxFileDropTarget() {}
virtual bool OnData( long x, long y );
virtual bool OnDropFiles( long x, long y, size_t nFiles, const wxChar * const aszFiles[] ) = 0;
virtual size_t GetFormatCount() const
{ return 1; }
virtual wxDataFormat GetFormat(size_t n) const
{ return wxDF_FILENAME; }
}; };
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// wxDropSource // wxDropSource
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
enum wxDragResult
{
wxDragError, // error prevented the d&d operation from completing
wxDragNone, // drag target didn't accept the data
wxDragCopy, // the data was successfully copied
wxDragMove, // the data was successfully moved (MSW only)
wxDragCancel // the operation was cancelled by user (not an error)
};
class wxDropSource: public wxObject class wxDropSource: public wxObject
{ {
public: public:
/* constructor. set data later with SetData() */
wxDropSource( wxWindow *win,
const wxIcon &go = wxNullIcon,
const wxIcon &stop = wxNullIcon );
/* constructor. set data later with SetData() */ /* constructor for setting one data object */
wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); wxDropSource( wxDataObject& data,
wxWindow *win,
const wxIcon &go = wxNullIcon,
const wxIcon &stop = wxNullIcon );
wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); ~wxDropSource();
~wxDropSource();
void SetData( wxDataObject& data ); /* start drag action */
virtual wxDragResult DoDragDrop( bool bAllowMove = FALSE );
/* start drag action */ /* GTK implementation */
wxDragResult DoDragDrop( bool bAllowMove = FALSE ); void RegisterWindow();
void UnregisterWindow();
/* override to give feedback */
virtual bool GiveFeedback( wxDragResult WXUNUSED(effect), bool WXUNUSED(bScrolling) ) { return TRUE; }
/* GTK implementation */
void RegisterWindow();
void UnregisterWindow();
GtkWidget *m_widget; GtkWidget *m_widget;
wxWindow *m_window; wxWindow *m_window;

View File

@@ -22,54 +22,23 @@ struct IDataObject;
// wxDataObject is a "smart" and polymorphic piece of data. // wxDataObject is a "smart" and polymorphic piece of data.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxDataObject class WXDLLEXPORT wxDataObject : public wxDataObjectBase
{ {
public: public:
// ctor & dtor // ctor & dtor
wxDataObject(); wxDataObject();
virtual ~wxDataObject(); virtual ~wxDataObject();
// pure virtuals to override // retrieve IDataObject interface (for other OLE related classes)
// get the best suited format for rendering our data
virtual wxDataFormat GetPreferredFormat() const = 0;
// get the number of formats we support: it is understood that if we
// can accept data in some format, then we can render data in this
// format as well, but the contrary is not necessarily true. For the
// default value of the argument, all formats we support should be
// returned, but if outputOnlyToo == FALSE, then we should only return
// the formats which our SetData() understands
virtual size_t GetFormatCount(bool outputOnlyToo = TRUE) const
{ return 1; }
// return all formats in the provided array (of size GetFormatCount())
virtual void GetAllFormats(wxDataFormat *formats,
bool outputOnlyToo = TRUE) const
{ formats[0] = GetPreferredFormat(); }
// get the (total) size of data for the given format
virtual size_t GetDataSize(const wxDataFormat& format) const = 0;
// copy raw data (in the specified format) to provided pointer
virtual bool GetDataHere(const wxDataFormat& format, void *buf) const = 0;
// get data from the buffer (in the given format)
virtual bool SetData(const wxDataFormat& format, const void *buf) = 0;
// accessors
// retrieve IDataObject interface (for other OLE related classes)
IDataObject *GetInterface() const { return m_pIDataObject; } IDataObject *GetInterface() const { return m_pIDataObject; }
// a simpler name which makes more sense for data objects supporting
// only one format
wxDataFormat GetFormat() const { return GetPreferredFormat(); }
// old interface
// decide if we support this format (can be either standard or custom
// format) -- now uses GetAllFormats()
virtual bool IsSupportedFormat(const wxDataFormat& format) const;
// implementation only from now on
// -------------------------------
// tell the object that it should be now owned by IDataObject - i.e. when // tell the object that it should be now owned by IDataObject - i.e. when
// it is deleted, it should delete us as well // it is deleted, it should delete us as well
void SetAutoDelete(); void SetAutoDelete();
// return TRUE if we support this format in "Get" direction
bool IsSupportedFormat(const wxDataFormat& format) const;
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
// function to return symbolic name of clipboard format (for debug messages) // function to return symbolic name of clipboard format (for debug messages)
static const char *GetFormatName(wxDataFormat format); static const char *GetFormatName(wxDataFormat format);
@@ -79,73 +48,4 @@ private:
IDataObject *m_pIDataObject; // pointer to the COM interface IDataObject *m_pIDataObject; // pointer to the COM interface
}; };
// ----------------------------------------------------------------------------
// wxTextDataObject is a specialization of wxDataObject for text data
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxTextDataObject : public wxDataObject
{
public:
// ctors
wxTextDataObject() { }
wxTextDataObject(const wxString& strText) : m_strText(strText) { }
void Init(const wxString& strText) { m_strText = strText; }
// implement base class pure virtuals
virtual wxDataFormat GetPreferredFormat() const
{ return wxDF_TEXT; }
virtual bool IsSupportedFormat(const wxDataFormat& format) const
{ return format == wxDF_TEXT || format == wxDF_LOCALE; }
virtual size_t GetDataSize(const wxDataFormat& format) const
{ return m_strText.Len() + 1; } // +1 for trailing '\0'of course
virtual bool GetDataHere(const wxDataFormat& format, void *buf) const
{ memcpy(buf, m_strText.c_str(), GetDataSize(format)); return TRUE; }
virtual bool SetData(const wxDataFormat& format, const void *buf)
{ m_strText = (const wxChar *)buf; return TRUE; }
// additional helpers
void SetText(const wxString& strText) { m_strText = strText; }
wxString GetText() const { return m_strText; }
private:
wxString m_strText;
};
// ----------------------------------------------------------------------------
// wxBitmapDataObject is a specialization of wxDataObject for bitmap data
// ----------------------------------------------------------------------------
#include "wx/bitmap.h"
class WXDLLEXPORT wxBitmapDataObject : public wxDataObject
{
public:
// ctors
wxBitmapDataObject() { }
wxBitmapDataObject(const wxBitmap& bitmap): m_bitmap(bitmap) { }
// set/get our bitmap
void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; }
const wxBitmap GetBitmap() const { return m_bitmap; }
// implement base class pure virtuals
virtual wxDataFormat GetPreferredFormat() const { return wxDF_BITMAP; }
virtual size_t GetFormatCount(bool outputOnlyToo = TRUE) const;
virtual void GetAllFormats(wxDataFormat *formats,
bool outputOnlyToo = TRUE) const;
virtual size_t GetDataSize(const wxDataFormat& format) const;
virtual bool GetDataHere(const wxDataFormat& format, void *buf) const;
virtual bool SetData(const wxDataFormat& format, const void *buf);
private:
wxBitmap m_bitmap;
};
// ----------------------------------------------------------------------------
// wxMetaFileDataObject: see metafile.h is a specialization of wxDataObject for bitmap data
// ----------------------------------------------------------------------------
// TODO: wxFileDataObject.
#endif //_WX_MSW_OLE_DATAOBJ_H #endif //_WX_MSW_OLE_DATAOBJ_H

View File

@@ -33,7 +33,7 @@ class WXDLLEXPORT wxWindow;
// wxDataObject object. It's responsible for giving UI feedback while dragging. // wxDataObject object. It's responsible for giving UI feedback while dragging.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxDropSource class WXDLLEXPORT wxDropSource : public wxDropSourceBase
{ {
public: public:
// ctors: if you use default ctor you must call SetData() later! // ctors: if you use default ctor you must call SetData() later!

View File

@@ -9,9 +9,6 @@
// Licence: wxWindows licence // Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// prolog
// ============================================================================
#ifndef _WX_OLEDROPTGT_H #ifndef _WX_OLEDROPTGT_H
#define _WX_OLEDROPTGT_H #define _WX_OLEDROPTGT_H
@@ -20,12 +17,13 @@
#endif #endif
#if !wxUSE_DRAG_AND_DROP #if !wxUSE_DRAG_AND_DROP
#error "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!" #error "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!"
#endif //WX_DRAG_DROP #endif //WX_DRAG_DROP
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// forward declarations // forward declarations
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class wxIDropTarget; class wxIDropTarget;
struct IDataObject; struct IDataObject;
@@ -38,11 +36,12 @@ struct IDataObject;
// your own class from it implementing pure virtual function in order to use it // your own class from it implementing pure virtual function in order to use it
// (all of them, including protected ones which are called by the class itself) // (all of them, including protected ones which are called by the class itself)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxDropTarget
class WXDLLEXPORT wxDropTarget : public wxDropTargetBase
{ {
public: public:
// ctor & dtor // ctor & dtor
wxDropTarget(); wxDropTarget(wxDataObject *dataObject = NULL);
virtual ~wxDropTarget(); virtual ~wxDropTarget();
// normally called by wxWindow on window creation/destruction, but might be // normally called by wxWindow on window creation/destruction, but might be
@@ -50,62 +49,57 @@ public:
bool Register(WXHWND hwnd); bool Register(WXHWND hwnd);
void Revoke(WXHWND hwnd); void Revoke(WXHWND hwnd);
// provide default implementation for base class pure virtuals
virtual bool OnDrop(wxCoord x, wxCoord y);
virtual bool GetData();
// implementation only from now on
// -------------------------------
// do we accept this kind of data? // do we accept this kind of data?
virtual bool IsAcceptedData(IDataObject *pIDataSource) const; bool IsAcceptedData(IDataObject *pIDataSource) const;
// called when mouse enters/leaves the window: might be used to give // give us the data source from IDropTarget::Drop() - this is later used by
// some visual feedback to the user // GetData() when it's called from inside OnData()
virtual void OnEnter() { } void SetDataSource(IDataObject *pIDataSource);
virtual void OnLeave() { }
// this function is called when data is dropped.
// (x, y) are the coordinates of the drop
virtual bool OnDrop(long x, long y, const void *pData) = 0;
protected:
// Override these to indicate what kind of data you support: the first
// format to which data can be converted is used. The classes below show
// how it can be done in the simplest cases.
// how many different (clipboard) formats do you support?
virtual size_t GetFormatCount() const = 0;
// return the n-th supported format
virtual wxDataFormat GetFormat(size_t n) const = 0;
private: private:
wxIDropTarget *m_pIDropTarget; // the pointer to COM interface // helper used by IsAcceptedData() and GetData()
wxDataFormat GetSupportedFormat(IDataObject *pIDataSource) const;
wxIDropTarget *m_pIDropTarget; // the pointer to our COM interface
IDataObject *m_pIDataSource; // the pointer to the source data object
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// A simple wxDropTarget derived class for text data: you only need to // A simple wxDropTarget derived class for text data: you only need to
// override OnDropText() to get something working // override OnDropText() to get something working
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxTextDropTarget : public wxDropTarget class WXDLLEXPORT wxTextDropTarget : public wxDropTarget
{ {
public: public:
virtual bool OnDrop(long x, long y, const void *pData); wxTextDropTarget();
virtual bool OnDropText(long x, long y, const wxChar *psz) = 0;
protected: virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) = 0;
virtual size_t GetFormatCount() const;
virtual wxDataFormat GetFormat(size_t n) const; virtual bool OnData(wxCoord x, wxCoord y);
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// A drop target which accepts files (dragged from File Manager or Explorer) // A drop target which accepts files (dragged from File Manager or Explorer)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxFileDropTarget : public wxDropTarget class WXDLLEXPORT wxFileDropTarget : public wxDropTarget
{ {
public: public:
virtual bool OnDrop(long x, long y, const void *pData); wxFileDropTarget();
// params: the number of files and the array of file names // parameters are the number of files and the array of file names
virtual bool OnDropFiles(long x, long y, virtual bool OnDropFiles(wxCoord x, wxCoord y,
size_t nFiles, const wxChar * const aszFiles[]) = 0; const wxArrayString& filenames) = 0;
protected: virtual bool OnData(wxCoord x, wxCoord y);
virtual size_t GetFormatCount() const;
virtual wxDataFormat GetFormat(size_t n) const;
}; };
// ============================================================================
#endif //_WX_OLEDROPTGT_H #endif //_WX_OLEDROPTGT_H

View File

@@ -43,15 +43,12 @@
// file names) we drop on them // file names) we drop on them
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
typedef long wxDropPointCoord;
class DnDText : public wxTextDropTarget class DnDText : public wxTextDropTarget
{ {
public: public:
DnDText(wxListBox *pOwner) { m_pOwner = pOwner; } DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y, virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text);
const wxChar* psz);
private: private:
wxListBox *m_pOwner; wxListBox *m_pOwner;
@@ -62,8 +59,8 @@ class DnDFile : public wxFileDropTarget
public: public:
DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; } DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y, virtual bool OnDropFiles(wxCoord x, wxCoord y,
size_t nFiles, const wxChar* const aszFiles[] ); const wxArrayString& filenames);
private: private:
wxListBox *m_pOwner; wxListBox *m_pOwner;
@@ -146,6 +143,10 @@ public:
{ {
} }
// this is for debugging - lets us see when exactly an object is freed
// (this may be later than you think if it's on the clipboard, for example)
virtual ~DnDShape() { }
// the functions used for drag-and-drop: they dump and restore a shape into // the functions used for drag-and-drop: they dump and restore a shape into
// some bitwise-copiable data (might use streams too...) // some bitwise-copiable data (might use streams too...)
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@@ -213,6 +214,11 @@ public:
{ {
} }
virtual ~DnDTriangularShape()
{
wxLogMessage("DnDTriangularShape is being deleted");
}
virtual Kind GetKind() const { return Triangle; } virtual Kind GetKind() const { return Triangle; }
virtual void Draw(wxDC& dc) virtual void Draw(wxDC& dc)
{ {
@@ -244,6 +250,11 @@ public:
{ {
} }
virtual ~DnDRectangularShape()
{
wxLogMessage("DnDRectangularShape is being deleted");
}
virtual Kind GetKind() const { return Rectangle; } virtual Kind GetKind() const { return Rectangle; }
virtual void Draw(wxDC& dc) virtual void Draw(wxDC& dc)
{ {
@@ -275,6 +286,11 @@ public:
{ {
} }
virtual ~DnDEllipticShape()
{
wxLogMessage("DnDEllipticShape is being deleted");
}
virtual Kind GetKind() const { return Ellipse; } virtual Kind GetKind() const { return Ellipse; }
virtual void Draw(wxDC& dc) virtual void Draw(wxDC& dc)
{ {
@@ -299,9 +315,24 @@ class DnDShapeDataObject : public wxDataObject
public: public:
// ctor doesn't copy the pointer, so it shouldn't go away while this object // ctor doesn't copy the pointer, so it shouldn't go away while this object
// is alive // is alive
DnDShapeDataObject(DnDShape *shape) DnDShapeDataObject(DnDShape *shape = (DnDShape *)NULL)
{ {
m_shape = shape; if ( shape )
{
// we need to copy the shape because the one we're handled may be
// deleted while it's still on the clipboard (for example) - and we
// reuse the serialisation methods here to copy it
void *buf = malloc(shape->DnDShape::GetDataSize());
shape->GetDataHere(buf);
m_shape = DnDShape::New(buf);
free(buf);
}
else
{
// nothing to copy
m_shape = NULL;
}
// this string should uniquely identify our format, but is otherwise // this string should uniquely identify our format, but is otherwise
// arbitrary // arbitrary
@@ -312,36 +343,38 @@ public:
m_hasBitmap = FALSE; m_hasBitmap = FALSE;
} }
virtual ~DnDShapeDataObject() { delete m_shape; }
// accessors // accessors
DnDShape *GetShape() const { return m_shape; } DnDShape *GetShape() const { return m_shape; }
// implement base class pure virtuals // implement base class pure virtuals
// ---------------------------------- // ----------------------------------
virtual wxDataFormat GetPreferredFormat() const virtual wxDataFormat GetPreferredFormat(Direction WXUNUSED(dir)) const
{ {
return m_formatShape; return m_formatShape;
} }
virtual size_t GetFormatCount(bool outputOnlyToo) const virtual size_t GetFormatCount(Direction dir) const
{ {
// our custom format is supported by both GetData() and SetData() // our custom format is supported by both GetData() and SetData()
size_t nFormats = 1; size_t nFormats = 1;
if ( outputOnlyToo ) if ( dir == Get )
{ {
// but the bitmap format(s) are only supported for output // but the bitmap format(s) are only supported for output
nFormats += m_dataobj.GetFormatCount(); nFormats += m_dataobj.GetFormatCount(dir);
} }
return nFormats; return nFormats;
} }
virtual void GetAllFormats(wxDataFormat *formats, bool outputOnlyToo) const virtual void GetAllFormats(wxDataFormat *formats, Direction dir) const
{ {
formats[0] = m_formatShape; formats[0] = m_formatShape;
if ( outputOnlyToo ) if ( dir == Get )
{ {
m_dataobj.GetAllFormats(&formats[1]); m_dataobj.GetAllFormats(&formats[1], dir);
} }
} }
@@ -356,7 +389,7 @@ public:
if ( !m_hasBitmap ) if ( !m_hasBitmap )
CreateBitmap(); CreateBitmap();
return m_dataobj.GetDataSize(format); return m_dataobj.GetDataSize();
} }
} }
@@ -375,11 +408,12 @@ public:
if ( !m_hasBitmap ) if ( !m_hasBitmap )
CreateBitmap(); CreateBitmap();
return m_dataobj.GetDataHere(format, pBuf); return m_dataobj.GetDataHere(pBuf);
} }
} }
virtual bool SetData(const wxDataFormat& format, const void *buf) virtual bool SetData(const wxDataFormat& format,
size_t len, const void *buf)
{ {
wxCHECK_MSG( format == m_formatShape, FALSE, "unsupported format" ); wxCHECK_MSG( format == m_formatShape, FALSE, "unsupported format" );
@@ -483,11 +517,9 @@ class DnDShapeDropTarget : public wxDropTarget
{ {
public: public:
DnDShapeDropTarget(DnDShapeFrame *frame) DnDShapeDropTarget(DnDShapeFrame *frame)
: wxDropTarget(new DnDShapeDataObject)
{ {
m_frame = frame; m_frame = frame;
// the same as used by DnDShapeDataObject
m_formatShape.SetId(shapeFormatId);
} }
// override base class (pure) virtuals // override base class (pure) virtuals
@@ -495,21 +527,23 @@ public:
{ m_frame->SetStatusText("Mouse entered the frame"); } { m_frame->SetStatusText("Mouse entered the frame"); }
virtual void OnLeave() virtual void OnLeave()
{ m_frame->SetStatusText("Mouse left the frame"); } { m_frame->SetStatusText("Mouse left the frame"); }
virtual bool OnDrop(long x, long y, const void *pData) virtual bool OnData(wxCoord x, wxCoord y)
{ {
m_frame->OnDrop(x, y, DnDShape::New(pData)); if ( !GetData() )
{
wxLogError("Failed to get drag and drop data");
return FALSE;
}
m_frame->OnDrop(x, y,
((DnDShapeDataObject *)GetDataObject())->GetShape());
return TRUE; return TRUE;
} }
protected:
virtual size_t GetFormatCount() const { return 1; }
virtual wxDataFormat GetFormat(size_t WXUNUSED(n)) const
{ return m_formatShape; }
private: private:
DnDShapeFrame *m_frame; DnDShapeFrame *m_frame;
wxDataFormat m_formatShape;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -1012,21 +1046,21 @@ void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
// Notifications called by the base class // Notifications called by the base class
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool DnDText::OnDropText( wxDropPointCoord, wxDropPointCoord, const wxChar *psz ) bool DnDText::OnDropText(wxCoord, wxCoord, const wxString& text)
{ {
m_pOwner->Append(psz); m_pOwner->Append(text);
return TRUE; return TRUE;
} }
bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles, bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
const wxChar* const aszFiles[])
{ {
size_t nFiles = filenames.GetCount();
wxString str; wxString str;
str.Printf( _T("%d files dropped"), nFiles); str.Printf( _T("%d files dropped"), nFiles);
m_pOwner->Append(str); m_pOwner->Append(str);
for ( size_t n = 0; n < nFiles; n++ ) { for ( size_t n = 0; n < nFiles; n++ ) {
m_pOwner->Append(aszFiles[n]); m_pOwner->Append(filenames[n]);
} }
return TRUE; return TRUE;
@@ -1224,6 +1258,18 @@ void DnDShapeFrame::OnDrag(wxMouseEvent& event)
//else: status text already set //else: status text already set
} }
void DnDShapeFrame::OnDrop(long x, long y, DnDShape *shape)
{
ms_lastDropTarget = this;
wxString s;
s.Printf("Shape dropped at (%ld, %ld)", x, y);
SetStatusText(s);
shape->Move(ScreenToClient(wxPoint(x, y)));
SetShape(shape);
}
void DnDShapeFrame::OnEditShape(wxCommandEvent& event) void DnDShapeFrame::OnEditShape(wxCommandEvent& event)
{ {
DnDShapeDialog dlg(this, m_shape); DnDShapeDialog dlg(this, m_shape);
@@ -1287,18 +1333,6 @@ void DnDShapeFrame::OnPaint(wxPaintEvent& event)
event.Skip(); event.Skip();
} }
void DnDShapeFrame::OnDrop(long x, long y, DnDShape *shape)
{
ms_lastDropTarget = this;
wxString s;
s.Printf("Shape dropped at (%ld, %ld)", x, y);
SetStatusText(s);
shape->Move(ScreenToClient(wxPoint(x, y)));
SetShape(shape);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DnDShape // DnDShape
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -33,6 +33,7 @@
#endif #endif
#include "wx/thread.h" #include "wx/thread.h"
#include "wx/clipbrd.h"
// =========================================================================== // ===========================================================================
// implementation // implementation

View File

@@ -175,6 +175,10 @@ bool wxTextDataObject::SetData(size_t WXUNUSED(len), const void *buf)
// wxFileDataObjectBase // wxFileDataObjectBase
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// VZ: I don't need this in MSW finally, so if it is needed in wxGTK, it should
// be moved to gtk/dataobj.cpp
#if 0
wxString wxFileDataObjectBase::GetFilenames() const wxString wxFileDataObjectBase::GetFilenames() const
{ {
wxString str; wxString str;
@@ -212,6 +216,8 @@ void wxFileDataObjectBase::SetFilenames(const wxChar* filenames)
} }
} }
#endif // 0
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxCustomDataObject // wxCustomDataObject
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -257,7 +263,7 @@ bool wxCustomDataObject::GetDataHere(void *buf) const
return TRUE; return TRUE;
} }
bool wxCustomDataObject::SetData(size_t len, const void *buf) bool wxCustomDataObject::SetData(size_t size, const void *buf)
{ {
Free(); Free();
@@ -265,7 +271,7 @@ bool wxCustomDataObject::SetData(size_t len, const void *buf)
if ( !m_data ) if ( !m_data )
return FALSE; return FALSE;
memcpy(m_data, buf, m_size = len); memcpy(m_data, buf, m_size = size);
return TRUE; return TRUE;
} }

View File

@@ -584,7 +584,7 @@ bool wxClipboard::GetData( wxDataObject *data )
} }
// build the list of supported formats // build the list of supported formats
size_t nFormats = data->GetFormatCount(FALSE /* for SetData() */); size_t nFormats = data->GetFormatCount(wxDataObject::Set);
wxDataFormat format, *formats; wxDataFormat format, *formats;
if ( nFormats == 1 ) if ( nFormats == 1 )
{ {
@@ -597,7 +597,7 @@ bool wxClipboard::GetData( wxDataObject *data )
formats = new wxDataFormat[nFormats]; formats = new wxDataFormat[nFormats];
} }
data->GetAllFormats(formats, FALSE); data->GetAllFormats(formats, wxDataObject::Set);
// get the format enumerator // get the format enumerator
bool result = FALSE; bool result = FALSE;

View File

@@ -58,6 +58,10 @@
static const wxChar *GetTymedName(DWORD tymed); static const wxChar *GetTymedName(DWORD tymed);
#endif // Debug #endif // Debug
// to be moved into wx/msw/bitmap.h
extern size_t wxConvertBitmapToDIB(BITMAPINFO *pbi, const wxBitmap& bitmap);
extern wxBitmap wxConvertDIBToBitmap(const BITMAPINFO *bmi);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxIEnumFORMATETC interface implementation // wxIEnumFORMATETC interface implementation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -320,6 +324,12 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
return DV_E_FORMATETC; return DV_E_FORMATETC;
} }
if ( !format.IsStandard() ) {
// for custom formats, put the size with the data - alloc the
// space for it
size += sizeof(size_t);
}
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size); HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
if ( hGlobal == NULL ) { if ( hGlobal == NULL ) {
wxLogLastError("GlobalAlloc"); wxLogLastError("GlobalAlloc");
@@ -369,17 +379,25 @@ STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
case TYMED_HGLOBAL: case TYMED_HGLOBAL:
{ {
// copy data // copy data
void *pBuf = GlobalLock(pmedium->hGlobal); HGLOBAL hGlobal = pmedium->hGlobal;
void *pBuf = GlobalLock(hGlobal);
if ( pBuf == NULL ) { if ( pBuf == NULL ) {
wxLogLastError(wxT("GlobalLock")); wxLogLastError(wxT("GlobalLock"));
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat; if ( !wxDataFormat(pformatetc->cfFormat).IsStandard() ) {
// for custom formats, put the size with the data
size_t *p = (size_t *)pBuf;
*p++ = GlobalSize(hGlobal);
pBuf = p;
}
wxDataFormat format = pformatetc->cfFormat;
if ( !m_pDataObject->GetDataHere(format, pBuf) ) if ( !m_pDataObject->GetDataHere(format, pBuf) )
return E_UNEXPECTED; return E_UNEXPECTED;
GlobalUnlock(pmedium->hGlobal); GlobalUnlock(hGlobal);
} }
break; break;
@@ -390,7 +408,7 @@ STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
return S_OK; return S_OK;
} }
// set data functions (not implemented) // set data functions
STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc, STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
STGMEDIUM *pmedium, STGMEDIUM *pmedium,
BOOL fRelease) BOOL fRelease)
@@ -400,7 +418,7 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
switch ( pmedium->tymed ) switch ( pmedium->tymed )
{ {
case TYMED_GDI: case TYMED_GDI:
m_pDataObject->SetData(wxDF_BITMAP, &pmedium->hBitmap); m_pDataObject->SetData(wxDF_BITMAP, 0, &pmedium->hBitmap);
break; break;
case TYMED_MFPICT: case TYMED_MFPICT:
@@ -419,10 +437,47 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat; // we've got a problem with SetData() here because the base
m_pDataObject->SetData(format, pBuf); // 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 ( pformatetc->cfFormat )
{
case CF_TEXT:
case CF_OEMTEXT:
size = strlen((const char *)pBuf);
break;
case CF_UNICODETEXT:
size = wcslen((const wchar_t *)pBuf);
break;
case CF_BITMAP:
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;
default:
{
// we suppose that the size precedes the data
size_t *p = (size_t *)pBuf;
size = *p++;
pBuf = p;
}
}
wxDataFormat format = pformatetc->cfFormat;
bool ok = m_pDataObject->SetData(format, size, pBuf);
GlobalUnlock(pmedium->hGlobal); GlobalUnlock(pmedium->hGlobal);
if ( !ok ) {
return E_UNEXPECTED;
}
} }
break; break;
@@ -474,7 +529,7 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
} }
// and now check the type of data requested // and now check the type of data requested
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat; wxDataFormat format = pformatetc->cfFormat;
if ( m_pDataObject->IsSupportedFormat(format) ) { if ( m_pDataObject->IsSupportedFormat(format) ) {
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"), wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
@@ -482,11 +537,10 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
#endif // Debug #endif // Debug
} }
else { else {
#ifdef __WXDEBUG__
wxLogTrace(wxTRACE_OleCalls, wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: %s unsupported"), wxT("wxIDataObject::QueryGetData: %s unsupported"),
wxDataObject::GetFormatName(format)); wxDataObject::GetFormatName(format));
#endif
return DV_E_FORMATETC; return DV_E_FORMATETC;
} }
@@ -521,25 +575,18 @@ STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
return DATA_S_SAMEFORMATETC; return DATA_S_SAMEFORMATETC;
} }
STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection, STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDir,
IEnumFORMATETC **ppenumFormatEtc) IEnumFORMATETC **ppenumFormatEtc)
{ {
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
bool allowOutputOnly = dwDirection == DATADIR_GET; wxDataObject::Direction dir = dwDir == DATADIR_GET ? wxDataObject::Get
: wxDataObject::Set;
size_t nFormatCount = m_pDataObject->GetFormatCount(allowOutputOnly); size_t nFormatCount = m_pDataObject->GetFormatCount(dir);
wxDataFormat format, *formats; wxDataFormat format, *formats;
if ( nFormatCount == 1 ) { formats = nFormatCount == 1 ? &format : new wxDataFormat[nFormatCount];
// this is the most common case, this is why we consider it separately m_pDataObject->GetAllFormats(formats, dir);
formats = &format;
format = m_pDataObject->GetPreferredFormat();
}
else {
// bad luck, build the array with all formats
formats = new wxDataFormat[nFormatCount];
m_pDataObject->GetAllFormats(formats, allowOutputOnly);
}
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount); wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
pEnum->AddRef(); pEnum->AddRef();
@@ -552,7 +599,10 @@ STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
return S_OK; return S_OK;
} }
// ----------------------------------------------------------------------------
// advise sink functions (not implemented) // advise sink functions (not implemented)
// ----------------------------------------------------------------------------
STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc, STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
DWORD advf, DWORD advf,
IAdviseSink *pAdvSink, IAdviseSink *pAdvSink,
@@ -656,67 +706,82 @@ const char *wxDataObject::GetFormatName(wxDataFormat format)
#endif // Debug #endif // Debug
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxPrivateDataObject // wxBitmapDataObject supports CF_DIB format
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxPrivateDataObject::wxPrivateDataObject() size_t wxBitmapDataObject::GetDataSize() const
{ {
m_size = 0; return wxConvertBitmapToDIB(NULL, GetBitmap());
m_data = NULL;
} }
void wxPrivateDataObject::Free() bool wxBitmapDataObject::GetDataHere(void *buf) const
{ {
if ( m_data ) return wxConvertBitmapToDIB((BITMAPINFO *)buf, GetBitmap()) != 0;
free(m_data);
} }
void wxPrivateDataObject::SetData( const void *data, size_t size ) bool wxBitmapDataObject::SetData(size_t len, const void *buf)
{ {
Free(); wxBitmap bitmap(wxConvertDIBToBitmap((const BITMAPINFO *)buf));
m_size = size; if ( !bitmap.Ok() ) {
m_data = malloc(size); wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
memcpy( m_data, data, size ); return FALSE;
} }
void wxPrivateDataObject::WriteData( void *dest ) const SetBitmap(bitmap);
{
WriteData( m_data, dest );
}
size_t wxPrivateDataObject::GetSize() const return TRUE;
{
return m_size;
}
void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
{
memcpy( dest, data, GetSize() );
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxBitmapDataObject: it supports standard CF_BITMAP and CF_DIB formats // wxBitmapDataObject2 supports CF_BITMAP format
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
size_t wxBitmapDataObject::GetFormatCount(bool outputOnlyToo) const // the bitmaps aren't passed by value as other types of data (i.e. by copying
{
return 2;
}
void wxBitmapDataObject::GetAllFormats(wxDataFormat *formats,
bool outputOnlyToo) const
{
formats[0] = CF_BITMAP;
formats[1] = CF_DIB;
}
// the bitmaps aren't passed by value as other types of data (i.e. by copyign
// the data into a global memory chunk and passing it to the clipboard or // 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 // another application or whatever), but by handle, so these generic functions
// don't make much sense to them. // 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 len, const void *pBuf)
{
HBITMAP hbmp = *(HBITMAP *)pBuf;
BITMAP bmp;
if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
{
wxLogLastError("GetObject(HBITMAP)");
}
wxBitmap bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes);
bitmap.SetHBITMAP((WXHBITMAP)hbmp);
if ( !bitmap.Ok() ) {
wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
return FALSE;
}
SetBitmap(bitmap);
return TRUE;
}
#if 0
size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
{ {
if ( format.GetFormatId() == CF_DIB ) if ( format.GetFormatId() == CF_DIB )
@@ -789,7 +854,8 @@ bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
return TRUE; return TRUE;
} }
bool wxBitmapDataObject::SetData(const wxDataFormat& format, const void *pBuf) bool wxBitmapDataObject::SetData(const wxDataFormat& format,
size_t size, const void *pBuf)
{ {
HBITMAP hbmp; HBITMAP hbmp;
if ( format.GetFormatId() == CF_DIB ) if ( format.GetFormatId() == CF_DIB )
@@ -833,10 +899,120 @@ bool wxBitmapDataObject::SetData(const wxDataFormat& format, const void *pBuf)
return TRUE; return TRUE;
} }
#endif // 0
// ----------------------------------------------------------------------------
// wxFileDataObject
// ----------------------------------------------------------------------------
bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *pData)
{
m_filenames.Empty();
// the documentation states that the first member of DROPFILES structure is
// a "DWORD offset of double NUL terminated file list". What they mean by
// this (I wonder if you see it immediately) is that the list starts at
// ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised
// to use DragQueryFile to work with this structure, but not told where and
// how to get HDROP.
HDROP hdrop = (HDROP)pData; // NB: it works, but I'm not sure about it
// get number of files (magic value -1)
UINT nFiles = ::DragQueryFile(hdrop, (unsigned)-1, NULL, 0u);
// for each file get the length, allocate memory and then get the name
wxString str;
UINT len, n;
for ( n = 0; n < nFiles; n++ ) {
// +1 for terminating NUL
len = ::DragQueryFile(hdrop, n, NULL, 0) + 1;
UINT len2 = ::DragQueryFile(hdrop, n, str.GetWriteBuf(len), len);
str.UngetWriteBuf();
m_filenames.Add(str);
if ( len2 != len - 1 ) {
wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned"
" %d characters, %d expected."), len2, len - 1);
}
}
return TRUE;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// private functions // private functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// otherwise VC++ would give here:
// "local variable 'bi' may be used without having been initialized"
// even though in fact it may not
#ifdef __VISUALC__
#pragma warning(disable:4701)
#endif // __VISUALC__
size_t wxConvertBitmapToDIB(BITMAPINFO *pbi, const wxBitmap& bitmap)
{
// shouldn't be selected into a DC or GetDIBits() would fail
wxASSERT_MSG( !bitmap.GetSelectedInto(),
wxT("can't copy bitmap selected into wxMemoryDC") );
HBITMAP hbmp = (HBITMAP)bitmap.GetHBITMAP();
BITMAPINFO bi;
// first get the info
ScreenHDC hdc;
if ( !GetDIBits(hdc, hbmp, 0, 0, NULL, pbi ? pbi : &bi, DIB_RGB_COLORS) )
{
wxLogLastError("GetDIBits(NULL)");
return 0;
}
if ( !pbi )
{
// we were only asked for size needed for the buffer, not to actually
// copy the data
return sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage;
}
// and now copy the bits
if ( !GetDIBits(hdc, hbmp, 0, pbi->bmiHeader.biHeight, pbi + 1,
pbi, DIB_RGB_COLORS) )
{
wxLogLastError("GetDIBits");
return 0;
}
return sizeof(BITMAPINFO) + pbi->bmiHeader.biSizeImage;
}
#ifdef __VISUALC__
#pragma warning(default:4701)
#endif // __VISUALC__
wxBitmap wxConvertDIBToBitmap(const BITMAPINFO *pbmi)
{
// here we get BITMAPINFO struct followed by the actual bitmap bits and
// BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
ScreenHDC hdc;
HBITMAP hbmp = CreateDIBitmap(hdc, pbmih, CBM_INIT,
pbmi + 1, pbmi, DIB_RGB_COLORS);
if ( !hbmp )
{
wxLogLastError("CreateDIBitmap");
}
wxBitmap bitmap(pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount);
bitmap.SetHBITMAP((WXHBITMAP)hbmp);
return bitmap;
}
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
static const wxChar *GetTymedName(DWORD tymed) static const wxChar *GetTymedName(DWORD tymed)

View File

@@ -36,17 +36,17 @@
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
#include "wx/log.h" #include "wx/log.h"
#include "wx/dataobj.h" #include "wx/dnd.h"
#include "wx/msw/ole/dropsrc.h"
#include <windows.h> #include <windows.h>
#ifdef wxUSE_NORLANDER_HEADERS #ifdef wxUSE_NORLANDER_HEADERS
#include <ole2.h> #include <ole2.h>
#endif #endif
#ifndef __WIN32__ #ifndef __WIN32__
#include <ole2.h> #include <ole2.h>
#include <olestd.h> #include <olestd.h>
#endif #endif
#include <oleauto.h> #include <oleauto.h>
@@ -165,7 +165,6 @@ wxDropSource::wxDropSource(wxWindow* WXUNUSED(win),
const wxIcon & WXUNUSED(stop)) const wxIcon & WXUNUSED(stop))
{ {
Init(); Init();
m_pData = NULL;
} }
wxDropSource::wxDropSource(wxDataObject& data, wxDropSource::wxDropSource(wxDataObject& data,
@@ -189,10 +188,10 @@ wxDropSource::~wxDropSource()
// Notes : you must call SetData() before if you had used def ctor // Notes : you must call SetData() before if you had used def ctor
wxDragResult wxDropSource::DoDragDrop(bool bAllowMove) wxDragResult wxDropSource::DoDragDrop(bool bAllowMove)
{ {
wxCHECK_MSG( m_pData != NULL, wxDragNone, wxT("No data in wxDropSource!") ); wxCHECK_MSG( m_data != NULL, wxDragNone, wxT("No data in wxDropSource!") );
DWORD dwEffect; DWORD dwEffect;
HRESULT hr = ::DoDragDrop(m_pData->GetInterface(), HRESULT hr = ::DoDragDrop(m_data->GetInterface(),
m_pIDropSource, m_pIDropSource,
bAllowMove ? DROPEFFECT_COPY | DROPEFFECT_MOVE bAllowMove ? DROPEFFECT_COPY | DROPEFFECT_MOVE
: DROPEFFECT_COPY, : DROPEFFECT_COPY,

View File

@@ -42,8 +42,7 @@
#include <shellapi.h> #include <shellapi.h>
#endif #endif
#include "wx/dataobj.h" #include "wx/dnd.h"
#include "wx/msw/ole/droptgt.h"
#ifndef __WIN32__ #ifndef __WIN32__
#include <ole2.h> #include <ole2.h>
@@ -70,19 +69,12 @@ public:
STDMETHODIMP DragLeave(void); STDMETHODIMP DragLeave(void);
STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD); STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
// we assume that if QueryGetData() returns S_OK, than we can really get data
// in this format, so we remember here the format for which QueryGetData()
// succeeded
void SetSupportedFormat(wxDataFormat cfFormat) { m_cfFormat = cfFormat; }
DECLARE_IUNKNOWN_METHODS; DECLARE_IUNKNOWN_METHODS;
protected: protected:
IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop
wxDropTarget *m_pTarget; // the real target (we're just a proxy) wxDropTarget *m_pTarget; // the real target (we're just a proxy)
wxDataFormat m_cfFormat; // the format in which to ask for data
private: private:
static inline DWORD GetDropEffect(DWORD flags); static inline DWORD GetDropEffect(DWORD flags);
}; };
@@ -108,7 +100,6 @@ wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
{ {
m_cRef = 0; m_cRef = 0;
m_pTarget = pTarget; m_pTarget = pTarget;
m_cfFormat = wxDF_INVALID;
m_pIDataObject = NULL; m_pIDataObject = NULL;
} }
@@ -212,45 +203,33 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
POINTL pt, POINTL pt,
DWORD *pdwEffect) DWORD *pdwEffect)
{ {
wxLogDebug(wxT("IDropTarget::Drop")); wxLogDebug(wxT("IDropTarget::Drop"));
// TODO I don't know why there is this parameter, but so far I assume // TODO I don't know why there is this parameter, but so far I assume
// that it's the same we've already got in DragEnter // that it's the same we've already got in DragEnter
wxASSERT( m_pIDataObject == pIDataSource ); wxASSERT( m_pIDataObject == pIDataSource );
STGMEDIUM stm; // by default, nothing happens
*pdwEffect = DROPEFFECT_NONE; *pdwEffect = DROPEFFECT_NONE;
// should be set by SetSupportedFormat() call // first ask the drop target if it wants data
wxASSERT( m_cfFormat != wxDF_INVALID ); if ( m_pTarget->OnDrop(pt.x, pt.y) ) {
// it does, so give it the data source
m_pTarget->SetDataSource(pIDataSource);
FORMATETC fmtMemory; // and now it has the data
fmtMemory.cfFormat = m_cfFormat; if ( m_pTarget->OnData(pt.x, pt.y) ) {
fmtMemory.ptd = NULL; // operation succeeded
fmtMemory.dwAspect = DVASPECT_CONTENT; *pdwEffect = GetDropEffect(grfKeyState);
fmtMemory.lindex = -1; }
fmtMemory.tymed = TYMED_HGLOBAL; // TODO to add other media //else: *pdwEffect is already DROPEFFECT_NONE
HRESULT hr = pIDataSource->GetData(&fmtMemory, &stm);
if ( SUCCEEDED(hr) ) {
if ( stm.hGlobal != NULL ) {
if ( m_pTarget->OnDrop(pt.x, pt.y, GlobalLock(stm.hGlobal)) )
*pdwEffect = GetDropEffect(grfKeyState);
//else: DROPEFFECT_NONE
GlobalUnlock(stm.hGlobal);
ReleaseStgMedium(&stm);
} }
} //else: OnDrop() returned FALSE, no need to copy data
else
{
// wxLogApiError("GetData", hr);
}
// release the held object // release the held object
RELEASE_AND_NULL(m_pIDataObject); RELEASE_AND_NULL(m_pIDataObject);
return S_OK; return S_OK;
} }
// ============================================================================ // ============================================================================
@@ -261,17 +240,18 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
// ctor/dtor // ctor/dtor
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxDropTarget::wxDropTarget() wxDropTarget::wxDropTarget(wxDataObject *dataObj)
: wxDropTargetBase(dataObj)
{ {
// create an IDropTarget implementation which will notify us about // create an IDropTarget implementation which will notify us about d&d
// d&d operations. // operations.
m_pIDropTarget = new wxIDropTarget(this); m_pIDropTarget = new wxIDropTarget(this);
m_pIDropTarget->AddRef(); m_pIDropTarget->AddRef();
} }
wxDropTarget::~wxDropTarget() wxDropTarget::~wxDropTarget()
{ {
ReleaseInterface(m_pIDropTarget); ReleaseInterface(m_pIDropTarget);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -280,140 +260,179 @@ wxDropTarget::~wxDropTarget()
bool wxDropTarget::Register(WXHWND hwnd) bool wxDropTarget::Register(WXHWND hwnd)
{ {
HRESULT hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE); HRESULT hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE);
if ( FAILED(hr) ) { if ( FAILED(hr) ) {
wxLogApiError("CoLockObjectExternal", hr); wxLogApiError("CoLockObjectExternal", hr);
return FALSE; return FALSE;
} }
hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget); hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
if ( FAILED(hr) ) { if ( FAILED(hr) ) {
::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE); ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
wxLogApiError("RegisterDragDrop", hr); wxLogApiError("RegisterDragDrop", hr);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
void wxDropTarget::Revoke(WXHWND hwnd) void wxDropTarget::Revoke(WXHWND hwnd)
{ {
HRESULT hr = ::RevokeDragDrop((HWND) hwnd); HRESULT hr = ::RevokeDragDrop((HWND) hwnd);
if ( FAILED(hr) ) { if ( FAILED(hr) ) {
wxLogApiError("RevokeDragDrop", hr); wxLogApiError("RevokeDragDrop", hr);
} }
::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE); ::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// determine if we accept data of this type // base class pure virtuals
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// OnDrop() is called only if we previously returned TRUE from
// IsAcceptedData(), so no need to check anything here
bool wxDropTarget::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
{
return TRUE;
}
// copy the data from the data source to the target data object
bool wxDropTarget::GetData()
{
wxDataFormat format = GetSupportedFormat(m_pIDataSource);
if ( format == wxDF_INVALID ) {
// this is strange because IsAcceptedData() succeeded previously!
wxFAIL_MSG(wxT("strange - did supported formats list change?"));
return FALSE;
}
STGMEDIUM stm;
FORMATETC fmtMemory;
fmtMemory.cfFormat = format;
fmtMemory.ptd = NULL;
fmtMemory.dwAspect = DVASPECT_CONTENT;
fmtMemory.lindex = -1;
fmtMemory.tymed = TYMED_HGLOBAL; // TODO to add other media
bool rc = FALSE;
HRESULT hr = m_pIDataSource->GetData(&fmtMemory, &stm);
if ( SUCCEEDED(hr) ) {
IDataObject *dataObject = m_dataObject->GetInterface();
hr = dataObject->SetData(&fmtMemory, &stm, TRUE);
if ( SUCCEEDED(hr) ) {
rc = TRUE;
}
else {
wxLogLastError("IDataObject::SetData()");
}
}
else {
wxLogLastError("IDataObject::GetData()");
}
return rc;
}
// ----------------------------------------------------------------------------
// callbacks used by wxIDropTarget
// ----------------------------------------------------------------------------
// we need a data source, so wxIDropTarget gives it to us using this function
void wxDropTarget::SetDataSource(IDataObject *pIDataSource)
{
m_pIDataSource = pIDataSource;
}
// determine if we accept data of this type
bool wxDropTarget::IsAcceptedData(IDataObject *pIDataSource) const bool wxDropTarget::IsAcceptedData(IDataObject *pIDataSource) const
{ {
// this strucutre describes a data of any type (first field will be return GetSupportedFormat(pIDataSource) != wxDF_INVALID;
// changing) being passed through global memory block.
static FORMATETC s_fmtMemory = {
0,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL
};
// cycle thorugh all supported formats
for ( size_t n = 0; n < GetFormatCount(); n++ ) {
s_fmtMemory.cfFormat = GetFormat(n);
// NB: don't use SUCCEEDED macro here: QueryGetData returns 1 (whatever it
// means) for file drag and drop
if ( pIDataSource->QueryGetData(&s_fmtMemory) == S_OK ) {
// remember this format: we'll later ask for data in it
m_pIDropTarget->SetSupportedFormat((unsigned int)s_fmtMemory.cfFormat);
return TRUE;
}
}
return FALSE;
} }
// ============================================================================ // ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const
{
// this strucutre describes a data of any type (first field will be
// changing) being passed through global memory block.
static FORMATETC s_fmtMemory = {
0,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL // TODO is it worth supporting other tymeds here?
};
// get the list of supported formats
size_t nFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
wxDataFormat format, *formats;
formats = nFormats == 1 ? &format : new wxDataFormat[nFormats];
m_dataObject->GetAllFormats(formats, wxDataObject::Set);
// cycle through all supported formats
size_t n;
for ( n = 0; n < nFormats; n++ ) {
s_fmtMemory.cfFormat = formats[n];
// NB: don't use SUCCEEDED macro here: QueryGetData returns S_FALSE
// for file drag and drop (format == CF_HDROP)
if ( pIDataSource->QueryGetData(&s_fmtMemory) == S_OK ) {
format = formats[n];
break;
}
}
if ( formats != &format ) {
// free memory if we allocated it
delete [] formats;
}
return n < nFormats ? format : wxDF_INVALID;
}
// ----------------------------------------------------------------------------
// wxTextDropTarget // wxTextDropTarget
// ============================================================================ // ----------------------------------------------------------------------------
bool wxTextDropTarget::OnDrop(long x, long y, const void *pData) wxTextDropTarget::wxTextDropTarget()
: wxDropTarget(new wxTextDataObject)
{ {
return OnDropText(x, y, (const wxChar *)pData);
} }
size_t wxTextDropTarget::GetFormatCount() const bool wxTextDropTarget::OnData(wxCoord x, wxCoord y)
{ {
return 1; if ( !GetData() )
return FALSE;
return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText());
} }
wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const // ----------------------------------------------------------------------------
{
return wxDF_TEXT;
}
// ============================================================================
// wxFileDropTarget // wxFileDropTarget
// ============================================================================ // ----------------------------------------------------------------------------
bool wxFileDropTarget::OnDrop(long x, long y, const void *pData) wxFileDropTarget::wxFileDropTarget()
: wxDropTarget(new wxFileDataObject)
{ {
// the documentation states that the first member of DROPFILES structure
// is a "DWORD offset of double NUL terminated file list". What they mean by
// this (I wonder if you see it immediately) is that the list starts at
// ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised to
// use DragQueryFile to work with this structure, but not told where and how
// to get HDROP.
HDROP hdrop = (HDROP)pData; // NB: it works, but I'm not sure about it
// get number of files (magic value -1)
UINT nFiles = ::DragQueryFile(hdrop, (unsigned)-1, NULL, 0u);
// for each file get the length, allocate memory and then get the name
wxChar **aszFiles = new wxChar *[nFiles];
UINT len, n;
for ( n = 0; n < nFiles; n++ ) {
// +1 for terminating NUL
len = ::DragQueryFile(hdrop, n, NULL, 0) + 1;
aszFiles[n] = new wxChar[len];
UINT len2 = ::DragQueryFile(hdrop, n, aszFiles[n], len);
if ( len2 != len - 1 ) {
wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned %d "
"characters, %d expected."), len2, len - 1);
}
}
bool bResult = OnDropFiles(x, y, nFiles, (const wxChar**) aszFiles);
// free memory
for ( n = 0; n < nFiles; n++ ) {
delete [] aszFiles[n];
}
delete [] aszFiles;
return bResult;
} }
size_t wxFileDropTarget::GetFormatCount() const bool wxFileDropTarget::OnData(wxCoord x, wxCoord y)
{ {
return 1; if ( !GetData() )
} return FALSE;
wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const return OnDropFiles(x, y,
{ ((wxFileDataObject *)m_dataObject)->GetFilenames());
#ifdef __WIN32__
return wxDF_FILENAME;
#else
// TODO: how to implement this in WIN16?
return wxDF_TEXT;
#endif
} }
#endif #endif

View File

@@ -54,9 +54,8 @@
#include "wx/ownerdrw.h" #include "wx/ownerdrw.h"
#endif #endif
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
#include "wx/dataobj.h" #include "wx/dnd.h"
#include "wx/msw/ole/droptgt.h"
#endif #endif
#include "wx/menuitem.h" #include "wx/menuitem.h"
@@ -1215,7 +1214,7 @@ void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
wxSize size(-1, -1); wxSize size(-1, -1);
if ( width == -1 ) if ( width == -1 )
{ {
if ( sizeFlags && wxSIZE_AUTO_WIDTH ) if ( sizeFlags & wxSIZE_AUTO_WIDTH )
{ {
size = DoGetBestSize(); size = DoGetBestSize();
width = size.x; width = size.x;
@@ -1229,7 +1228,7 @@ void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
if ( height == -1 ) if ( height == -1 )
{ {
if ( sizeFlags && wxSIZE_AUTO_HEIGHT ) if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
{ {
if ( size.x == -1 ) if ( size.x == -1 )
{ {