{
public:
bool OnInit()
- { wxTheClipboard = new wxClipboard; }
+ { wxTheClipboard = new wxClipboard; return TRUE; }
void OnExit()
{ delete wxTheClipboard; wxTheClipboard = (wxClipboard *)NULL; }
// get data from the buffer of specified length (in the given format),
// return TRUE if the data was read successfully, FALSE otherwise
virtual bool SetData(const wxDataFormat& format,
- size_t len, const void *buf) = 0;
+ size_t len, const void *buf)
+ {
+ return FALSE;
+ }
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// 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
{
public:
- // ctor: you can specify the bitmap here or in SetBitmap(), or override
- // GetBitmap()
+ // ctor: use AddFile() later to fill the array
wxFileDataObjectBase() : wxDataObjectSimple(wxDF_FILENAME) { }
- // get a reference to our array - you may modify it (i.e. add/remove
- // filenames to it then)
- wxArrayString& GetFilenames() { return m_filenames; }
+ // get a reference to our array
+ const wxArrayString& GetFilenames() { return m_filenames; }
- // a helper function
- void AddFile(const wxString& filename) { m_filenames.Add(filename); }
+ // the Get() functions do nothing for us
+ 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
- // 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:
+protected:
wxArrayString m_filenames;
};
#define wxTOOL_LEFT 3
#define wxTOOL_RIGHT 4
-
-// tyhe ids of standard data formats
+// the values of the format constants should be the same as correspondign
+// CF_XXX constants in Windows API
enum wxDataFormatId
{
- wxDF_INVALID = 0,
- wxDF_TEXT = 1, /* CF_TEXT */
- wxDF_BITMAP = 2, /* CF_BITMAP */
- wxDF_METAFILE = 3, /* CF_METAFILEPICT */
- wxDF_SYLK = 4,
- wxDF_DIF = 5,
- wxDF_TIFF = 6,
- wxDF_OEMTEXT = 7, /* CF_OEMTEXT */
- wxDF_DIB = 8, /* CF_DIB */
- wxDF_PALETTE = 9,
- wxDF_PENDATA = 10,
- wxDF_RIFF = 11,
- wxDF_WAVE = 12,
- wxDF_UNICODETEXT = 13,
- wxDF_ENHMETAFILE = 14,
- wxDF_FILENAME = 15, /* CF_HDROP */
- wxDF_LOCALE = 16,
- wxDF_PRIVATE = 20,
- wxDF_MAX
+ wxDF_INVALID = 0,
+ wxDF_TEXT = 1, /* CF_TEXT */
+ wxDF_BITMAP = 2, /* CF_BITMAP */
+ wxDF_METAFILE = 3, /* CF_METAFILEPICT */
+ wxDF_SYLK = 4,
+ wxDF_DIF = 5,
+ wxDF_TIFF = 6,
+ wxDF_OEMTEXT = 7, /* CF_OEMTEXT */
+ wxDF_DIB = 8, /* CF_DIB */
+ wxDF_PALETTE = 9,
+ wxDF_PENDATA = 10,
+ wxDF_RIFF = 11,
+ wxDF_WAVE = 12,
+ wxDF_UNICODETEXT = 13,
+ wxDF_ENHMETAFILE = 14,
+ wxDF_FILENAME = 15, /* CF_HDROP */
+ wxDF_LOCALE = 16,
+ wxDF_PRIVATE = 20,
+ wxDF_MAX
};
/* Virtual keycodes */
// start drag action, see enum wxDragResult for return value description
//
// 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
// "effect"
// ----------------------------------------------------------------------------
// 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
// called after OnDrop() returns TRUE: you will usually just call
// GetData() from here and, probably, also refresh something to update the
// 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
// with the data from the drop source if it returns TRUE
wxDataObject *m_dataObject;
};
+// ----------------------------------------------------------------------------
+// the platform-specific headers also define standard wxDropTarget
+// implementations wxTextDropTarget and wxFileDropTarget
+// ----------------------------------------------------------------------------
+
// ----------------------------------------------------------------------------
// include platform dependent class declarations
// ----------------------------------------------------------------------------
#if defined(__WXMSW__)
- #include "wx/dataobj.h"
#include "wx/msw/ole/dropsrc.h"
#include "wx/msw/ole/droptgt.h"
#elif defined(__WXMOTIF__)
#pragma interface
#endif
-#include "wx/defs.h"
-
#if wxUSE_DRAG_AND_DROP
#include "wx/object.h"
class wxDropTarget: public wxObject
{
public:
- wxDropTarget( wxDataObject *data );
- ~wxDropTarget();
- /* may be overridden to react to events */
- virtual bool OnEnter( int x, int y );
-
- virtual void OnLeave();
+ wxDropTarget();
+ ~wxDropTarget();
+
+ /* may be overridden to react to events */
+ virtual void OnEnter();
+ virtual void OnLeave();
+
+ /* may be overridden to reject certain formats or drops
+ on certain areas. always returns TRUE by default
+ indicating that you'd accept the data from the drag. */
+ virtual bool OnMove( long x, long y );
+
+ /* has to be overridden to accept a drop event. call
+ IsSupported() to ask which formats are available
+ and then call RequestData() to indicate the format
+ you request. */
+ virtual bool OnDrop( long x, long y );
- /* may be overridden to reject certain formats or drops
- on certain areas. always returns TRUE by default
- indicating that you'd accept the data from the drag. */
- virtual bool OnMove( int x, int y );
+ /* this gets called once the data has actually arrived. get
+ it with GetData(). this has to be overridden. */
+ virtual bool OnData( long x, long y );
- /* has to be overridden to accept a drop event. call
- IsSupported() to ask which formats are available
- and then call RequestData() to indicate the format
- you request. */
- virtual bool OnDrop( int x, int y );
+ /* called from within OnDrop() to request a certain format
+ from the drop event. */
+ bool RequestData( wxDataFormat format );
- /* this gets called once the data has actually arrived.
- it will call GetData() to fill up its wxDataObject */
- virtual bool OnData( int x, int y );
+ /* called to query what formats are available */
+ bool IsSupported( wxDataFormat format );
- /* fill data with data from the dragging source */
- bool GetData();
+ /* 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
- GdkAtom GetMatchingPair();
+ void RegisterWidget( GtkWidget *widget );
+ void UnregisterWidget( GtkWidget *widget );
+
+ GdkDragContext *m_dragContext;
+ GtkWidget *m_dragWidget;
+ GtkSelectionData *m_dragData;
+ 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; }
+ void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
+ void SetDragTime( guint time ) { m_dragTime = time; }
+};
+
+//-------------------------------------------------------------------------
+// wxTextDropTarget
+//-------------------------------------------------------------------------
- void RegisterWidget( GtkWidget *widget );
- void UnregisterWidget( GtkWidget *widget );
+class wxTextDropTarget: public wxDropTarget
+{
+public:
- wxDataObject *m_data;
- GdkDragContext *m_dragContext;
- GtkWidget *m_dragWidget;
- GtkSelectionData *m_dragData;
- guint m_dragTime;
- bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
+ wxTextDropTarget() {}
- void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
- void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
- void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
- void SetDragTime( guint time ) { m_dragTime = time; }
+ 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; }
};
//-------------------------------------------------------------------------
-// wxDropSource
+// wxPrivateDropTarget
//-------------------------------------------------------------------------
-enum wxDragResult
+/*
+class wxPrivateDropTarget: public wxDropTarget
{
- 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)
+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;
};
+*/
-class wxDropSource: public wxObject
+//----------------------------------------------------------------------------
+// A drop target which accepts files (dragged from File Manager or Explorer)
+//----------------------------------------------------------------------------
+
+class wxFileDropTarget: public wxDropTarget
{
public:
- /* constructor. set data later with SetData() */
- wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
+ wxFileDropTarget() {}
+
+ virtual bool OnData( long x, long y );
- wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
- ~wxDropSource();
+ 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; }
+};
- void SetData( wxDataObject& data );
+//-------------------------------------------------------------------------
+// wxDropSource
+//-------------------------------------------------------------------------
+
+class wxDropSource: public wxObject
+{
+public:
+ /* constructor. set data later with SetData() */
+ wxDropSource( wxWindow *win,
+ const wxIcon &go = wxNullIcon,
+ const wxIcon &stop = wxNullIcon );
- /* start drag action */
- wxDragResult DoDragDrop( bool bAllowMove = FALSE );
+ /* constructor for setting one data object */
+ wxDropSource( wxDataObject& data,
+ wxWindow *win,
+ const wxIcon &go = wxNullIcon,
+ const wxIcon &stop = wxNullIcon );
- /* override to give feedback */
- virtual bool GiveFeedback( wxDragResult WXUNUSED(effect), bool WXUNUSED(bScrolling) ) { return TRUE; }
+ ~wxDropSource();
- /* GTK implementation */
+ /* start drag action */
+ virtual wxDragResult DoDragDrop( bool bAllowMove = FALSE );
- void RegisterWindow();
- void UnregisterWindow();
+ /* GTK implementation */
+ void RegisterWindow();
+ void UnregisterWindow();
GtkWidget *m_widget;
wxWindow *m_window;
#pragma interface
#endif
-#include "wx/defs.h"
-
#if wxUSE_DRAG_AND_DROP
#include "wx/object.h"
class wxDropTarget: public wxObject
{
public:
- wxDropTarget( wxDataObject *data );
- ~wxDropTarget();
- /* may be overridden to react to events */
- virtual bool OnEnter( int x, int y );
-
- virtual void OnLeave();
+ wxDropTarget();
+ ~wxDropTarget();
+
+ /* may be overridden to react to events */
+ virtual void OnEnter();
+ virtual void OnLeave();
+
+ /* may be overridden to reject certain formats or drops
+ on certain areas. always returns TRUE by default
+ indicating that you'd accept the data from the drag. */
+ virtual bool OnMove( long x, long y );
+
+ /* has to be overridden to accept a drop event. call
+ IsSupported() to ask which formats are available
+ and then call RequestData() to indicate the format
+ you request. */
+ virtual bool OnDrop( long x, long y );
- /* may be overridden to reject certain formats or drops
- on certain areas. always returns TRUE by default
- indicating that you'd accept the data from the drag. */
- virtual bool OnMove( int x, int y );
+ /* this gets called once the data has actually arrived. get
+ it with GetData(). this has to be overridden. */
+ virtual bool OnData( long x, long y );
- /* has to be overridden to accept a drop event. call
- IsSupported() to ask which formats are available
- and then call RequestData() to indicate the format
- you request. */
- virtual bool OnDrop( int x, int y );
+ /* called from within OnDrop() to request a certain format
+ from the drop event. */
+ bool RequestData( wxDataFormat format );
- /* this gets called once the data has actually arrived.
- it will call GetData() to fill up its wxDataObject */
- virtual bool OnData( int x, int y );
+ /* called to query what formats are available */
+ bool IsSupported( wxDataFormat format );
- /* fill data with data from the dragging source */
- bool GetData();
+ /* 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
- GdkAtom GetMatchingPair();
+ void RegisterWidget( GtkWidget *widget );
+ void UnregisterWidget( GtkWidget *widget );
+
+ GdkDragContext *m_dragContext;
+ GtkWidget *m_dragWidget;
+ GtkSelectionData *m_dragData;
+ 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; }
+ void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
+ void SetDragTime( guint time ) { m_dragTime = time; }
+};
+
+//-------------------------------------------------------------------------
+// wxTextDropTarget
+//-------------------------------------------------------------------------
- void RegisterWidget( GtkWidget *widget );
- void UnregisterWidget( GtkWidget *widget );
+class wxTextDropTarget: public wxDropTarget
+{
+public:
- wxDataObject *m_data;
- GdkDragContext *m_dragContext;
- GtkWidget *m_dragWidget;
- GtkSelectionData *m_dragData;
- guint m_dragTime;
- bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
+ wxTextDropTarget() {}
- void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
- void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
- void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
- void SetDragTime( guint time ) { m_dragTime = time; }
+ 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; }
};
//-------------------------------------------------------------------------
-// wxDropSource
+// wxPrivateDropTarget
//-------------------------------------------------------------------------
-enum wxDragResult
+/*
+class wxPrivateDropTarget: public wxDropTarget
{
- 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)
+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;
};
+*/
-class wxDropSource: public wxObject
+//----------------------------------------------------------------------------
+// A drop target which accepts files (dragged from File Manager or Explorer)
+//----------------------------------------------------------------------------
+
+class wxFileDropTarget: public wxDropTarget
{
public:
- /* constructor. set data later with SetData() */
- wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
+ wxFileDropTarget() {}
+
+ virtual bool OnData( long x, long y );
- wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
- ~wxDropSource();
+ 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; }
+};
- void SetData( wxDataObject& data );
+//-------------------------------------------------------------------------
+// wxDropSource
+//-------------------------------------------------------------------------
+
+class wxDropSource: public wxObject
+{
+public:
+ /* constructor. set data later with SetData() */
+ wxDropSource( wxWindow *win,
+ const wxIcon &go = wxNullIcon,
+ const wxIcon &stop = wxNullIcon );
- /* start drag action */
- wxDragResult DoDragDrop( bool bAllowMove = FALSE );
+ /* constructor for setting one data object */
+ wxDropSource( wxDataObject& data,
+ wxWindow *win,
+ const wxIcon &go = wxNullIcon,
+ const wxIcon &stop = wxNullIcon );
- /* override to give feedback */
- virtual bool GiveFeedback( wxDragResult WXUNUSED(effect), bool WXUNUSED(bScrolling) ) { return TRUE; }
+ ~wxDropSource();
- /* GTK implementation */
+ /* start drag action */
+ virtual wxDragResult DoDragDrop( bool bAllowMove = FALSE );
- void RegisterWindow();
- void UnregisterWindow();
+ /* GTK implementation */
+ void RegisterWindow();
+ void UnregisterWindow();
GtkWidget *m_widget;
wxWindow *m_window;
// wxDataObject is a "smart" and polymorphic piece of data.
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxDataObject
+class WXDLLEXPORT wxDataObject : public wxDataObjectBase
{
public:
// ctor & dtor
wxDataObject();
virtual ~wxDataObject();
- // pure virtuals to override
- // 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)
+ // retrieve IDataObject interface (for other OLE related classes)
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
// it is deleted, it should delete us as well
void SetAutoDelete();
+ // return TRUE if we support this format in "Get" direction
+ bool IsSupportedFormat(const wxDataFormat& format) const;
+
#ifdef __WXDEBUG__
// function to return symbolic name of clipboard format (for debug messages)
static const char *GetFormatName(wxDataFormat format);
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
-
// wxDataObject object. It's responsible for giving UI feedback while dragging.
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxDropSource
+class WXDLLEXPORT wxDropSource : public wxDropSourceBase
{
public:
// ctors: if you use default ctor you must call SetData() later!
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
-// ============================================================================
-// prolog
-// ============================================================================
#ifndef _WX_OLEDROPTGT_H
#define _WX_OLEDROPTGT_H
#endif
#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
// ----------------------------------------------------------------------------
// forward declarations
// ----------------------------------------------------------------------------
+
class wxIDropTarget;
struct IDataObject;
// 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)
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxDropTarget
+
+class WXDLLEXPORT wxDropTarget : public wxDropTargetBase
{
public:
// ctor & dtor
- wxDropTarget();
+ wxDropTarget(wxDataObject *dataObject = NULL);
virtual ~wxDropTarget();
// normally called by wxWindow on window creation/destruction, but might be
bool Register(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?
- virtual bool IsAcceptedData(IDataObject *pIDataSource) const;
-
- // called when mouse enters/leaves the window: might be used to give
- // some visual feedback to the user
- virtual void OnEnter() { }
- 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;
+ bool IsAcceptedData(IDataObject *pIDataSource) const;
+
+ // give us the data source from IDropTarget::Drop() - this is later used by
+ // GetData() when it's called from inside OnData()
+ void SetDataSource(IDataObject *pIDataSource);
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
// override OnDropText() to get something working
// ----------------------------------------------------------------------------
+
class WXDLLEXPORT wxTextDropTarget : public wxDropTarget
{
public:
- virtual bool OnDrop(long x, long y, const void *pData);
- virtual bool OnDropText(long x, long y, const wxChar *psz) = 0;
+ wxTextDropTarget();
-protected:
- virtual size_t GetFormatCount() const;
- virtual wxDataFormat GetFormat(size_t n) const;
+ virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) = 0;
+
+ virtual bool OnData(wxCoord x, wxCoord y);
};
// ----------------------------------------------------------------------------
// A drop target which accepts files (dragged from File Manager or Explorer)
// ----------------------------------------------------------------------------
+
class WXDLLEXPORT wxFileDropTarget : public wxDropTarget
{
public:
- virtual bool OnDrop(long x, long y, const void *pData);
+ wxFileDropTarget();
- // params: the number of files and the array of file names
- virtual bool OnDropFiles(long x, long y,
- size_t nFiles, const wxChar * const aszFiles[]) = 0;
+ // parameters are the number of files and the array of file names
+ virtual bool OnDropFiles(wxCoord x, wxCoord y,
+ const wxArrayString& filenames) = 0;
-protected:
- virtual size_t GetFormatCount() const;
- virtual wxDataFormat GetFormat(size_t n) const;
+ virtual bool OnData(wxCoord x, wxCoord y);
};
-// ============================================================================
#endif //_WX_OLEDROPTGT_H
// file names) we drop on them
// ----------------------------------------------------------------------------
-typedef long wxDropPointCoord;
-
class DnDText : public wxTextDropTarget
{
public:
DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
- virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y,
- const wxChar* psz);
+ virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text);
private:
wxListBox *m_pOwner;
public:
DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
- virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y,
- size_t nFiles, const wxChar* const aszFiles[] );
+ virtual bool OnDropFiles(wxCoord x, wxCoord y,
+ const wxArrayString& filenames);
private:
wxListBox *m_pOwner;
{
}
+ // 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
// some bitwise-copiable data (might use streams too...)
// ------------------------------------------------------------------------
{
}
+ virtual ~DnDTriangularShape()
+ {
+ wxLogMessage("DnDTriangularShape is being deleted");
+ }
+
virtual Kind GetKind() const { return Triangle; }
virtual void Draw(wxDC& dc)
{
{
}
+ virtual ~DnDRectangularShape()
+ {
+ wxLogMessage("DnDRectangularShape is being deleted");
+ }
+
virtual Kind GetKind() const { return Rectangle; }
virtual void Draw(wxDC& dc)
{
{
}
+ virtual ~DnDEllipticShape()
+ {
+ wxLogMessage("DnDEllipticShape is being deleted");
+ }
+
virtual Kind GetKind() const { return Ellipse; }
virtual void Draw(wxDC& dc)
{
public:
// ctor doesn't copy the pointer, so it shouldn't go away while this object
// 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
// arbitrary
m_hasBitmap = FALSE;
}
+ virtual ~DnDShapeDataObject() { delete m_shape; }
+
// accessors
DnDShape *GetShape() const { return m_shape; }
// implement base class pure virtuals
// ----------------------------------
- virtual wxDataFormat GetPreferredFormat() const
+ virtual wxDataFormat GetPreferredFormat(Direction WXUNUSED(dir)) const
{
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()
size_t nFormats = 1;
- if ( outputOnlyToo )
+ if ( dir == Get )
{
// but the bitmap format(s) are only supported for output
- nFormats += m_dataobj.GetFormatCount();
+ nFormats += m_dataobj.GetFormatCount(dir);
}
return nFormats;
}
- virtual void GetAllFormats(wxDataFormat *formats, bool outputOnlyToo) const
+ virtual void GetAllFormats(wxDataFormat *formats, Direction dir) const
{
formats[0] = m_formatShape;
- if ( outputOnlyToo )
+ if ( dir == Get )
{
- m_dataobj.GetAllFormats(&formats[1]);
+ m_dataobj.GetAllFormats(&formats[1], dir);
}
}
if ( !m_hasBitmap )
CreateBitmap();
- return m_dataobj.GetDataSize(format);
+ return m_dataobj.GetDataSize();
}
}
if ( !m_hasBitmap )
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" );
{
public:
DnDShapeDropTarget(DnDShapeFrame *frame)
+ : wxDropTarget(new DnDShapeDataObject)
{
m_frame = frame;
-
- // the same as used by DnDShapeDataObject
- m_formatShape.SetId(shapeFormatId);
}
// override base class (pure) virtuals
{ m_frame->SetStatusText("Mouse entered the frame"); }
virtual void OnLeave()
{ 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;
}
-protected:
- virtual size_t GetFormatCount() const { return 1; }
- virtual wxDataFormat GetFormat(size_t WXUNUSED(n)) const
- { return m_formatShape; }
-
private:
DnDShapeFrame *m_frame;
- wxDataFormat m_formatShape;
};
// ----------------------------------------------------------------------------
// 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;
}
-bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
- const wxChar* const aszFiles[])
+bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
{
+ size_t nFiles = filenames.GetCount();
wxString str;
str.Printf( _T("%d files dropped"), nFiles);
m_pOwner->Append(str);
for ( size_t n = 0; n < nFiles; n++ ) {
- m_pOwner->Append(aszFiles[n]);
+ m_pOwner->Append(filenames[n]);
}
return TRUE;
//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)
{
DnDShapeDialog dlg(this, m_shape);
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
// ----------------------------------------------------------------------------
#endif
#include "wx/thread.h"
+#include "wx/clipbrd.h"
// ===========================================================================
// implementation
// 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 str;
}
}
+#endif // 0
+
// ----------------------------------------------------------------------------
// wxCustomDataObject
// ----------------------------------------------------------------------------
return TRUE;
}
-bool wxCustomDataObject::SetData(size_t len, const void *buf)
+bool wxCustomDataObject::SetData(size_t size, const void *buf)
{
Free();
if ( !m_data )
return FALSE;
- memcpy(m_data, buf, m_size = len);
+ memcpy(m_data, buf, m_size = size);
return TRUE;
}
}
// build the list of supported formats
- size_t nFormats = data->GetFormatCount(FALSE /* for SetData() */);
+ size_t nFormats = data->GetFormatCount(wxDataObject::Set);
wxDataFormat format, *formats;
if ( nFormats == 1 )
{
formats = new wxDataFormat[nFormats];
}
- data->GetAllFormats(formats, FALSE);
+ data->GetAllFormats(formats, wxDataObject::Set);
// get the format enumerator
bool result = FALSE;
static const wxChar *GetTymedName(DWORD tymed);
#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
// ----------------------------------------------------------------------------
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);
if ( hGlobal == NULL ) {
wxLogLastError("GlobalAlloc");
case TYMED_HGLOBAL:
{
// copy data
- void *pBuf = GlobalLock(pmedium->hGlobal);
+ HGLOBAL hGlobal = pmedium->hGlobal;
+ void *pBuf = GlobalLock(hGlobal);
if ( pBuf == NULL ) {
wxLogLastError(wxT("GlobalLock"));
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) )
return E_UNEXPECTED;
- GlobalUnlock(pmedium->hGlobal);
+ GlobalUnlock(hGlobal);
}
break;
return S_OK;
}
-// set data functions (not implemented)
+// set data functions
STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
STGMEDIUM *pmedium,
BOOL fRelease)
switch ( pmedium->tymed )
{
case TYMED_GDI:
- m_pDataObject->SetData(wxDF_BITMAP, &pmedium->hBitmap);
+ m_pDataObject->SetData(wxDF_BITMAP, 0, &pmedium->hBitmap);
break;
case TYMED_MFPICT:
return E_OUTOFMEMORY;
}
- wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
- m_pDataObject->SetData(format, pBuf);
+ // 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 ( 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);
+
+ if ( !ok ) {
+ return E_UNEXPECTED;
+ }
}
break;
}
// and now check the type of data requested
- wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
+ wxDataFormat format = pformatetc->cfFormat;
if ( m_pDataObject->IsSupportedFormat(format) ) {
#ifdef __WXDEBUG__
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
#endif // Debug
}
else {
-#ifdef __WXDEBUG__
wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: %s unsupported"),
wxDataObject::GetFormatName(format));
-#endif
+
return DV_E_FORMATETC;
}
return DATA_S_SAMEFORMATETC;
}
-STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
+STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDir,
IEnumFORMATETC **ppenumFormatEtc)
{
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;
- if ( nFormatCount == 1 ) {
- // this is the most common case, this is why we consider it separately
- formats = &format;
- format = m_pDataObject->GetPreferredFormat();
- }
- else {
- // bad luck, build the array with all formats
- formats = new wxDataFormat[nFormatCount];
- m_pDataObject->GetAllFormats(formats, allowOutputOnly);
- }
+ formats = nFormatCount == 1 ? &format : new wxDataFormat[nFormatCount];
+ m_pDataObject->GetAllFormats(formats, dir);
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
pEnum->AddRef();
return S_OK;
}
+// ----------------------------------------------------------------------------
// advise sink functions (not implemented)
+// ----------------------------------------------------------------------------
+
STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
DWORD advf,
IAdviseSink *pAdvSink,
#endif // Debug
// ----------------------------------------------------------------------------
-// wxPrivateDataObject
+// wxBitmapDataObject supports CF_DIB format
// ----------------------------------------------------------------------------
-wxPrivateDataObject::wxPrivateDataObject()
+size_t wxBitmapDataObject::GetDataSize() const
{
- m_size = 0;
- m_data = NULL;
+ return wxConvertBitmapToDIB(NULL, GetBitmap());
}
-void wxPrivateDataObject::Free()
+bool wxBitmapDataObject::GetDataHere(void *buf) const
{
- if ( m_data )
- free(m_data);
+ return wxConvertBitmapToDIB((BITMAPINFO *)buf, GetBitmap()) != 0;
}
-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));
+
+ if ( !bitmap.Ok() ) {
+ wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
- m_size = size;
- m_data = malloc(size);
+ return FALSE;
+ }
+
+ SetBitmap(bitmap);
- memcpy( m_data, data, size );
+ return TRUE;
}
-void wxPrivateDataObject::WriteData( void *dest ) const
+// ----------------------------------------------------------------------------
+// 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
{
- WriteData( m_data, dest );
+ return 0;
}
-size_t wxPrivateDataObject::GetSize() const
+bool wxBitmapDataObject2::GetDataHere(void *pBuf) const
{
- return m_size;
+ // we put a bitmap handle into pBuf
+ *(WXHBITMAP *)pBuf = GetBitmap().GetHBITMAP();
+
+ return TRUE;
}
-void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
+bool wxBitmapDataObject2::SetData(size_t len, const void *pBuf)
{
- memcpy( dest, data, GetSize() );
-}
+ HBITMAP hbmp = *(HBITMAP *)pBuf;
-// ----------------------------------------------------------------------------
-// wxBitmapDataObject: it supports standard CF_BITMAP and CF_DIB formats
-// ----------------------------------------------------------------------------
+ BITMAP bmp;
+ if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
+ {
+ wxLogLastError("GetObject(HBITMAP)");
+ }
-size_t wxBitmapDataObject::GetFormatCount(bool outputOnlyToo) const
-{
- return 2;
-}
+ wxBitmap bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes);
+ bitmap.SetHBITMAP((WXHBITMAP)hbmp);
-void wxBitmapDataObject::GetAllFormats(wxDataFormat *formats,
- bool outputOnlyToo) const
-{
- formats[0] = CF_BITMAP;
- formats[1] = CF_DIB;
+ if ( !bitmap.Ok() ) {
+ wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
+
+ return FALSE;
+ }
+
+ SetBitmap(bitmap);
+
+ return TRUE;
}
-// 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
-// another application or whatever), but by handle, so these generic functions
-// don't make much sense to them.
+#if 0
size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
{
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;
if ( format.GetFormatId() == CF_DIB )
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
// ----------------------------------------------------------------------------
+// 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__
static const wxChar *GetTymedName(DWORD tymed)
#if wxUSE_DRAG_AND_DROP
#include "wx/log.h"
-#include "wx/dataobj.h"
-#include "wx/msw/ole/dropsrc.h"
+#include "wx/dnd.h"
#include <windows.h>
+
#ifdef wxUSE_NORLANDER_HEADERS
-#include <ole2.h>
+ #include <ole2.h>
#endif
#ifndef __WIN32__
- #include <ole2.h>
- #include <olestd.h>
+ #include <ole2.h>
+ #include <olestd.h>
#endif
#include <oleauto.h>
const wxIcon & WXUNUSED(stop))
{
Init();
- m_pData = NULL;
}
wxDropSource::wxDropSource(wxDataObject& data,
// Notes : you must call SetData() before if you had used def ctor
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;
- HRESULT hr = ::DoDragDrop(m_pData->GetInterface(),
+ HRESULT hr = ::DoDragDrop(m_data->GetInterface(),
m_pIDropSource,
bAllowMove ? DROPEFFECT_COPY | DROPEFFECT_MOVE
: DROPEFFECT_COPY,
#include <shellapi.h>
#endif
-#include "wx/dataobj.h"
-#include "wx/msw/ole/droptgt.h"
+#include "wx/dnd.h"
#ifndef __WIN32__
#include <ole2.h>
STDMETHODIMP DragLeave(void);
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;
protected:
IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop
wxDropTarget *m_pTarget; // the real target (we're just a proxy)
- wxDataFormat m_cfFormat; // the format in which to ask for data
-
private:
static inline DWORD GetDropEffect(DWORD flags);
};
{
m_cRef = 0;
m_pTarget = pTarget;
- m_cfFormat = wxDF_INVALID;
m_pIDataObject = NULL;
}
POINTL pt,
DWORD *pdwEffect)
{
- wxLogDebug(wxT("IDropTarget::Drop"));
-
- // 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
- wxASSERT( m_pIDataObject == pIDataSource );
-
- STGMEDIUM stm;
- *pdwEffect = DROPEFFECT_NONE;
-
- // should be set by SetSupportedFormat() call
- wxASSERT( m_cfFormat != wxDF_INVALID );
-
- FORMATETC fmtMemory;
- fmtMemory.cfFormat = m_cfFormat;
- fmtMemory.ptd = NULL;
- fmtMemory.dwAspect = DVASPECT_CONTENT;
- fmtMemory.lindex = -1;
- fmtMemory.tymed = TYMED_HGLOBAL; // TODO to add other media
-
- 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);
+ wxLogDebug(wxT("IDropTarget::Drop"));
+
+ // 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
+ wxASSERT( m_pIDataObject == pIDataSource );
+
+ // by default, nothing happens
+ *pdwEffect = DROPEFFECT_NONE;
+
+ // first ask the drop target if it wants data
+ if ( m_pTarget->OnDrop(pt.x, pt.y) ) {
+ // it does, so give it the data source
+ m_pTarget->SetDataSource(pIDataSource);
+
+ // and now it has the data
+ if ( m_pTarget->OnData(pt.x, pt.y) ) {
+ // operation succeeded
+ *pdwEffect = GetDropEffect(grfKeyState);
+ }
+ //else: *pdwEffect is already DROPEFFECT_NONE
}
- }
- else
- {
- // wxLogApiError("GetData", hr);
- }
+ //else: OnDrop() returned FALSE, no need to copy data
- // release the held object
- RELEASE_AND_NULL(m_pIDataObject);
+ // release the held object
+ RELEASE_AND_NULL(m_pIDataObject);
- return S_OK;
+ return S_OK;
}
// ============================================================================
// ctor/dtor
// ----------------------------------------------------------------------------
-wxDropTarget::wxDropTarget()
+wxDropTarget::wxDropTarget(wxDataObject *dataObj)
+ : wxDropTargetBase(dataObj)
{
- // create an IDropTarget implementation which will notify us about
- // d&d operations.
- m_pIDropTarget = new wxIDropTarget(this);
- m_pIDropTarget->AddRef();
+ // create an IDropTarget implementation which will notify us about d&d
+ // operations.
+ m_pIDropTarget = new wxIDropTarget(this);
+ m_pIDropTarget->AddRef();
}
wxDropTarget::~wxDropTarget()
{
- ReleaseInterface(m_pIDropTarget);
+ ReleaseInterface(m_pIDropTarget);
}
// ----------------------------------------------------------------------------
bool wxDropTarget::Register(WXHWND hwnd)
{
- HRESULT hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE);
- if ( FAILED(hr) ) {
- wxLogApiError("CoLockObjectExternal", hr);
- return FALSE;
- }
+ HRESULT hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE);
+ if ( FAILED(hr) ) {
+ wxLogApiError("CoLockObjectExternal", hr);
+ return FALSE;
+ }
- hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
- if ( FAILED(hr) ) {
- ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
+ hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
+ if ( FAILED(hr) ) {
+ ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
- wxLogApiError("RegisterDragDrop", hr);
- return FALSE;
- }
+ wxLogApiError("RegisterDragDrop", hr);
+ return FALSE;
+ }
- return TRUE;
+ return TRUE;
}
void wxDropTarget::Revoke(WXHWND hwnd)
{
- HRESULT hr = ::RevokeDragDrop((HWND) hwnd);
+ HRESULT hr = ::RevokeDragDrop((HWND) hwnd);
- if ( FAILED(hr) ) {
- wxLogApiError("RevokeDragDrop", hr);
- }
+ if ( FAILED(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
// ----------------------------------------------------------------------------
-bool wxDropTarget::IsAcceptedData(IDataObject *pIDataSource) const
+
+// 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()
{
- // 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
- };
-
- // 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;
+ 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 FALSE;
+ return rc;
}
-// ============================================================================
-// wxTextDropTarget
-// ============================================================================
+// ----------------------------------------------------------------------------
+// callbacks used by wxIDropTarget
+// ----------------------------------------------------------------------------
-bool wxTextDropTarget::OnDrop(long x, long y, const void *pData)
+// we need a data source, so wxIDropTarget gives it to us using this function
+void wxDropTarget::SetDataSource(IDataObject *pIDataSource)
{
- return OnDropText(x, y, (const wxChar *)pData);
+ m_pIDataSource = pIDataSource;
}
-size_t wxTextDropTarget::GetFormatCount() const
+// determine if we accept data of this type
+bool wxDropTarget::IsAcceptedData(IDataObject *pIDataSource) const
{
- return 1;
+ return GetSupportedFormat(pIDataSource) != wxDF_INVALID;
}
-wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
+// ----------------------------------------------------------------------------
+// helper functions
+// ----------------------------------------------------------------------------
+
+wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const
{
- return wxDF_TEXT;
+ // 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;
}
-// ============================================================================
-// wxFileDropTarget
-// ============================================================================
+// ----------------------------------------------------------------------------
+// wxTextDropTarget
+// ----------------------------------------------------------------------------
-bool wxFileDropTarget::OnDrop(long x, long y, const void *pData)
+wxTextDropTarget::wxTextDropTarget()
+ : wxDropTarget(new wxTextDataObject)
{
- // 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;
+bool wxTextDropTarget::OnData(wxCoord x, wxCoord y)
+{
+ if ( !GetData() )
+ return FALSE;
- return bResult;
+ return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText());
}
-size_t wxFileDropTarget::GetFormatCount() const
+// ----------------------------------------------------------------------------
+// wxFileDropTarget
+// ----------------------------------------------------------------------------
+
+wxFileDropTarget::wxFileDropTarget()
+ : wxDropTarget(new wxFileDataObject)
{
- return 1;
}
-wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
+bool wxFileDropTarget::OnData(wxCoord x, wxCoord y)
{
-#ifdef __WIN32__
- return wxDF_FILENAME;
-#else
- // TODO: how to implement this in WIN16?
- return wxDF_TEXT;
-#endif
+ if ( !GetData() )
+ return FALSE;
+
+ return OnDropFiles(x, y,
+ ((wxFileDataObject *)m_dataObject)->GetFilenames());
}
#endif
#include "wx/ownerdrw.h"
#endif
-#if wxUSE_DRAG_AND_DROP
- #include "wx/dataobj.h"
- #include "wx/msw/ole/droptgt.h"
+#if wxUSE_DRAG_AND_DROP
+ #include "wx/dnd.h"
#endif
#include "wx/menuitem.h"
wxSize size(-1, -1);
if ( width == -1 )
{
- if ( sizeFlags && wxSIZE_AUTO_WIDTH )
+ if ( sizeFlags & wxSIZE_AUTO_WIDTH )
{
size = DoGetBestSize();
width = size.x;
if ( height == -1 )
{
- if ( sizeFlags && wxSIZE_AUTO_HEIGHT )
+ if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
{
if ( size.x == -1 )
{