X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5b2f31eb30be576374064413b9d0f63a1bf8c110..15c3723c6092669f91c9251382f4a1521deeceeb:/src/msw/textctrl.cpp diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 4ecf1d2019..a5a89ea845 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -300,10 +300,17 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, #if wxUSE_RICHEDIT if ( IsRich() ) { - // have to enable events manually - LPARAM mask = ENM_CHANGE | ENM_DROPFILES | ENM_SELCHANGE | ENM_UPDATE; + // enable the events we're interested in: we want to get EN_CHANGE and + // EN_UPDATE as for the normal controls + LPARAM mask = ENM_CHANGE | ENM_UPDATE; - if ( m_windowStyle & wxTE_AUTO_URL ) + if ( GetRichVersion() == 1 ) + { + // we also need EN_MSGFILTER for richedit 1.0 for the reasons + // explained in its handler + mask |= ENM_MOUSEEVENTS; + } + else if ( m_windowStyle & wxTE_AUTO_URL ) { mask |= ENM_LINK; @@ -357,6 +364,12 @@ void wxTextCtrl::AdoptAttributesFromHWND() WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const { + // default border for the text controls is the sunken one + if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT ) + { + style |= wxBORDER_SUNKEN; + } + long msStyle = wxControl::MSWGetStyle(style, exstyle); // default styles @@ -665,7 +678,10 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly) { if ( !selectionOnly ) { - SetSelection(-1, -1); + //SetSelection(-1, -1); + // This eliminates an annoying flashing effect + // when replacing all text. + Clear(); } ::SendMessage(GetHwnd(), EM_REPLACESEL, 0, (LPARAM)valueDos.c_str()); @@ -686,6 +702,25 @@ void wxTextCtrl::Clear() ::SetWindowText(GetHwnd(), wxT("")); } +#ifdef __WIN32__ + +bool wxTextCtrl::EmulateKeyPress(const wxKeyEvent& event) +{ + SetFocus(); + + size_t lenOld = GetValue().length(); + + wxUint32 code = event.GetRawKeyCode(); + ::keybd_event(code, 0, 0 /* key press */, 0); + ::keybd_event(code, 0, KEYEVENTF_KEYUP, 0); + + // assume that any alphanumeric key changes the total number of characters + // in the control - this should work in 99% of cases + return GetValue().length() != lenOld; +} + +#endif // __WIN32__ + // ---------------------------------------------------------------------------- // Clipboard operations // ---------------------------------------------------------------------------- @@ -838,6 +873,12 @@ void wxTextCtrl::GetSelection(long* from, long* to) const bool wxTextCtrl::IsEditable() const { + // strangely enough, we may be called before the control is created: our + // own Create() calls MSWGetStyle() which calls AcceptsFocus() which calls + // us + if ( !m_hWnd ) + return TRUE; + long style = ::GetWindowLong(GetHwnd(), GWL_STYLE); return (style & ES_READONLY) == 0; @@ -1186,7 +1227,8 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) long wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { - // we always want the characters and the arrows + long lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam); + if ( nMsg == WM_GETDLGCODE ) { // we always want the chars and the arrows @@ -1194,22 +1236,30 @@ long wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) // we may have several different cases: // 1. normal case: both TAB and ENTER are used for dialog navigation - // 2. ctrl which wants TAB for itself: ENTER is used to pass to the next - // control in the dialog - // 3. ctrl which wants ENTER for itself: TAB is used for dialog navigation - // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to pass to - // the next control - if ( m_windowStyle & wxTE_PROCESS_ENTER ) + // 2. ctrl which wants TAB for itself: ENTER is used to pass to the + // next control in the dialog + // 3. ctrl which wants ENTER for itself: TAB is used for dialog + // navigation + // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to pass + // to the next control + + // the multiline edit control should always get for itself + if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) ) lDlgCode |= DLGC_WANTMESSAGE; - if ( m_windowStyle & wxTE_PROCESS_TAB ) + + if ( HasFlag(wxTE_PROCESS_TAB) ) lDlgCode |= DLGC_WANTTAB; - return lDlgCode; + lRc |= lDlgCode; } - return wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam); + return lRc; } +// ---------------------------------------------------------------------------- +// text control event processing +// ---------------------------------------------------------------------------- + bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) { switch (param) @@ -1251,6 +1301,7 @@ bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) case EN_HSCROLL: case EN_VSCROLL: return FALSE; + default: return FALSE; } @@ -1463,66 +1514,97 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) // EN_LINK processing // ---------------------------------------------------------------------------- -bool wxTextCtrl::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *result) +bool wxTextCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { NMHDR *hdr = (NMHDR* )lParam; - if ( hdr->code == EN_LINK ) + switch ( hdr->code ) { - 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 + case EN_MSGFILTER: + { + const MSGFILTER *msgf = (MSGFILTER *)lParam; + UINT msg = msgf->msg; + + // this is a bit crazy but richedit 1.0 sends us all mouse + // events _except_ WM_LBUTTONUP (don't ask me why) so we have + // generate the wxWin events for this message manually + // + // NB: in fact, this is still not totally correct as it does + // send us WM_LBUTTONUP if the selection was cleared by the + // last click -- so currently we get 2 events in this case, + // but as I don't see any obvious way to check for this I + // leave this code in place because it's still better than + // not getting left up events at all + if ( msg == WM_LBUTTONUP ) { - 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); + WXUINT flags = msgf->wParam; + int x = GET_X_LPARAM(msgf->lParam), + y = GET_Y_LPARAM(msgf->lParam); + + HandleMouseEvent(msg, x, y, flags); } - break; - } + } - return TRUE; + // return TRUE to process the event (and FALSE to ignore it) + return TRUE; + + case EN_LINK: + { + const 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; + // not processed, leave it to the base class + return wxTextCtrlBase::MSWOnNotify(idCtrl, lParam, result); } // ---------------------------------------------------------------------------- @@ -1573,6 +1655,8 @@ bool wxTextCtrl::SetForegroundColour(const wxColour& colour) // styling support for rich edit controls // ---------------------------------------------------------------------------- +#if wxUSE_RICHEDIT + bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) { if ( !IsRich() ) @@ -1706,6 +1790,21 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) return ok; } +bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style) +{ + if ( !wxTextCtrlBase::SetDefaultStyle(style) ) + return FALSE; + + // we have to do this or the style wouldn't apply for the text typed by the + // user + long posLast = GetLastPosition(); + SetStyle(posLast, posLast, m_defaultStyle); + + return TRUE; +} + +#endif + // ---------------------------------------------------------------------------- // wxRichEditModule // ----------------------------------------------------------------------------