From c57e33394ca152e6e13f10363b76aef6e74a4705 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 29 Jul 2001 22:40:21 +0000 Subject: [PATCH] 1. added wxTE_AUTO_URL style and support for it under Win32 (and brief mention in docs and tests in the sample) 2. moved wxTextCtrl-specific stuff from defs.h/event.h to textctrl.h git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11209 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/text.tex | 19 ++++++--- include/wx/defs.h | 16 ------- include/wx/event.h | 6 +-- include/wx/msw/textctrl.h | 2 + include/wx/textctrl.h | 75 +++++++++++++++++++++++++++++++++ samples/text/text.cpp | 89 +++++++++++++++++++++++++-------------- src/common/event.cpp | 2 - src/common/textcmn.cpp | 6 +++ src/msw/textctrl.cpp | 82 ++++++++++++++++++++++++++++++++++-- 9 files changed, 235 insertions(+), 62 deletions(-) diff --git a/docs/latex/wx/text.tex b/docs/latex/wx/text.tex index fff6a22f19..2d5697d970 100644 --- a/docs/latex/wx/text.tex +++ b/docs/latex/wx/text.tex @@ -30,6 +30,12 @@ you can still use Ctrl-Enter to pass to the next control from the keyboard.} \twocolitem{\windowstyle{wxTE\_MULTILINE}}{The text control allows multiple lines.} \twocolitem{\windowstyle{wxTE\_PASSWORD}}{The text will be echoed as asterisks.} \twocolitem{\windowstyle{wxTE\_READONLY}}{The text will not be user-editable.} +\twocolitem{\windowstyle{wxTE\_RICH}}{Use rich text control under Win32, this +allows to have more than 64Kb of text in the control even under Win9x. This +style is ignored under other platforms.} +\twocolitem{\windowstyle{wxTE\_AUTO\_URL}}{Highlight the URLs and generate the +wxTextUrlEvents when mouse events occur over them. This style is supported +under Win32 only and requires wxTE\_RICH.} \twocolitem{\windowstyle{wxHSCROLL}}{A horizontal scrollbar will be created. No effect under GTK+.} \end{twocollist} @@ -55,8 +61,10 @@ the following: If your compiler does not support derivation from {\bf streambuf} and gives a compile error, define the symbol {\bf NO\_TEXT\_WINDOW\_STREAM} in the wxTextCtrl header file. -Note that any use of C++ iostreams (including this one) deprecated and might get completely removed -in the future. +% VZ: it is wrong to say that C++ iostreams are deprecated, we need a better +% wording here - disabling this for now +%Note that any use of C++ iostreams (including this one) is deprecated and might +%get completely removed in the future. \wxheading{Event handling} @@ -122,9 +130,10 @@ controls don't have a horizontal scrollbar, the text is automatically scrolled so that the \helpref{insertion point}{wxtextctrlgetinsertionpoint} is always visible. -Under Windows, if the {\bf wxTE\_MULTILINE} style is used, the window is implemented -as a Windows rich text control with unlimited capacity. Otherwise, normal edit control limits -apply. +% VZ: this is no longer true +%Under Windows, if the {\bf wxTE\_MULTILINE} style is used, the window is implemented +%as a Windows rich text control with unlimited capacity. Otherwise, normal edit control limits +%apply. \wxheading{See also} diff --git a/include/wx/defs.h b/include/wx/defs.h index 7f603a5422..45a4f7403c 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -1092,22 +1092,6 @@ enum wxBorder #define wxLB_HSCROLL wxHSCROLL // always show an entire number of rows #define wxLB_INT_HEIGHT 0x0800 -/* - * wxTextCtrl style flags - */ -// the flag bits 0x0001, 2, 4 and 8 are free but should be used only for the -// things which don't make sense for a text control used by wxTextEntryDialog -// because they would otherwise conflict with wxOK, wxCANCEL, wxCENTRE -#define wxTE_READONLY 0x0010 -#define wxTE_MULTILINE 0x0020 -#define wxTE_PROCESS_TAB 0x0040 -// this style means to use RICHEDIT control and does something only under wxMSW -// and Win32 and is silently ignored under all other platforms -#define wxTE_RICH 0x0080 -#define wxTE_NO_VSCROLL 0x0100 -#define wxTE_AUTO_SCROLL 0x0200 -#define wxTE_PROCESS_ENTER 0x0400 -#define wxTE_PASSWORD 0x0800 // use wxHSCROLL to not wrap text at all, wxTE_LINEWRAP to wrap it at any // position and wxTE_WORDWRAP to wrap at words boundary diff --git a/include/wx/event.h b/include/wx/event.h index 4f64c38725..92f344d41c 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -104,7 +104,7 @@ BEGIN_DECLARE_EVENT_TYPES() #else // !WXWIN_COMPATIBILITY_EVENT_TYPES // it is important to still have these as constants to avoid // initialization order related problems - DECLARE_EVENT_TYPE(wxEVT_NULL,0); + DECLARE_EVENT_TYPE(wxEVT_NULL,0); const wxEventType wxEVT_FIRST = 10000; const wxEventType wxEVT_USER_FIRST = wxEVT_FIRST + 2000; #endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES @@ -115,8 +115,10 @@ BEGIN_DECLARE_EVENT_TYPES() DECLARE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_SELECTED, 4) DECLARE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 5) DECLARE_EVENT_TYPE(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 6) + /* now in wx/textctrl.h DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED, 7) DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER, 8) + */ DECLARE_EVENT_TYPE(wxEVT_COMMAND_MENU_SELECTED, 9) DECLARE_EVENT_TYPE(wxEVT_COMMAND_SLIDER_UPDATED, 10) DECLARE_EVENT_TYPE(wxEVT_COMMAND_RADIOBOX_SELECTED, 11) @@ -1930,8 +1932,6 @@ typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&); #define EVT_CHOICE(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_CHOICE_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), #define EVT_LISTBOX(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LISTBOX_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), #define EVT_LISTBOX_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), -#define EVT_TEXT(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_TEXT_UPDATED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), -#define EVT_TEXT_ENTER(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_TEXT_ENTER, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), #define EVT_MENU(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_MENU_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), #define EVT_MENU_RANGE(id1, id2, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_MENU_SELECTED, id1, id2, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), #define EVT_SLIDER(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_SLIDER_UPDATED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), diff --git a/include/wx/msw/textctrl.h b/include/wx/msw/textctrl.h index 1f85ae5ca3..b516b8c8a3 100644 --- a/include/wx/msw/textctrl.h +++ b/include/wx/msw/textctrl.h @@ -131,6 +131,8 @@ public: #endif #if wxUSE_RICHEDIT + virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result); + bool IsRich() const { return m_isRich; } void SetRichEdit(bool isRich) { m_isRich = isRich; } diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index eb83f06c39..aa8f5bf48a 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -59,6 +59,31 @@ class WXDLLEXPORT wxTextCtrl; WXDLLEXPORT_DATA(extern const wxChar*) wxTextCtrlNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxEmptyString; +// ---------------------------------------------------------------------------- +// wxTextCtrl style flags +// ---------------------------------------------------------------------------- + +// the flag bits 0x0001, 2, 4 and 8 are free but should be used only for the +// things which don't make sense for a text control used by wxTextEntryDialog +// because they would otherwise conflict with wxOK, wxCANCEL, wxCENTRE +#define wxTE_READONLY 0x0010 +#define wxTE_MULTILINE 0x0020 +#define wxTE_PROCESS_TAB 0x0040 + +// this style means to use RICHEDIT control and does something only under wxMSW +// and Win32 and is silently ignored under all other platforms +#define wxTE_RICH 0x0080 +#define wxTE_NO_VSCROLL 0x0100 +#define wxTE_AUTO_SCROLL 0x0200 +#define wxTE_PROCESS_ENTER 0x0400 +#define wxTE_PASSWORD 0x0800 + +// automatically detect the URLs and generate the events when mouse is +// moved/clicked over an URL +// +// this is for Win32 richedit controls only so far +#define wxTE_AUTO_URL 0x1000 + // ---------------------------------------------------------------------------- // wxTextAttr: a structure containing the visual attributes of a text // ---------------------------------------------------------------------------- @@ -254,6 +279,56 @@ private: #include "wx/stubs/textctrl.h" #endif +// ---------------------------------------------------------------------------- +// wxTextCtrl events +// ---------------------------------------------------------------------------- + +BEGIN_DECLARE_EVENT_TYPES() + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED, 7) + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER, 8) + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL, 13) +END_DECLARE_EVENT_TYPES() + +class WXDLLEXPORT wxTextUrlEvent : public wxCommandEvent +{ +public: + wxTextUrlEvent(int id, const wxMouseEvent& evtMouse, + long start, long end) + : wxCommandEvent(wxEVT_COMMAND_TEXT_URL, id), + m_evtMouse(evtMouse) + { m_start = start; m_end = end; } + + // get the mouse event which happend over the URL + const wxMouseEvent& GetMouseEvent() const { return m_evtMouse; } + + // get the start of the URL + long GetURLStart() const { return m_start; } + + // get the end of the URL + long GetURLEnd() const { return m_end; } + +protected: + // the corresponding mouse event + wxMouseEvent m_evtMouse; + + // the start and end indices of the URL in the text control + long m_start, + m_end; + +private: + DECLARE_DYNAMIC_CLASS(wxTextUrlEvent) + +public: + // for wxWin RTTI only, don't use + wxTextUrlEvent() { } +}; + +typedef void (wxEvtHandler::*wxTextUrlEventFunction)(wxTextUrlEvent&); + +#define EVT_TEXT(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_TEXT_UPDATED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), +#define EVT_TEXT_ENTER(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_TEXT_ENTER, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & fn, (wxObject *) NULL ), +#define EVT_TEXT_URL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_TEXT_URL, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxTextUrlEventFunction) & fn, (wxObject *) NULL ), + #endif // wxUSE_TEXTCTRL #endif diff --git a/samples/text/text.cpp b/samples/text/text.cpp index dece7ff5a5..fc7716f5a5 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -67,6 +67,7 @@ public: void OnKeyUp(wxKeyEvent& event); void OnChar(wxKeyEvent& event); void OnText(wxCommandEvent& event); + void OnTextURL(wxTextUrlEvent& event); void OnMouseEvent(wxMouseEvent& event); bool m_hasCapture; @@ -275,6 +276,7 @@ BEGIN_EVENT_TABLE(MyTextCtrl, wxTextCtrl) EVT_KEY_UP(MyTextCtrl::OnKeyUp) EVT_CHAR(MyTextCtrl::OnChar) EVT_TEXT(-1, MyTextCtrl::OnText) + EVT_TEXT_URL(-1, MyTextCtrl::OnTextURL) EVT_MOUSE_EVENTS(MyTextCtrl::OnMouseEvent) END_EVENT_TABLE() @@ -406,6 +408,40 @@ void MyTextCtrl::LogEvent(const wxChar *name, wxKeyEvent& event) const GetChar( event.MetaDown(), _T('M') ) ); } +static wxString GetMouseEventDesc(const wxMouseEvent& ev) +{ + // click event + wxString button; + bool dbl, up; + if ( ev.LeftDown() || ev.LeftUp() || ev.LeftDClick() ) + { + button = _T("Left"); + dbl = ev.LeftDClick(); + up = ev.LeftUp(); + } + else if ( ev.MiddleDown() || ev.MiddleUp() || ev.MiddleDClick() ) + { + button = _T("Middle"); + dbl = ev.MiddleDClick(); + up = ev.MiddleUp(); + } + else if ( ev.RightDown() || ev.RightUp() || ev.RightDClick() ) + { + button = _T("Right"); + dbl = ev.RightDClick(); + up = ev.RightUp(); + } + else + { + return _T("Unknown mouse event"); + } + + return wxString::Format(_T("%s mouse button %s"), + button.c_str(), + dbl ? _T("double clicked") + : up ? _T("released") : _T("clicked")); +} + void MyTextCtrl::OnMouseEvent(wxMouseEvent& ev) { if ( !ev.Moving() ) @@ -421,37 +457,7 @@ void MyTextCtrl::OnMouseEvent(wxMouseEvent& ev) } else { - // click event - wxString button; - bool dbl, up; - if ( ev.LeftDown() || ev.LeftUp() || ev.LeftDClick() ) - { - button = _T("Left"); - dbl = ev.LeftDClick(); - up = ev.LeftUp(); - } - else if ( ev.MiddleDown() || ev.MiddleUp() || ev.MiddleDClick() ) - { - button = _T("Middle"); - dbl = ev.MiddleDClick(); - up = ev.MiddleUp(); - } - else if ( ev.RightDown() || ev.RightUp() || ev.RightDClick() ) - { - button = _T("Right"); - dbl = ev.RightDClick(); - up = ev.RightUp(); - } - else - { - wxLogStatus(_T("Unknown mouse event")); - return; - } - - msg.Printf(_T("%s mouse button %s"), - button.c_str(), - dbl ? _T("double clicked") - : up ? _T("released") : _T("clicked")); + msg = GetMouseEventDesc(ev); } msg << _T(" at (") << ev.GetX() << _T(", ") << ev.GetY() << _T(") ") @@ -485,6 +491,22 @@ void MyTextCtrl::OnText(wxCommandEvent& event) } } +void MyTextCtrl::OnTextURL(wxTextUrlEvent& event) +{ + const wxMouseEvent& ev = event.GetMouseEvent(); + + // filter out mouse moves, too many of them + if ( ev.Moving() ) + return; + + long start = event.GetURLStart(), + end = event.GetURLEnd(); + + wxLogMessage(_T("Mouse event over URL '%s': %s"), + GetValue().Mid(start, end - start).c_str(), + GetMouseEventDesc(ev).c_str()); +} + void MyTextCtrl::OnChar(wxKeyEvent& event) { LogEvent( _T("Char"), event); @@ -668,7 +690,10 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h ) "very very very long line to test" "wxHSCROLL style", wxPoint(450, 10), wxSize(230, 230), - wxTE_RICH | wxTE_MULTILINE | wxHSCROLL); + wxTE_RICH | + wxTE_MULTILINE | + wxTE_AUTO_URL | + wxHSCROLL); m_textrich->SetStyle(0, 10, *wxRED); m_textrich->SetStyle(10, 20, *wxBLUE); diff --git a/src/common/event.cpp b/src/common/event.cpp index 49ce7c19fa..043fa5caab 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -120,8 +120,6 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHOICE_SELECTED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_SELECTED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER) DEFINE_EVENT_TYPE(wxEVT_COMMAND_MENU_SELECTED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_SLIDER_UPDATED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBOX_SELECTED) diff --git a/src/common/textcmn.cpp b/src/common/textcmn.cpp index c854878f7a..3563743cfd 100644 --- a/src/common/textcmn.cpp +++ b/src/common/textcmn.cpp @@ -46,6 +46,12 @@ // implementation // ============================================================================ +IMPLEMENT_DYNAMIC_CLASS(wxTextUrlEvent, wxCommandEvent) + +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL) + // ---------------------------------------------------------------------------- // ctor // ---------------------------------------------------------------------------- diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 96ff0f3edd..caa8d82fe0 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -298,11 +298,19 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, #if wxUSE_RICHEDIT if (m_isRich) { - // Have to enable events - ::SendMessage(GetHwnd(), EM_SETEVENTMASK, 0, - ENM_CHANGE | ENM_DROPFILES | ENM_SELCHANGE | ENM_UPDATE); + // have to enable events manually + LPARAM mask = ENM_CHANGE | ENM_DROPFILES | ENM_SELCHANGE | ENM_UPDATE; + + if ( m_windowStyle & wxTE_AUTO_URL ) + { + mask |= ENM_LINK; + + ::SendMessage(GetHwnd(), EM_AUTOURLDETECT, TRUE, 0); + } + + ::SendMessage(GetHwnd(), EM_SETEVENTMASK, 0, mask); } -#endif +#endif // wxUSE_RICHEDIT SubclassWin(GetHWND()); @@ -1170,6 +1178,72 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) // the rest of the file only deals with the rich edit controls #if wxUSE_RICHEDIT +// ---------------------------------------------------------------------------- +// EN_LINK processing +// ---------------------------------------------------------------------------- + +bool wxTextCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) +{ + NMHDR *hdr = (NMHDR* )lParam; + if ( hdr->code == EN_LINK ) + { + ENLINK *enlink = (ENLINK *)hdr; + + switch ( enlink->msg ) + { + case WM_SETCURSOR: + // ok, so it is hardcoded - do we really nee to customize it? + ::SetCursor(GetHcursorOf(wxCursor(wxCURSOR_HAND))); + *result = TRUE; + break; + + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + // send a mouse event + { + static const wxEventType eventsMouse[] = + { + wxEVT_MOTION, + wxEVT_LEFT_DOWN, + wxEVT_LEFT_UP, + wxEVT_LEFT_DCLICK, + wxEVT_RIGHT_DOWN, + wxEVT_RIGHT_UP, + wxEVT_RIGHT_DCLICK, + }; + + // the event ids are consecutive + wxMouseEvent + evtMouse(eventsMouse[enlink->msg - WM_MOUSEMOVE]); + + InitMouseEvent(evtMouse, + GET_X_LPARAM(enlink->lParam), + GET_Y_LPARAM(enlink->lParam), + enlink->wParam); + + wxTextUrlEvent event(m_windowId, evtMouse, + enlink->chrg.cpMin, + enlink->chrg.cpMax); + + InitCommandEvent(event); + + *result = ProcessCommand(event); + } + break; + } + + return TRUE; + } + + // not processed + return FALSE; +} + // ---------------------------------------------------------------------------- // colour setting for the rich edit controls // ---------------------------------------------------------------------------- -- 2.45.2