From: Vadim Zeitlin Date: Fri, 12 May 2006 15:21:41 +0000 (+0000) Subject: added clipboard events (wxEVT_COMMAND_TEXT_COPY/CUT/PASTE) and implemented them for... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/78c91815008ef5888231c6c7f3678872e9e35ff6?ds=inline added clipboard events (wxEVT_COMMAND_TEXT_COPY/CUT/PASTE) and implemented them for wxMSW git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39141 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/latex/wx/category.tex b/docs/latex/wx/category.tex index f1ae1587ba..3c5d54fba5 100644 --- a/docs/latex/wx/category.tex +++ b/docs/latex/wx/category.tex @@ -218,6 +218,7 @@ An event object contains information about a specific event. Event handlers \twocolitem{\helpref{wxActivateEvent}{wxactivateevent}}{A window or application activation event} \twocolitem{\helpref{wxCalendarEvent}{wxcalendarevent}}{Used with \helpref{wxCalendarCtrl}{wxcalendarctrl}} \twocolitem{\helpref{wxCalculateLayoutEvent}{wxcalculatelayoutevent}}{Used to calculate window layout} +\twocolitem{\helpref{wxClipboardTextEvent}{wxclipboardtextevent}}{A clipboard copy/cut/paste treebook event event} \twocolitem{\helpref{wxCloseEvent}{wxcloseevent}}{A close window or end session event} \twocolitem{\helpref{wxCommandEvent}{wxcommandevent}}{An event from a variety of standard controls} \twocolitem{\helpref{wxContextMenuEvent}{wxcontextmenuevent}}{An event generated when the user issues a context menu command} diff --git a/docs/latex/wx/classes.tex b/docs/latex/wx/classes.tex index 7dc6aff273..93257fe33a 100644 --- a/docs/latex/wx/classes.tex +++ b/docs/latex/wx/classes.tex @@ -39,6 +39,7 @@ \input clientdc.tex \input clientdat.tex \input clipbrd.tex +\input clipevent.tex \input closeevt.tex \input cmdlpars.tex \input colour.tex diff --git a/docs/latex/wx/clipevent.tex b/docs/latex/wx/clipevent.tex new file mode 100644 index 0000000000..de6e3ba0eb --- /dev/null +++ b/docs/latex/wx/clipevent.tex @@ -0,0 +1,84 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Name: clipevent.tex +%% Purpose: wxClipboardTextEvent documentation +%% Author: Evgeniy Tarassov, Vadim Zeitlin +%% Modified by: +%% Created: 2005-10-04 +%% RCS-ID: $Id$ +%% Copyright: (c) 2006 Vadim Zeitlin +%% License: wxWindows license +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{\class{wxClipboardTextEvent}}\label{wxclipboardtextevent} + +This class represents the events generated by a control (typically a +\helpref{wxTextCtrl}{wxtextctrl} but other windows can generate these events as +well) when its content gets copied or cut to, or pasted from the clipboard. +There are three types of corresponding events wxEVT\_COMMAND\_TEXT\_COPY, +wxEVT\_COMMAND\_TEXT\_CUT and wxEVT\_COMMAND\_TEXT\_PASTE. + +If any of these events is processed (without being skipped) by an event +handler, the corresponding operation doesn't take place which allows to prevent +the text from being copied from or pasted to a control. It is also possible to +examine the clipboard contents in the PASTE event handler and transform it in +some way before inserting in a control -- for example, changing its case or +removing invalid characters. + +Finally notice that a CUT event is always preceded by the COPY event which +makes it possible to only process the latter if it doesn't matter if the text +was copied or cut. + +\wxheading{Remarks} + +These events are currently only generated by \helpref{wxComboBox}{wxcombobox} and +under Windows and \helpref{wxTextCtrl}{wxtextctrl} under Windows and GTK and +are not generated for the text controls with \texttt{wxTE\_RICH} style under +Windows. + + +\wxheading{Derived from} + +\helpref{wxCommandEvent}{wxcommandevent}\\ +\helpref{wxEvent}{wxevent}\\ +\helpref{wxObject}{wxobject} + + + +\wxheading{Include files} + + + + + +\wxheading{Event handling} + +To process this type of events use the following event handling macros. The +\arg{func} parameter must be a member functions that takes an argument of type +\texttt{wxClipboardTextEvent \&}. + +\twocolwidtha{10cm} +\begin{twocollist}\itemsep=0pt +\twocolitem{{\bf EVT\_TEXT\_COPY(id, func)}}{Some or all of the controls +content was copied to the clipboard.} +\twocolitem{{\bf EVT\_TEXT\_CUT(id, func)}}{Some or all of the controls content +was cut (i.e. copied and deleted).} +\twocolitem{{\bf EVT\_TEXT\_PASTE(id, func)}}{Clipboard content was pasted into +the control.} +\end{twocollist} + + + +\wxheading{See also} + +\helpref{wxClipboard}{wxclipboard} + + + +\latexignore{\rtfignore{\wxheading{Members}}} + + +\membersection{wxClipboardTextEvent::wxClipboardTextEvent}\label{wxclipboardtexteventwxclipboardtextevent} + +\func{}{wxClipboardTextEvent}{\param{wxEventType }{commandType = wxEVT\_NULL}, \param{int }{id = 0}} + + diff --git a/include/wx/event.h b/include/wx/event.h index 909ffbc405..acdf448c41 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -267,6 +267,11 @@ BEGIN_DECLARE_EVENT_TYPES() DECLARE_EVENT_TYPE(wxEVT_MOVING, 442) DECLARE_EVENT_TYPE(wxEVT_HIBERNATE, 443) + // Clipboard events + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_COPY, 444) + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_CUT, 445) + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_PASTE, 446) + // Generic command events // Note: a click is a higher-level event than button down/up DECLARE_EVENT_TYPE(wxEVT_COMMAND_LEFT_CLICK, 500) @@ -2014,6 +2019,34 @@ private: DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHelpEvent) }; +// A Clipboard Text event is sent when a window intercepts text copy/cut/paste +// message, i.e. the user has cut/copied/pasted data from/into a text control +// via ctrl-C/X/V, ctrl/shift-del/insert, a popup menu command, etc. +// NOTE : under windows these events are *NOT* generated automatically +// for a Rich Edit text control. +/* +wxEVT_COMMAND_TEXT_COPY +wxEVT_COMMAND_TEXT_CUT +wxEVT_COMMAND_TEXT_PASTE +*/ + +class WXDLLIMPEXP_CORE wxClipboardTextEvent : public wxCommandEvent +{ +public: + wxClipboardTextEvent(wxEventType type = wxEVT_NULL, + wxWindowID winid = 0) + : wxCommandEvent(type, winid) + { } + wxClipboardTextEvent(const wxClipboardTextEvent & event) + : wxCommandEvent(event) + { } + + virtual wxEvent *Clone() const { return new wxClipboardTextEvent(*this); } + +private: + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxClipboardTextEvent) +}; + // A Context event is sent when the user right clicks on a window or // presses Shift-F10 // NOTE : Under windows this is a repackaged WM_CONTETXMENU message @@ -2531,6 +2564,7 @@ typedef void (wxEvtHandler::*wxNotifyEventFunction)(wxNotifyEvent&); typedef void (wxEvtHandler::*wxHelpEventFunction)(wxHelpEvent&); typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&); typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&); +typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&); // these typedefs don't have the same name structure as the others, keep for // backwards compatibility only @@ -2611,6 +2645,8 @@ typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureC (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxContextMenuEventFunction, &func) #define wxMouseCaptureChangedEventHandler(func) \ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureChangedEventFunction, &func) +#define wxClipboardTextEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxClipboardTextEventFunction, &func) #endif // wxUSE_GUI @@ -3002,6 +3038,11 @@ typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureC #define EVT_CONTEXT_MENU(func) wx__DECLARE_EVT0(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(func)) #define EVT_COMMAND_CONTEXT_MENU(winid, func) wx__DECLARE_EVT1(wxEVT_CONTEXT_MENU, winid, wxContextMenuEventHandler(func)) +// Clipboard text Events +#define EVT_TEXT_CUT(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TEXT_CUT, winid, wxClipboardTextEventHandler(func)) +#define EVT_TEXT_COPY(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TEXT_COPY, winid, wxClipboardTextEventHandler(func)) +#define EVT_TEXT_PASTE(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TEXT_PASTE, winid, wxClipboardTextEventHandler(func)) + // ---------------------------------------------------------------------------- // Global data // ---------------------------------------------------------------------------- diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index b69eecbabc..d9c3e215ad 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -332,6 +332,8 @@ public: #ifdef __WIN32__ int HandleMenuChar(int chAccel, WXLPARAM lParam); #endif + // Create and process a clipboard event specified by type. + bool HandleClipboardEvent( WXUINT nMsg ); bool HandleQueryDragIcon(WXHICON *hIcon); diff --git a/samples/text/text.cpp b/samples/text/text.cpp index 9fda9d9c2d..fe76bd993f 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -75,6 +75,10 @@ public: void OnTextURL(wxTextUrlEvent& event); void OnTextMaxLen(wxCommandEvent& event); + void OnTextCut(wxClipboardTextEvent & event); + void OnTextCopy(wxClipboardTextEvent & event); + void OnTextPaste(wxClipboardTextEvent & event); + void OnMouseEvent(wxMouseEvent& event); void OnSetFocus(wxFocusEvent& event); @@ -85,10 +89,13 @@ public: static bool ms_logMouse; static bool ms_logText; static bool ms_logFocus; + static bool ms_logClip; private: static inline wxChar GetChar(bool on, wxChar c) { return on ? c : _T('-'); } + void LogKeyEvent(const wxChar *name, wxKeyEvent& event) const; + void LogClipEvent(const wxChar *what, wxClipboardTextEvent& event); bool m_hasCapture; @@ -282,6 +289,11 @@ public: MyTextCtrl::ms_logFocus = event.IsChecked(); } + void OnLogClip(wxCommandEvent& event) + { + MyTextCtrl::ms_logClip = event.IsChecked(); + } + void OnSetText(wxCommandEvent& WXUNUSED(event)) { m_panel->m_text->SetValue(_T("Hello, world (what else did you expect)?")); @@ -366,6 +378,7 @@ enum // clipboard menu TEXT_CLIPBOARD_COPY = 200, TEXT_CLIPBOARD_PASTE, + TEXT_CLIPBOARD_VETO, // tooltip menu TEXT_TOOLTIPS_SETDELAY = 300, @@ -397,6 +410,7 @@ enum TEXT_LOG_MOUSE, TEXT_LOG_TEXT, TEXT_LOG_FOCUS, + TEXT_LOG_CLIP, TEXT_END }; @@ -441,6 +455,9 @@ bool MyApp::OnInit() _T("Copy the selection to the clipboard")); menuClipboard->Append(TEXT_CLIPBOARD_PASTE, _T("&Paste\tCtrl-Shift-V"), _T("Paste from clipboard to the text control")); + menuClipboard->AppendSeparator(); + menuClipboard->AppendCheckItem(TEXT_CLIPBOARD_VETO, _T("Vet&o\tCtrl-Shift-O"), + _T("Veto all clipboard operations")); menu_bar->Append(menuClipboard, _T("&Clipboard")); #endif // wxUSE_CLIPBOARD @@ -475,13 +492,13 @@ bool MyApp::OnInit() menuLog->AppendCheckItem(TEXT_LOG_MOUSE, _T("Log &mouse events")); menuLog->AppendCheckItem(TEXT_LOG_TEXT, _T("Log &text events")); menuLog->AppendCheckItem(TEXT_LOG_FOCUS, _T("Log &focus events")); + menuLog->AppendCheckItem(TEXT_LOG_CLIP, _T("Log clip&board events")); menuLog->AppendSeparator(); menuLog->Append(TEXT_CLEAR, _T("&Clear the log\tCtrl-L"), _T("Clear the log window contents")); // select only the interesting events by default - MyTextCtrl::ms_logKey = - MyTextCtrl::ms_logChar = false; + MyTextCtrl::ms_logClip = MyTextCtrl::ms_logText = true; menuLog->Check(TEXT_LOG_KEY, MyTextCtrl::ms_logKey); @@ -514,6 +531,9 @@ BEGIN_EVENT_TABLE(MyTextCtrl, wxTextCtrl) EVT_TEXT_ENTER(wxID_ANY, MyTextCtrl::OnTextEnter) EVT_TEXT_URL(wxID_ANY, MyTextCtrl::OnTextURL) EVT_TEXT_MAXLEN(wxID_ANY, MyTextCtrl::OnTextMaxLen) + EVT_TEXT_CUT(wxID_ANY, MyTextCtrl::OnTextCut) + EVT_TEXT_COPY(wxID_ANY, MyTextCtrl::OnTextCopy) + EVT_TEXT_PASTE(wxID_ANY, MyTextCtrl::OnTextPaste) EVT_MOUSE_EVENTS(MyTextCtrl::OnMouseEvent) @@ -526,6 +546,7 @@ bool MyTextCtrl::ms_logChar = false; bool MyTextCtrl::ms_logMouse = false; bool MyTextCtrl::ms_logText = false; bool MyTextCtrl::ms_logFocus = false; +bool MyTextCtrl::ms_logClip = false; void MyTextCtrl::LogKeyEvent(const wxChar *name, wxKeyEvent& event) const { @@ -795,6 +816,39 @@ void MyTextCtrl::OnTextMaxLen(wxCommandEvent& WXUNUSED(event)) wxLogMessage(_T("You can't enter more characters into this control.")); } + +void MyTextCtrl::OnTextCut(wxClipboardTextEvent& event) +{ + LogClipEvent(_T("cut to"), event); +} + +void MyTextCtrl::OnTextCopy(wxClipboardTextEvent& event) +{ + LogClipEvent(_T("copied to"), event); +} + +void MyTextCtrl::OnTextPaste(wxClipboardTextEvent& event) +{ + LogClipEvent(_T("pasted from"), event); +} + +void MyTextCtrl::LogClipEvent(const wxChar *what, wxClipboardTextEvent& event) +{ + wxFrame *frame = wxDynamicCast(wxGetTopLevelParent(this), wxFrame); + wxCHECK_RET( frame, _T("no parent frame?") ); + + const bool veto = frame->GetMenuBar()->IsChecked(TEXT_CLIPBOARD_VETO); + if ( !veto ) + event.Skip(); + + if ( ms_logClip ) + { + wxLogMessage(_T("Text %s%s the clipboard."), + veto ? _T("not ") : _T(""), what); + } +} + + void MyTextCtrl::OnTextURL(wxTextUrlEvent& event) { const wxMouseEvent& ev = event.GetMouseEvent(); @@ -1237,6 +1291,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(TEXT_LOG_MOUSE,MyFrame::OnLogMouse) EVT_MENU(TEXT_LOG_TEXT, MyFrame::OnLogText) EVT_MENU(TEXT_LOG_FOCUS,MyFrame::OnLogFocus) + EVT_MENU(TEXT_LOG_CLIP, MyFrame::OnLogClip) #if wxUSE_LOG EVT_MENU(TEXT_CLEAR, MyFrame::OnLogClear) #endif // wxUSE_LOG diff --git a/src/common/event.cpp b/src/common/event.cpp index 9debc5b90a..f200ea664c 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -92,6 +92,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent) IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent) IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent) + IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent) #endif // wxUSE_GUI #if wxUSE_BASE @@ -288,6 +289,11 @@ DEFINE_EVENT_TYPE(wxEVT_COMPARE_ITEM) DEFINE_EVENT_TYPE(wxEVT_INIT_DIALOG) DEFINE_EVENT_TYPE(wxEVT_UPDATE_UI) +// Clipboard events +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_COPY) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_CUT) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_PASTE) + // Generic command events // Note: a click is a higher-level event than button down/up DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_CLICK) diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index 61908d5fdc..18c6b0da34 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -207,6 +207,13 @@ LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd, } } break; + + case WM_CUT: + case WM_COPY: + case WM_PASTE: + if( win->HandleClipboardEvent( message ) ) + return 0; + break; } return ::CallWindowProc(CASTWNDPROC gs_wndprocEdit, hWnd, message, wParam, lParam); diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index c2c88e5525..4230d68033 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -258,10 +258,49 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_SET_FOCUS(wxTextCtrl::OnSetFocus) END_EVENT_TABLE() +// ---------------------------------------------------------------------------- +// function prototypes +// ---------------------------------------------------------------------------- + +LRESULT APIENTRY _EXPORT wxTextCtrlWndProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +// --------------------------------------------------------------------------- +// global vars +// --------------------------------------------------------------------------- + +// the pointer to standard text control wnd proc +static WNDPROC gs_wndprocEdit = (WNDPROC)NULL; + // ============================================================================ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wnd proc for subclassed edit control +// ---------------------------------------------------------------------------- + +LRESULT APIENTRY _EXPORT wxTextCtrlWndProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd); + + switch ( message ) + { + case WM_CUT: + case WM_COPY: + case WM_PASTE: + if( win->HandleClipboardEvent( message ) ) + return 0; + break; + } + return ::CallWindowProc(CASTWNDPROC gs_wndprocEdit, hWnd, message, wParam, lParam); +} + // ---------------------------------------------------------------------------- // creation // ---------------------------------------------------------------------------- @@ -479,6 +518,9 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, } #endif // wxUSE_RICHEDIT + gs_wndprocEdit = wxSetWindowProc((HWND)GetHwnd(), + wxTextCtrlWndProc); + return true; } diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 7e6640eb42..28985957c0 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -5053,6 +5053,18 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), return wxNOT_FOUND; } +bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg ) +{ + const wxEventType type = ( nMsg == WM_CUT ) ? wxEVT_COMMAND_TEXT_CUT : + ( nMsg == WM_COPY ) ? wxEVT_COMMAND_TEXT_COPY : + /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE; + wxClipboardTextEvent evt(type, GetId()); + + evt.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(evt); +} + // --------------------------------------------------------------------------- // joystick // ---------------------------------------------------------------------------