diff --git a/include/wx/control.h b/include/wx/control.h index 79adf0144f..7b1d491309 100644 --- a/include/wx/control.h +++ b/include/wx/control.h @@ -46,6 +46,9 @@ protected: // inherit colour and font settings from the parent window void InheritAttributes(); + + // initialize the common fields of wxCommandEvent + void InitCommandEvent(wxCommandEvent& event) const; }; // ---------------------------------------------------------------------------- diff --git a/include/wx/msw/enhmeta.h b/include/wx/msw/enhmeta.h index a7f235453d..88f7cfa8a9 100644 --- a/include/wx/msw/enhmeta.h +++ b/include/wx/msw/enhmeta.h @@ -51,6 +51,11 @@ public: const wxString& GetFileName() const { return m_filename; } + // copy the metafile to the clipboard: the width and height parameters are + // for backwards compatibility (with wxMetaFile) only, they are ignored by + // this method + bool SetClipboard(int width = 0, int height = 0); + // implementation WXHANDLE GetHENHMETAFILE() const { return m_hMF; } void SetHENHMETAFILE(WXHANDLE hMF) { Free(); m_hMF = hMF; } @@ -96,7 +101,7 @@ private: #if wxUSE_DRAG_AND_DROP // notice that we want to support both CF_METAFILEPICT and CF_ENHMETAFILE and -// so we derive from and not from wxDataObjectSimple +// so we derive from wxDataObject and not from wxDataObjectSimple class WXDLLEXPORT wxEnhMetaFileDataObject : public wxDataObject { public: diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index c23c715266..6ed5fcb913 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -300,6 +300,9 @@ private: #define GetHmenu() ((HMENU)GetHMenu()) #define GetHmenuOf(menu) ((HMENU)menu->GetHMenu()) +#define GetHcursor() ((HCURSOR)GetHCURSOR()) +#define GetHcursorOf(cursor) ((HCURSOR)(cursor).GetHCURSOR()) + // --------------------------------------------------------------------------- // global data // --------------------------------------------------------------------------- @@ -326,6 +329,10 @@ WXDLLEXPORT void wxSetInstance(HINSTANCE hInst); #if wxUSE_GUI +// cursor stuff +extern HCURSOR wxGetCurrentBusyCursor(); // from msw/utils.cpp +extern const wxCursor *wxGetGlobalCursor(); // from msw/cursor.cpp + WXDLLEXPORT wxWindow* wxFindWinFromHandle(WXHWND hWnd); WXDLLEXPORT void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font); diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index 8e99dd0b17..479e92c1f5 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -68,5 +68,28 @@ void wxControlBase::InheritAttributes() void wxControlBase::Command(wxCommandEvent& event) { - (void)ProcessEvent(event); + (void)GetEventHandler()->ProcessEvent(event); } + +void wxControlBase::InitCommandEvent(wxCommandEvent& event) const +{ + event.SetEventObject((wxControlBase *)this); // const_cast + + // event.SetId(GetId()); -- this is usuall done in the event ctor + + switch ( m_clientDataType ) + { + case ClientData_Void: + event.SetClientData(GetClientData()); + break; + + case ClientData_Object: + event.SetClientObject(GetClientObject()); + break; + + case ClientData_None: + // nothing to do + ; + } +} + diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 94c9239a6d..903493b2f1 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -126,7 +126,6 @@ extern wxChar *wxOsVersion; extern wxList *wxWinHandleList; extern wxList WXDLLEXPORT wxPendingDelete; extern void wxSetKeyboardHook(bool doIt); -extern wxCursor *g_globalCursor; MSG s_currentMsg; wxApp *wxTheApp = NULL; @@ -228,8 +227,6 @@ bool wxApp::Initialize() Ctl3dAutoSubclass(wxhInstance); #endif - g_globalCursor = new wxCursor; - // VZ: these icons are not in wx.rc anyhow (but should they?)! #if 0 wxSTD_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_FRAME")); @@ -497,13 +494,6 @@ void wxApp::CleanUp() // wxDefaultResourceTable->ClearTable(); #endif - // Indicate that the cursor can be freed, so that cursor won't be deleted - // by deleting the bitmap list before g_globalCursor goes out of scope - // (double deletion of the cursor). - wxSetCursor(wxNullCursor); - delete g_globalCursor; - g_globalCursor = NULL; - wxDeleteStockObjects(); // Destroy all GDI lists, etc. diff --git a/src/msw/cursor.cpp b/src/msw/cursor.cpp index e914dff561..1f76183f6e 100644 --- a/src/msw/cursor.cpp +++ b/src/msw/cursor.cpp @@ -49,7 +49,40 @@ // wxWin macros // ---------------------------------------------------------------------------- - IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxCursorBase) +IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxCursorBase) + +// ---------------------------------------------------------------------------- +// globals +// ---------------------------------------------------------------------------- + +// Current cursor, in order to hang on to cursor handle when setting the cursor +// globally +static wxCursor *gs_globalCursor = NULL; + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +class wxCursorModule : public wxModule +{ +public: + virtual bool OnInit() + { + gs_globalCursor = new wxCursor; + + return TRUE; + } + + virtual void OnExit() + { + delete gs_globalCursor; + gs_globalCursor = (wxCursor *)NULL; + } +}; + +// ============================================================================ +// implementation +// ============================================================================ // ---------------------------------------------------------------------------- // wxCursorRefData @@ -278,16 +311,19 @@ wxCursor::~wxCursor() // Global cursor setting // ---------------------------------------------------------------------------- +const wxCursor *wxGetGlobalCursor() +{ + return gs_globalCursor; +} + void wxSetCursor(const wxCursor& cursor) { - extern wxCursor *g_globalCursor; - - if ( cursor.Ok() && cursor.GetHCURSOR() ) + if ( cursor.Ok() ) { - ::SetCursor((HCURSOR) cursor.GetHCURSOR()); + ::SetCursor(GetHcursorOf(cursor)); - if ( g_globalCursor ) - (*g_globalCursor) = cursor; + if ( gs_globalCursor ) + *gs_globalCursor = cursor; } } diff --git a/src/msw/data.cpp b/src/msw/data.cpp index 103f694ce0..1b24fc3e3a 100644 --- a/src/msw/data.cpp +++ b/src/msw/data.cpp @@ -37,13 +37,6 @@ wxWindowList wxTopLevelWindows; // List of windows pending deletion wxList WXDLLEXPORT wxPendingDelete; -// Current cursor, in order to hang on to -// cursor handle when setting the cursor globally -wxCursor *g_globalCursor = NULL; - -// Message Strings for Internationalization -char **wx_msg_str = (char**)NULL; - // Custom OS version, as optionally placed in wx.ini/.wxrc // Currently this can be Win95, Windows, Win32s, WinNT. // For some systems, you can't tell until run-time what services you diff --git a/src/msw/dialog.cpp b/src/msw/dialog.cpp index 658003fe30..3463629b49 100644 --- a/src/msw/dialog.cpp +++ b/src/msw/dialog.cpp @@ -530,13 +530,28 @@ long wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) case WM_SETCURSOR: // we want to override the busy cursor for modal dialogs: // typically, wxBeginBusyCursor() is called and then a modal dialog - // is shown, but the modal dialog shouldn't have this cursor + // is shown, but the modal dialog shouldn't have hourglass cursor if ( wxIsBusy() ) { - rc = TRUE; + // set our cursor for all windows (but see below) + wxCursor cursor = m_cursor; + if ( !cursor.Ok() ) + cursor = wxCURSOR_ARROW; + ::SetCursor(GetHcursorOf(cursor)); + + // in any case, stop here and don't let wxWindow process this + // message (it would set the busy cursor) processed = TRUE; + + // but return FALSE to tell the child window (if the event + // comes from one of them and not from ourselves) that it can + // set its own cursor if it has one: thus, standard controls + // (e.g. text ctrl) still have correct cursors in a dialog + // invoked while wxIsBusy() + rc = FALSE; } + break; } if ( !processed ) diff --git a/src/msw/enhmeta.cpp b/src/msw/enhmeta.cpp index 189d2980b8..0fd8b2d9af 100644 --- a/src/msw/enhmeta.cpp +++ b/src/msw/enhmeta.cpp @@ -36,6 +36,7 @@ #endif //WX_PRECOMP #include "wx/metafile.h" +#include "wx/clipbrd.h" #include "wx/msw/private.h" @@ -161,6 +162,13 @@ wxSize wxEnhMetaFile::GetSize() const return size; } +bool wxEnhMetaFile::SetClipboard(int WXUNUSED(width), int WXUNUSED(height)) +{ + wxCHECK_MSG( m_hMF, FALSE, _T("can't copy invalid metafile to clipboard") ); + + return wxTheClipboard->AddData(new wxEnhMetaFileDataObject(*this)); +} + // ---------------------------------------------------------------------------- // wxEnhMetaFileDC // ---------------------------------------------------------------------------- diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index c4969c9394..91ad453853 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: textctrl.cpp +// Name: msw/textctrl.cpp // Purpose: wxTextCtrl // Author: Julian Smart // Modified by: @@ -887,7 +887,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) if ( !(m_windowStyle & wxTE_MULTILINE) ) { wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); - event.SetEventObject( this ); + InitCommandEvent(event); if ( GetEventHandler()->ProcessEvent(event) ) return; } @@ -934,9 +934,9 @@ bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) case EN_CHANGE: { wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); - event.SetEventObject( this ); - event.SetString( GetValue() ); - ProcessCommand( event ); + InitCommandEvent(event); + event.SetString(GetValue()); + ProcessCommand(event); } break; @@ -1016,27 +1016,27 @@ wxSize wxTextCtrl::DoGetBestSize() const // standard handlers for standard edit menu events // ---------------------------------------------------------------------------- -void wxTextCtrl::OnCut(wxCommandEvent& event) +void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event)) { Cut(); } -void wxTextCtrl::OnCopy(wxCommandEvent& event) +void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event)) { Copy(); } -void wxTextCtrl::OnPaste(wxCommandEvent& event) +void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event)) { Paste(); } -void wxTextCtrl::OnUndo(wxCommandEvent& event) +void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event)) { Undo(); } -void wxTextCtrl::OnRedo(wxCommandEvent& event) +void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event)) { Redo(); } diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index 2f56096849..7126032d69 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -806,10 +806,15 @@ bool wxGetResource(const wxString& section, const wxString& entry, int *value, c // helper functions for showing a "busy" cursor // --------------------------------------------------------------------------- -HCURSOR gs_wxBusyCursor = 0; // new, busy cursor -HCURSOR gs_wxBusyCursorOld = 0; // old cursor +static HCURSOR gs_wxBusyCursor = 0; // new, busy cursor +static HCURSOR gs_wxBusyCursorOld = 0; // old cursor static int gs_wxBusyCursorCount = 0; +extern HCURSOR wxGetCurrentBusyCursor() +{ + return gs_wxBusyCursor; +} + // Set the cursor to the busy cursor for all windows void wxBeginBusyCursor(wxCursor *cursor) { diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 163a72e055..48cf53abc9 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -480,7 +480,7 @@ bool wxWindow::SetCursor(const wxCursor& cursor) ::GetWindowRect(hWnd, &rect); if ( ::PtInRect(&rect, point) && !wxIsBusy() ) - ::SetCursor((HCURSOR)m_cursor.GetHCURSOR()); + ::SetCursor(GetHcursorOf(m_cursor)); return TRUE; } @@ -2664,54 +2664,46 @@ bool wxWindow::HandleSetCursor(WXHWND hWnd, short nHitTest, int WXUNUSED(mouseMsg)) { - // don't set cursor for other windows, only for this one: this prevents - // children of this window from getting the same cursor as the parent has - // (don't forget that this message is propagated by default up the window - // parent-child hierarchy) - if ( GetHWND() == hWnd ) + // the logic is as follows: + // 1. if we have the cursor set it unless wxIsBusy() + // 2. if we're a top level window, set some cursor anyhow + // 3. if wxIsBusy(), set the busy cursor, otherwise the global one + + HCURSOR hcursor = 0; + bool isBusy = wxIsBusy(); + if ( m_cursor.Ok() ) { - // don't set cursor when the mouse is not in the client part - if ( nHitTest == HTCLIENT || nHitTest == HTERROR ) + hcursor = GetHcursorOf(m_cursor); + } + + if ( !GetParent() ) + { + if ( isBusy ) { - HCURSOR hcursor = 0; - if ( wxIsBusy() ) + hcursor = wxGetCurrentBusyCursor(); + } + else if ( !hcursor ) + { + const wxCursor *cursor = wxGetGlobalCursor(); + if ( cursor && cursor->Ok() ) { - // from msw\utils.cpp - extern HCURSOR gs_wxBusyCursor; - - hcursor = gs_wxBusyCursor; - } - else - { - wxCursor *cursor = NULL; - - if ( m_cursor.Ok() ) - { - cursor = &m_cursor; - } - else - { - // from msw\data.cpp - extern wxCursor *g_globalCursor; - - if ( g_globalCursor && g_globalCursor->Ok() ) - cursor = g_globalCursor; - } - - if ( cursor ) - hcursor = (HCURSOR)cursor->GetHCURSOR(); - } - - if ( hcursor ) - { - ::SetCursor(hcursor); - - return TRUE; + hcursor = GetHcursorOf(*cursor); } } } - return FALSE; + if ( hcursor ) + { + ::SetCursor(hcursor); + + // cursor set, stop here + return TRUE; + } + else + { + // pass up the window chain + return FALSE; + } } // ---------------------------------------------------------------------------