1. wxPostEvent added and documented
2. Made it possible to have wxDataObjects which support multiple formats painlessly 3. Extensively modified dnd sample to show a "real life" wxDataObject git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4028 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -9,6 +9,14 @@
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "event.h"
|
||||
#endif
|
||||
@@ -38,6 +46,10 @@
|
||||
#include "wx/validate.h"
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxWin macros
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !USE_SHARED_LIBRARY
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject)
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
|
||||
@@ -84,12 +96,26 @@
|
||||
|
||||
#endif // !USE_SHARED_LIBRARY
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// global variables
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// To put pending event handlers
|
||||
wxList *wxPendingEvents = (wxList *)NULL;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
/* To put pending event handlers */
|
||||
extern wxList *wxPendingEvents;
|
||||
extern wxCriticalSection *wxPendingEventsLocker;
|
||||
// protects wxPendingEvents list
|
||||
wxCriticalSection *wxPendingEventsLocker = (wxCriticalSection *)NULL;
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEvent
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* General wxWindows events, covering
|
||||
* all interesting things that might happen (button clicking, resizing,
|
||||
@@ -514,10 +540,10 @@ wxEvtHandler::wxEvtHandler()
|
||||
m_enabled = TRUE;
|
||||
m_dynamicEvents = (wxList *) NULL;
|
||||
m_isWindow = FALSE;
|
||||
#if wxUSE_THREADS
|
||||
m_eventsLocker = new wxCriticalSection();
|
||||
#endif
|
||||
m_pendingEvents = (wxList *) NULL;
|
||||
#if wxUSE_THREADS
|
||||
m_eventsLocker = new wxCriticalSection;
|
||||
#endif
|
||||
}
|
||||
|
||||
wxEvtHandler::~wxEvtHandler()
|
||||
@@ -542,63 +568,76 @@ wxEvtHandler::~wxEvtHandler()
|
||||
delete m_dynamicEvents;
|
||||
};
|
||||
|
||||
#if wxUSE_THREADS
|
||||
if (m_pendingEvents)
|
||||
delete m_pendingEvents;
|
||||
delete m_pendingEvents;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
delete m_eventsLocker;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
|
||||
#ifdef __WXGTK__
|
||||
extern bool g_isIdle;
|
||||
extern void wxapp_install_idle_handler();
|
||||
#endif
|
||||
|
||||
bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
|
||||
{
|
||||
wxEvent *event_main;
|
||||
wxCriticalSectionLocker locker(*m_eventsLocker);
|
||||
|
||||
// check that we are really in a child thread
|
||||
wxASSERT( !wxThread::IsMain() );
|
||||
wxASSERT_MSG( !wxThread::IsMain(),
|
||||
wxT("use ProcessEvent() in main thread") );
|
||||
|
||||
if (m_pendingEvents == NULL)
|
||||
m_pendingEvents = new wxList();
|
||||
AddPendingEvent(event);
|
||||
|
||||
event_main = (wxEvent *)event.Clone();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
m_pendingEvents->Append(event_main);
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
void wxEvtHandler::AddPendingEvent(wxEvent& event)
|
||||
{
|
||||
if ( !m_pendingEvents )
|
||||
m_pendingEvents = new wxList;
|
||||
|
||||
wxEvent *event2 = (wxEvent *)event.Clone();
|
||||
|
||||
m_pendingEvents->Append(event2);
|
||||
|
||||
wxPendingEventsLocker->Enter();
|
||||
if ( !wxPendingEvents )
|
||||
wxPendingEvents = new wxList;
|
||||
wxPendingEvents->Append(this);
|
||||
wxPendingEventsLocker->Leave();
|
||||
|
||||
// TODO: Wake up idle handler for the other platforms.
|
||||
#ifdef __WXGTK__
|
||||
if (g_isIdle)
|
||||
extern bool g_isIdle;
|
||||
extern void wxapp_install_idle_handler();
|
||||
if ( g_isIdle )
|
||||
wxapp_install_idle_handler();
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
#else // this works for wxMSW, but may be for others too?
|
||||
// might also send a dummy message to the top level window, this would
|
||||
// probably be cleaner?
|
||||
wxIdleEvent eventIdle;
|
||||
wxTheApp->OnIdle(eventIdle);
|
||||
#endif // platform
|
||||
}
|
||||
|
||||
void wxEvtHandler::ProcessPendingEvents()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxCriticalSectionLocker locker(*m_eventsLocker);
|
||||
#endif
|
||||
|
||||
wxNode *node = m_pendingEvents->First();
|
||||
wxEvent *event;
|
||||
|
||||
while (node != NULL) {
|
||||
event = (wxEvent *)node->Data();
|
||||
ProcessEvent(*event);
|
||||
delete node;
|
||||
node = m_pendingEvents->First();
|
||||
while ( node )
|
||||
{
|
||||
event = (wxEvent *)node->Data();
|
||||
ProcessEvent(*event);
|
||||
delete node;
|
||||
node = m_pendingEvents->First();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Event table stuff
|
||||
@@ -607,25 +646,24 @@ void wxEvtHandler::ProcessPendingEvents()
|
||||
bool wxEvtHandler::ProcessEvent(wxEvent& event)
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
/* check that our flag corresponds to reality */
|
||||
// check that our flag corresponds to reality
|
||||
wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) );
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
/* An event handler can be enabled or disabled */
|
||||
// An event handler can be enabled or disabled
|
||||
if ( GetEvtHandlerEnabled() )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
/* Check whether we are in a child thread. */
|
||||
if (!wxThread::IsMain())
|
||||
// Check whether we are in a child thread.
|
||||
if ( !wxThread::IsMain() )
|
||||
return ProcessThreadEvent(event);
|
||||
#endif
|
||||
/* Handle per-instance dynamic event tables first */
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
// Handle per-instance dynamic event tables first
|
||||
if ( m_dynamicEvents && SearchDynamicEventTable(event) )
|
||||
return TRUE;
|
||||
|
||||
/* Then static per-class event tables */
|
||||
|
||||
// Then static per-class event tables
|
||||
const wxEventTable *table = GetEventTable();
|
||||
|
||||
#if wxUSE_GUI && wxUSE_VALIDATORS
|
||||
|
@@ -48,10 +48,6 @@
|
||||
wxApp *wxTheApp = (wxApp *) NULL;
|
||||
wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
extern wxList *wxPendingEvents;
|
||||
extern wxCriticalSection *wxPendingEventsLocker;
|
||||
#endif
|
||||
extern wxResourceCache *wxTheResourceCache;
|
||||
extern bool g_isIdle;
|
||||
|
||||
@@ -127,7 +123,7 @@ unsigned char g_palette[64*3] =
|
||||
// local functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern void wxFlushResources(void);
|
||||
extern void wxFlushResources();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// global functions
|
||||
@@ -265,6 +261,7 @@ static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -427,11 +424,9 @@ void wxApp::OnIdle( wxIdleEvent &event )
|
||||
|
||||
s_inOnIdle = TRUE;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
/* Resend in the main thread events which have been prepared in other
|
||||
threads */
|
||||
ProcessPendingEvents();
|
||||
#endif
|
||||
|
||||
/* 'Garbage' collection of windows deleted with Close(). */
|
||||
DeletePendingObjects();
|
||||
@@ -520,12 +515,16 @@ void wxApp::Dispatch()
|
||||
gtk_main_iteration();
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
void wxApp::ProcessPendingEvents()
|
||||
{
|
||||
wxNode *node = wxPendingEvents->First();
|
||||
#if wxUSE_THREADS
|
||||
wxCriticalSectionLocker locker(*wxPendingEventsLocker);
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
if ( !wxPendingEvents )
|
||||
return;
|
||||
|
||||
wxNode *node = wxPendingEvents->First();
|
||||
while (node)
|
||||
{
|
||||
wxEvtHandler *handler = (wxEvtHandler *)node->Data();
|
||||
@@ -537,7 +536,6 @@ void wxApp::ProcessPendingEvents()
|
||||
node = wxPendingEvents->First();
|
||||
}
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
void wxApp::DeletePendingObjects()
|
||||
{
|
||||
|
@@ -39,12 +39,6 @@ wxWindowList wxTopLevelWindows;
|
||||
/* List of windows pending deletion */
|
||||
wxList wxPendingDelete;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
/* List of events pending processing */
|
||||
wxList *wxPendingEvents = NULL;
|
||||
wxCriticalSection *wxPendingEventsLocker = NULL;
|
||||
#endif
|
||||
|
||||
/* Current cursor, in order to hang on to
|
||||
* cursor handle when setting the cursor globally */
|
||||
wxCursor g_globalCursor;
|
||||
|
@@ -651,7 +651,7 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget),
|
||||
/* disable GUI threads */
|
||||
wxapp_uninstall_thread_wakeup();
|
||||
#endif
|
||||
|
||||
|
||||
gtk_selection_data_set( selection_data,
|
||||
selection_data->target,
|
||||
8, // 8-bit
|
||||
@@ -745,7 +745,8 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop
|
||||
if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm );
|
||||
}
|
||||
|
||||
wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go, const wxIcon &stop )
|
||||
wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win,
|
||||
const wxIcon &go, const wxIcon &stop )
|
||||
{
|
||||
m_waiting = TRUE;
|
||||
|
||||
@@ -754,15 +755,8 @@ wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go,
|
||||
if (win->m_wxwindow) m_widget = win->m_wxwindow;
|
||||
m_retValue = wxDragCancel;
|
||||
|
||||
if (data)
|
||||
{
|
||||
m_data = new wxDataBroker();
|
||||
m_data->Add( data );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data = (wxDataBroker*) NULL;
|
||||
}
|
||||
m_data = new wxDataBroker;
|
||||
m_data->Add(&data);
|
||||
|
||||
m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
|
||||
m_goaheadCursor = wxCursor( wxCURSOR_HAND );
|
||||
@@ -786,6 +780,15 @@ wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win )
|
||||
m_goaheadCursor = wxCursor( wxCURSOR_HAND );
|
||||
}
|
||||
|
||||
void wxDropSource::SetData( wxDataObject& data )
|
||||
{
|
||||
if ( m_data )
|
||||
delete m_data;
|
||||
|
||||
m_data = new wxDataBroker;
|
||||
m_data->Add(&data);
|
||||
}
|
||||
|
||||
void wxDropSource::SetData( wxDataObject *data )
|
||||
{
|
||||
if (m_data) delete m_data;
|
||||
@@ -808,7 +811,7 @@ void wxDropSource::SetData( wxDataBroker *data )
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
wxDropSource::~wxDropSource(void)
|
||||
wxDropSource::~wxDropSource()
|
||||
{
|
||||
if (m_data) delete m_data;
|
||||
|
||||
@@ -854,7 +857,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
|
||||
/* disable GUI threads */
|
||||
wxapp_uninstall_thread_wakeup();
|
||||
#endif
|
||||
|
||||
|
||||
/* don't start dragging if no button is down */
|
||||
if (button_number)
|
||||
{
|
||||
@@ -883,7 +886,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
|
||||
/* re-enable GUI threads */
|
||||
wxapp_install_thread_wakeup();
|
||||
#endif
|
||||
|
||||
|
||||
g_blockEventsOnDrag = FALSE;
|
||||
|
||||
UnregisterWindow();
|
||||
|
@@ -48,10 +48,6 @@
|
||||
wxApp *wxTheApp = (wxApp *) NULL;
|
||||
wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
extern wxList *wxPendingEvents;
|
||||
extern wxCriticalSection *wxPendingEventsLocker;
|
||||
#endif
|
||||
extern wxResourceCache *wxTheResourceCache;
|
||||
extern bool g_isIdle;
|
||||
|
||||
@@ -127,7 +123,7 @@ unsigned char g_palette[64*3] =
|
||||
// local functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern void wxFlushResources(void);
|
||||
extern void wxFlushResources();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// global functions
|
||||
@@ -265,6 +261,7 @@ static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -427,11 +424,9 @@ void wxApp::OnIdle( wxIdleEvent &event )
|
||||
|
||||
s_inOnIdle = TRUE;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
/* Resend in the main thread events which have been prepared in other
|
||||
threads */
|
||||
ProcessPendingEvents();
|
||||
#endif
|
||||
|
||||
/* 'Garbage' collection of windows deleted with Close(). */
|
||||
DeletePendingObjects();
|
||||
@@ -520,12 +515,16 @@ void wxApp::Dispatch()
|
||||
gtk_main_iteration();
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
void wxApp::ProcessPendingEvents()
|
||||
{
|
||||
wxNode *node = wxPendingEvents->First();
|
||||
#if wxUSE_THREADS
|
||||
wxCriticalSectionLocker locker(*wxPendingEventsLocker);
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
if ( !wxPendingEvents )
|
||||
return;
|
||||
|
||||
wxNode *node = wxPendingEvents->First();
|
||||
while (node)
|
||||
{
|
||||
wxEvtHandler *handler = (wxEvtHandler *)node->Data();
|
||||
@@ -537,7 +536,6 @@ void wxApp::ProcessPendingEvents()
|
||||
node = wxPendingEvents->First();
|
||||
}
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
void wxApp::DeletePendingObjects()
|
||||
{
|
||||
|
@@ -39,12 +39,6 @@ wxWindowList wxTopLevelWindows;
|
||||
/* List of windows pending deletion */
|
||||
wxList wxPendingDelete;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
/* List of events pending processing */
|
||||
wxList *wxPendingEvents = NULL;
|
||||
wxCriticalSection *wxPendingEventsLocker = NULL;
|
||||
#endif
|
||||
|
||||
/* Current cursor, in order to hang on to
|
||||
* cursor handle when setting the cursor globally */
|
||||
wxCursor g_globalCursor;
|
||||
|
@@ -651,7 +651,7 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget),
|
||||
/* disable GUI threads */
|
||||
wxapp_uninstall_thread_wakeup();
|
||||
#endif
|
||||
|
||||
|
||||
gtk_selection_data_set( selection_data,
|
||||
selection_data->target,
|
||||
8, // 8-bit
|
||||
@@ -745,7 +745,8 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop
|
||||
if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm );
|
||||
}
|
||||
|
||||
wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go, const wxIcon &stop )
|
||||
wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win,
|
||||
const wxIcon &go, const wxIcon &stop )
|
||||
{
|
||||
m_waiting = TRUE;
|
||||
|
||||
@@ -754,15 +755,8 @@ wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go,
|
||||
if (win->m_wxwindow) m_widget = win->m_wxwindow;
|
||||
m_retValue = wxDragCancel;
|
||||
|
||||
if (data)
|
||||
{
|
||||
m_data = new wxDataBroker();
|
||||
m_data->Add( data );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data = (wxDataBroker*) NULL;
|
||||
}
|
||||
m_data = new wxDataBroker;
|
||||
m_data->Add(&data);
|
||||
|
||||
m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
|
||||
m_goaheadCursor = wxCursor( wxCURSOR_HAND );
|
||||
@@ -786,6 +780,15 @@ wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win )
|
||||
m_goaheadCursor = wxCursor( wxCURSOR_HAND );
|
||||
}
|
||||
|
||||
void wxDropSource::SetData( wxDataObject& data )
|
||||
{
|
||||
if ( m_data )
|
||||
delete m_data;
|
||||
|
||||
m_data = new wxDataBroker;
|
||||
m_data->Add(&data);
|
||||
}
|
||||
|
||||
void wxDropSource::SetData( wxDataObject *data )
|
||||
{
|
||||
if (m_data) delete m_data;
|
||||
@@ -808,7 +811,7 @@ void wxDropSource::SetData( wxDataBroker *data )
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
wxDropSource::~wxDropSource(void)
|
||||
wxDropSource::~wxDropSource()
|
||||
{
|
||||
if (m_data) delete m_data;
|
||||
|
||||
@@ -854,7 +857,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
|
||||
/* disable GUI threads */
|
||||
wxapp_uninstall_thread_wakeup();
|
||||
#endif
|
||||
|
||||
|
||||
/* don't start dragging if no button is down */
|
||||
if (button_number)
|
||||
{
|
||||
@@ -883,7 +886,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
|
||||
/* re-enable GUI threads */
|
||||
wxapp_install_thread_wakeup();
|
||||
#endif
|
||||
|
||||
|
||||
g_blockEventsOnDrag = FALSE;
|
||||
|
||||
UnregisterWindow();
|
||||
|
@@ -98,10 +98,6 @@ extern wxChar *wxBuffer;
|
||||
extern wxChar *wxOsVersion;
|
||||
extern wxList *wxWinHandleList;
|
||||
extern wxList WXDLLEXPORT wxPendingDelete;
|
||||
#if wxUSE_THREADS
|
||||
extern wxList *wxPendingEvents;
|
||||
extern wxCriticalSection *wxPendingEventsLocker;
|
||||
#endif
|
||||
extern void wxSetKeyboardHook(bool doIt);
|
||||
extern wxCursor *g_globalCursor;
|
||||
|
||||
@@ -179,11 +175,8 @@ bool wxApp::Initialize()
|
||||
wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
|
||||
#endif
|
||||
|
||||
// I'm annoyed ... I don't know where to put this and I don't want to
|
||||
// create a module for that as it's part of the core.
|
||||
#if wxUSE_THREADS
|
||||
wxPendingEvents = new wxList();
|
||||
wxPendingEventsLocker = new wxCriticalSection();
|
||||
wxPendingEventsLocker = new wxCriticalSection;
|
||||
#endif
|
||||
|
||||
wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
|
||||
@@ -565,8 +558,8 @@ void wxApp::CleanUp()
|
||||
|
||||
// GL: I'm annoyed ... I don't know where to put this and I don't want to
|
||||
// create a module for that as it's part of the core.
|
||||
#if wxUSE_THREADS
|
||||
delete wxPendingEvents;
|
||||
#if wxUSE_THREADS
|
||||
delete wxPendingEventsLocker;
|
||||
// If we don't do the following, we get an apparent memory leak.
|
||||
((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
|
||||
@@ -931,12 +924,17 @@ bool wxApp::ProcessIdle()
|
||||
return event.MoreRequested();
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
void wxApp::ProcessPendingEvents()
|
||||
{
|
||||
wxNode *node = wxPendingEvents->First();
|
||||
#if wxUSE_THREADS
|
||||
// ensure that we're the only thread to modify the pending events list
|
||||
wxCriticalSectionLocker locker(*wxPendingEventsLocker);
|
||||
#endif
|
||||
|
||||
if ( !wxPendingEvents )
|
||||
return;
|
||||
|
||||
wxNode *node = wxPendingEvents->First();
|
||||
while (node)
|
||||
{
|
||||
wxEvtHandler *handler = (wxEvtHandler *)node->Data();
|
||||
@@ -947,8 +945,6 @@ void wxApp::ProcessPendingEvents()
|
||||
node = wxPendingEvents->First();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void wxApp::ExitMainLoop()
|
||||
{
|
||||
@@ -1032,10 +1028,11 @@ void wxApp::OnIdle(wxIdleEvent& event)
|
||||
event.RequestMore(TRUE);
|
||||
}
|
||||
|
||||
// If they are pending events, we must process them.
|
||||
#if wxUSE_THREADS
|
||||
// If they are pending events, we must process them: pending events are
|
||||
// either events to the threads other than main or events posted with
|
||||
// wxPostEvent() functions
|
||||
ProcessPendingEvents();
|
||||
#endif
|
||||
|
||||
s_inOnIdle = FALSE;
|
||||
}
|
||||
|
||||
@@ -1168,22 +1165,19 @@ void wxExit()
|
||||
// Yield to incoming messages
|
||||
bool wxYield()
|
||||
{
|
||||
// we don't want to process WM_QUIT from here - it should be processed in
|
||||
// the main event loop in order to stop it
|
||||
|
||||
MSG msg;
|
||||
// We want to go back to the main message loop
|
||||
// if we see a WM_QUIT. (?)
|
||||
#ifdef __WXWINE__
|
||||
while (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
|
||||
#else
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
|
||||
#endif
|
||||
while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
|
||||
msg.message != WM_QUIT )
|
||||
{
|
||||
if ( !wxTheApp->DoMessage() )
|
||||
break;
|
||||
}
|
||||
|
||||
// If they are pending events, we must process them.
|
||||
#if wxUSE_THREADS
|
||||
wxTheApp->ProcessPendingEvents();
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -142,7 +142,8 @@ bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
static bool wxSetClipboardData(wxDataObject *data)
|
||||
{
|
||||
size_t size = data->GetDataSize();
|
||||
wxDataFormat format = data->GetPreferredFormat();
|
||||
size_t size = data->GetDataSize(format);
|
||||
HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
|
||||
if ( !hGlobal )
|
||||
{
|
||||
@@ -154,11 +155,10 @@ static bool wxSetClipboardData(wxDataObject *data)
|
||||
|
||||
LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
|
||||
|
||||
data->GetDataHere(lpGlobalMemory);
|
||||
data->GetDataHere(format, lpGlobalMemory);
|
||||
|
||||
GlobalUnlock(hGlobal);
|
||||
|
||||
wxDataFormat format = data->GetPreferredFormat();
|
||||
if ( !::SetClipboardData(format, hGlobal) )
|
||||
{
|
||||
wxLogSysError(_("Failed to set clipboard data in format %s"),
|
||||
|
@@ -37,12 +37,6 @@ wxWindowList wxTopLevelWindows;
|
||||
// List of windows pending deletion
|
||||
wxList WXDLLEXPORT wxPendingDelete;
|
||||
|
||||
// List of events pending processing
|
||||
#if wxUSE_THREADS
|
||||
wxList *wxPendingEvents = NULL;
|
||||
wxCriticalSection *wxPendingEventsLocker = NULL;
|
||||
#endif
|
||||
|
||||
// Current cursor, in order to hang on to
|
||||
// cursor handle when setting the cursor globally
|
||||
wxCursor *g_globalCursor = NULL;
|
||||
|
@@ -54,52 +54,58 @@
|
||||
// functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static const char *GetTymedName(DWORD tymed);
|
||||
#ifdef __WXDEBUG__
|
||||
static const char *GetTymedName(DWORD tymed);
|
||||
#endif // Debug
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIEnumFORMATETC interface implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxIEnumFORMATETC : public IEnumFORMATETC
|
||||
{
|
||||
public:
|
||||
wxIEnumFORMATETC(CLIPFORMAT cf);
|
||||
wxIEnumFORMATETC(const wxDataFormat* formats, ULONG nCount);
|
||||
~wxIEnumFORMATETC() { delete [] m_formats; }
|
||||
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
|
||||
// IEnumFORMATETC
|
||||
STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
|
||||
STDMETHODIMP Skip(ULONG celt);
|
||||
STDMETHODIMP Reset();
|
||||
STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
|
||||
// IEnumFORMATETC
|
||||
STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
|
||||
STDMETHODIMP Skip(ULONG celt);
|
||||
STDMETHODIMP Reset();
|
||||
STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
|
||||
|
||||
private:
|
||||
FORMATETC m_format; // (unique @@@) format we can provide data in
|
||||
ULONG m_nCurrent; // current enum position (currently either 0 or 1)
|
||||
CLIPFORMAT *m_formats; // formats we can provide data in
|
||||
ULONG m_nCount, // number of formats we support
|
||||
m_nCurrent; // current enum position
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIDataObject implementation of IDataObject interface
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxIDataObject : public IDataObject
|
||||
{
|
||||
public:
|
||||
wxIDataObject(wxDataObject *pDataObject);
|
||||
wxIDataObject(wxDataObject *pDataObject);
|
||||
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
|
||||
// IDataObject
|
||||
STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
|
||||
STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
|
||||
STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
|
||||
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
|
||||
STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
|
||||
STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
|
||||
STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
|
||||
STDMETHODIMP DUnadvise(DWORD dwConnection);
|
||||
STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
|
||||
// IDataObject
|
||||
STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
|
||||
STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
|
||||
STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
|
||||
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
|
||||
STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
|
||||
STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
|
||||
STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
|
||||
STDMETHODIMP DUnadvise(DWORD dwConnection);
|
||||
STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
|
||||
|
||||
private:
|
||||
wxDataObject *m_pDataObject; // pointer to C++ class we belong to
|
||||
wxDataObject *m_pDataObject; // pointer to C++ class we belong to
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@@ -144,70 +150,90 @@ wxString wxDataFormat::GetId() const
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_IID_TABLE(wxIEnumFORMATETC)
|
||||
ADD_IID(Unknown)
|
||||
ADD_IID(EnumFORMATETC)
|
||||
ADD_IID(Unknown)
|
||||
ADD_IID(EnumFORMATETC)
|
||||
END_IID_TABLE;
|
||||
|
||||
IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
|
||||
|
||||
wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf)
|
||||
wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount)
|
||||
{
|
||||
m_format.cfFormat = cf;
|
||||
m_format.ptd = NULL;
|
||||
m_format.dwAspect = DVASPECT_CONTENT;
|
||||
m_format.lindex = -1;
|
||||
m_format.tymed = TYMED_HGLOBAL;
|
||||
m_cRef = 0;
|
||||
m_nCurrent = 0;
|
||||
m_cRef = 0;
|
||||
m_nCurrent = 0;
|
||||
m_nCount = nCount;
|
||||
m_formats = new CLIPFORMAT[nCount];
|
||||
for ( ULONG n = 0; n < nCount; n++ ) {
|
||||
m_formats[n] = formats[n].GetFormatId();
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
|
||||
FORMATETC *rgelt,
|
||||
ULONG *pceltFetched)
|
||||
{
|
||||
wxLogTrace(wxT("wxIEnumFORMATETC::Next"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Next"));
|
||||
|
||||
if ( celt > 1 )
|
||||
return S_FALSE;
|
||||
if ( celt > 1 ) {
|
||||
// we only return 1 element at a time - mainly because I'm too lazy to
|
||||
// implement something which you're never asked for anyhow
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if ( m_nCurrent == 0 ) {
|
||||
*rgelt = m_format;
|
||||
m_nCurrent++;
|
||||
if ( m_nCurrent < m_nCount ) {
|
||||
FORMATETC format;
|
||||
format.cfFormat = m_formats[m_nCurrent++];
|
||||
format.ptd = NULL;
|
||||
format.dwAspect = DVASPECT_CONTENT;
|
||||
format.lindex = -1;
|
||||
format.tymed = TYMED_HGLOBAL;
|
||||
*rgelt = format;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
// bad index
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
|
||||
{
|
||||
wxLogTrace(wxT("wxIEnumFORMATETC::Skip"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Skip"));
|
||||
|
||||
if ( m_nCurrent == 0 )
|
||||
m_nCurrent++;
|
||||
m_nCurrent += celt;
|
||||
if ( m_nCurrent < m_nCount )
|
||||
return S_OK;
|
||||
|
||||
return S_FALSE;
|
||||
// no, can't skip this many elements
|
||||
m_nCurrent -= celt;
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Reset()
|
||||
{
|
||||
wxLogTrace(wxT("wxIEnumFORMATETC::Reset"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Reset"));
|
||||
|
||||
m_nCurrent = 0;
|
||||
m_nCurrent = 0;
|
||||
|
||||
return S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
|
||||
{
|
||||
wxLogTrace(wxT("wxIEnumFORMATETC::Clone"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Clone"));
|
||||
|
||||
wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat);
|
||||
pNew->AddRef();
|
||||
*ppenum = pNew;
|
||||
// unfortunately, we can't reuse the code in ctor - types are different
|
||||
wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(NULL, 0);
|
||||
pNew->m_nCount = m_nCount;
|
||||
pNew->m_formats = new CLIPFORMAT[m_nCount];
|
||||
for ( ULONG n = 0; n < m_nCount; n++ ) {
|
||||
pNew->m_formats[n] = m_formats[n];
|
||||
}
|
||||
pNew->AddRef();
|
||||
*ppenum = pNew;
|
||||
|
||||
return S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -215,71 +241,118 @@ STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_IID_TABLE(wxIDataObject)
|
||||
ADD_IID(Unknown)
|
||||
ADD_IID(DataObject)
|
||||
ADD_IID(Unknown)
|
||||
ADD_IID(DataObject)
|
||||
END_IID_TABLE;
|
||||
|
||||
IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
|
||||
|
||||
wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
|
||||
{
|
||||
m_cRef = 0;
|
||||
m_pDataObject = pDataObject;
|
||||
m_cRef = 0;
|
||||
m_pDataObject = pDataObject;
|
||||
}
|
||||
|
||||
// get data functions
|
||||
STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
|
||||
{
|
||||
wxLogTrace(wxT("wxIDataObject::GetData"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetData"));
|
||||
|
||||
// is data is in our format?
|
||||
HRESULT hr = QueryGetData(pformatetcIn);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
// is data is in our format?
|
||||
HRESULT hr = QueryGetData(pformatetcIn);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
// alloc memory
|
||||
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
|
||||
m_pDataObject->GetDataSize());
|
||||
if ( hGlobal == NULL ) {
|
||||
wxLogLastError("GlobalAlloc");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
// for the bitmaps and metafiles we use the handles instead of global memory
|
||||
// to pass the data
|
||||
wxDataFormat format = (wxDataFormatId)pformatetcIn->cfFormat;
|
||||
|
||||
// copy data
|
||||
pmedium->tymed = TYMED_HGLOBAL;
|
||||
pmedium->hGlobal = hGlobal;
|
||||
pmedium->pUnkForRelease = NULL;
|
||||
switch ( format )
|
||||
{
|
||||
case wxDF_BITMAP:
|
||||
pmedium->tymed = TYMED_GDI;
|
||||
break;
|
||||
|
||||
hr = GetDataHere(pformatetcIn, pmedium);
|
||||
if ( FAILED(hr) ) {
|
||||
GlobalFree(hGlobal);
|
||||
return hr;
|
||||
}
|
||||
case wxDF_METAFILE:
|
||||
pmedium->tymed = TYMED_MFPICT;
|
||||
break;
|
||||
|
||||
return S_OK;
|
||||
default:
|
||||
// alloc memory
|
||||
size_t size = m_pDataObject->GetDataSize(format);
|
||||
if ( !size ) {
|
||||
// it probably means that the method is just not implemented
|
||||
wxLogDebug(wxT("Invalid data size - can't be 0"));
|
||||
|
||||
return DV_E_FORMATETC;
|
||||
}
|
||||
|
||||
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
|
||||
if ( hGlobal == NULL ) {
|
||||
wxLogLastError("GlobalAlloc");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// copy data
|
||||
pmedium->tymed = TYMED_HGLOBAL;
|
||||
pmedium->hGlobal = hGlobal;
|
||||
}
|
||||
|
||||
pmedium->pUnkForRelease = NULL;
|
||||
|
||||
// do copy the data
|
||||
hr = GetDataHere(pformatetcIn, pmedium);
|
||||
if ( FAILED(hr) ) {
|
||||
// free resources we allocated
|
||||
if ( pmedium->tymed == TYMED_HGLOBAL ) {
|
||||
GlobalFree(pmedium->hGlobal);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium)
|
||||
{
|
||||
wxLogTrace(wxT("wxIDataObject::GetDataHere"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetDataHere"));
|
||||
|
||||
// put data in caller provided medium
|
||||
if ( pmedium->tymed != TYMED_HGLOBAL )
|
||||
return DV_E_TYMED;
|
||||
// put data in caller provided medium
|
||||
switch ( pmedium->tymed )
|
||||
{
|
||||
case TYMED_GDI:
|
||||
m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap);
|
||||
break;
|
||||
|
||||
// copy data
|
||||
void *pBuf = GlobalLock(pmedium->hGlobal);
|
||||
if ( pBuf == NULL ) {
|
||||
wxLogLastError(wxT("GlobalLock"));
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
case TYMED_MFPICT:
|
||||
// this should be copied on bitmaps - but I don't have time for
|
||||
// this now
|
||||
wxFAIL_MSG(wxT("TODO - no support for metafiles in wxDataObject"));
|
||||
break;
|
||||
|
||||
m_pDataObject->GetDataHere(pBuf);
|
||||
case TYMED_HGLOBAL:
|
||||
{
|
||||
// copy data
|
||||
void *pBuf = GlobalLock(pmedium->hGlobal);
|
||||
if ( pBuf == NULL ) {
|
||||
wxLogLastError(wxT("GlobalLock"));
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
GlobalUnlock(pmedium->hGlobal);
|
||||
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
|
||||
m_pDataObject->GetDataHere(format, pBuf);
|
||||
|
||||
return S_OK;
|
||||
GlobalUnlock(pmedium->hGlobal);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return DV_E_TYMED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// set data functions (not implemented)
|
||||
@@ -287,7 +360,8 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium,
|
||||
BOOL fRelease)
|
||||
{
|
||||
wxLogTrace(wxT("wxIDataObject::SetData"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
@@ -296,39 +370,53 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
|
||||
{
|
||||
// do we accept data in this format?
|
||||
if ( pformatetc == NULL ) {
|
||||
wxLogTrace(wxT("wxIDataObject::QueryGetData: invalid ptr."));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: invalid ptr."));
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// the only one allowed by current COM implementation
|
||||
if ( pformatetc->lindex != -1 ) {
|
||||
wxLogTrace(wxT("wxIDataObject::QueryGetData: bad lindex %d"),
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: bad lindex %d"),
|
||||
pformatetc->lindex);
|
||||
return DV_E_LINDEX;
|
||||
}
|
||||
|
||||
// we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
|
||||
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
|
||||
wxLogTrace(wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
|
||||
pformatetc->dwAspect);
|
||||
return DV_E_DVASPECT;
|
||||
}
|
||||
|
||||
// @@ we only transfer data by global memory (bad for large amounts of it!)
|
||||
if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) {
|
||||
wxLogTrace(wxT("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL."),
|
||||
GetTymedName(pformatetc->tymed));
|
||||
// we only transfer data by global memory, except for some particular cases
|
||||
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
|
||||
DWORD tymed = pformatetc->tymed;
|
||||
if ( (format == wxDF_BITMAP && !(tymed & TYMED_GDI)) ||
|
||||
!(tymed & TYMED_HGLOBAL) ) {
|
||||
// it's not what we're waiting for
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s & %s == 0."),
|
||||
GetTymedName(tymed),
|
||||
GetTymedName(format == wxDF_BITMAP ? TYMED_GDI : TYMED_HGLOBAL));
|
||||
#endif // Debug
|
||||
return DV_E_TYMED;
|
||||
}
|
||||
|
||||
// and now check the type of data requested
|
||||
if ( m_pDataObject->IsSupportedFormat((wxDataFormatId)pformatetc->cfFormat) ) {
|
||||
wxLogTrace(wxT("wxIDataObject::QueryGetData: %s ok"),
|
||||
wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
|
||||
if ( m_pDataObject->IsSupportedFormat(format) ) {
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
|
||||
wxDataObject::GetFormatName(format));
|
||||
#endif // Debug
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
wxLogTrace(wxT("wxIDataObject::QueryGetData: %s unsupported"),
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s unsupported"),
|
||||
wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
|
||||
return DV_E_FORMATETC;
|
||||
}
|
||||
@@ -337,30 +425,47 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
|
||||
STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
|
||||
FORMATETC *pFormatetcOut)
|
||||
{
|
||||
wxLogTrace(wxT("wxIDataObject::GetCanonicalFormatEtc"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetCanonicalFormatEtc"));
|
||||
|
||||
// @@ implementation is trivial, we might want something better here
|
||||
if ( pFormatetcOut != NULL )
|
||||
pFormatetcOut->ptd = NULL;
|
||||
return DATA_S_SAMEFORMATETC;
|
||||
// TODO we might want something better than this trivial implementation here
|
||||
if ( pFormatetcOut != NULL )
|
||||
pFormatetcOut->ptd = NULL;
|
||||
|
||||
return DATA_S_SAMEFORMATETC;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
|
||||
IEnumFORMATETC **ppenumFormatEtc)
|
||||
{
|
||||
wxLogTrace(wxT("wxIDataObject::EnumFormatEtc"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
|
||||
|
||||
if ( dwDirection == DATADIR_SET ) {
|
||||
// we don't allow setting of data anyhow
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
if ( dwDirection == DATADIR_SET ) {
|
||||
// we don't allow setting of data anyhow
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
wxIEnumFORMATETC *pEnum =
|
||||
new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat());
|
||||
pEnum->AddRef();
|
||||
*ppenumFormatEtc = pEnum;
|
||||
size_t nFormatCount = m_pDataObject->GetFormatCount();
|
||||
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);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
|
||||
pEnum->AddRef();
|
||||
*ppenumFormatEtc = pEnum;
|
||||
|
||||
if ( formats != &format ) {
|
||||
delete [] formats;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// advise sink functions (not implemented)
|
||||
@@ -397,9 +502,32 @@ wxDataObject::~wxDataObject()
|
||||
m_pIDataObject->Release();
|
||||
}
|
||||
|
||||
bool wxDataObject::IsSupportedFormat(const wxDataFormat& format) const
|
||||
{
|
||||
size_t nFormatCount = GetFormatCount();
|
||||
if ( nFormatCount == 1 ) {
|
||||
return format == GetPreferredFormat();
|
||||
}
|
||||
else {
|
||||
wxDataFormat *formats = new wxDataFormat[nFormatCount];
|
||||
GetAllFormats(formats);
|
||||
|
||||
size_t n;
|
||||
for ( n = 0; n < nFormatCount; n++ ) {
|
||||
if ( formats[n] == format )
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] formats;
|
||||
|
||||
// found?
|
||||
return n < nFormatCount;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
const char *wxDataObject::GetFormatName(wxDataFormat format)
|
||||
{
|
||||
#ifdef __WXDEBUG__
|
||||
// case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
|
||||
#ifdef __VISUALC__
|
||||
#pragma warning(disable:4063)
|
||||
@@ -431,11 +559,8 @@ const char *wxDataObject::GetFormatName(wxDataFormat format)
|
||||
#ifdef __VISUALC__
|
||||
#pragma warning(default:4063)
|
||||
#endif // VC++
|
||||
|
||||
#else // !Debug
|
||||
return "";
|
||||
#endif // Debug
|
||||
}
|
||||
#endif // Debug
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxPrivateDataObject
|
||||
@@ -478,9 +603,34 @@ void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
|
||||
memcpy( dest, data, GetSize() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxBitmapDataObject
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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.
|
||||
|
||||
size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
|
||||
{
|
||||
// no data to copy anyhow
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
|
||||
void *pBuf) const
|
||||
{
|
||||
// we put a bitmap handle into pBuf
|
||||
*(WXHBITMAP *)pBuf = m_bitmap.GetHBITMAP();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
|
||||
static const char *GetTymedName(DWORD tymed)
|
||||
{
|
||||
static char s_szBuf[128];
|
||||
@@ -498,7 +648,7 @@ static const char *GetTymedName(DWORD tymed)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: OLE parts of wxBitmap/File/MetafileDataObject
|
||||
#endif // Debug
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -160,13 +160,18 @@ void wxDropSource::Init()
|
||||
m_pIDropSource->AddRef();
|
||||
}
|
||||
|
||||
wxDropSource::wxDropSource(wxWindow* WXUNUSED(win))
|
||||
wxDropSource::wxDropSource(wxWindow* WXUNUSED(win),
|
||||
const wxIcon & WXUNUSED(go),
|
||||
const wxIcon & WXUNUSED(stop))
|
||||
{
|
||||
Init();
|
||||
m_pData = NULL;
|
||||
}
|
||||
|
||||
wxDropSource::wxDropSource(wxDataObject& data, wxWindow* WXUNUSED(win))
|
||||
wxDropSource::wxDropSource(wxDataObject& data,
|
||||
wxWindow* WXUNUSED(win),
|
||||
const wxIcon & WXUNUSED(go),
|
||||
const wxIcon & WXUNUSED(stop))
|
||||
{
|
||||
Init();
|
||||
SetData(data);
|
||||
|
Reference in New Issue
Block a user