X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cd4453e5889921086191e190e69745bd25b19bc1..dbcbe229628c7667da2b6257198467d4f09ab28d:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 5b07081f99..3d030562ba 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -39,7 +39,6 @@ #include "wx/dcclient.h" #include "wx/utils.h" #include "wx/app.h" - #include "wx/panel.h" #include "wx/layout.h" #include "wx/dialog.h" #include "wx/frame.h" @@ -47,8 +46,7 @@ #include "wx/button.h" #include "wx/msgdlg.h" #include "wx/settings.h" - - #include + #include "wx/statbox.h" #endif #if wxUSE_OWNER_DRAWN @@ -132,7 +130,6 @@ extern MSG s_currentMsg; wxMenu *wxCurrentPopupMenu = NULL; #endif // wxUSE_MENUS_NATIVE -extern wxList WXDLLEXPORT wxPendingDelete; extern const wxChar *wxCanvasClassName; // --------------------------------------------------------------------------- @@ -179,7 +176,6 @@ BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase) EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged) EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog) EVT_IDLE(wxWindowMSW::OnIdle) - EVT_SET_FOCUS(wxWindowMSW::OnSetFocus) END_EVENT_TABLE() // =========================================================================== @@ -194,7 +190,7 @@ END_EVENT_TABLE() wxWindow *wxWindowMSW::FindItem(long id) const { #if wxUSE_CONTROLS - wxControl *item = wxDynamicThisCast(this, wxControl); + wxControl *item = wxDynamicCastThis(wxControl); if ( item ) { // is it we or one of our "internal" children? @@ -354,6 +350,17 @@ bool wxWindowMSW::Create(wxWindow *parent, { wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); +#if wxUSE_STATBOX + // wxGTK doesn't allow to create controls with static box as the parent so + // this will result in a crash when the program is ported to wxGTK - warn + // about it + // + // the correct solution is to create the controls as siblings of the + // static box + wxASSERT_MSG( !wxDynamicCastThis(wxStaticBox), + _T("wxStaticBox can't be used as a window parent!") ); +#endif // wxUSE_STATBOX + if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) return FALSE; @@ -760,6 +767,15 @@ int wxWindowMSW::GetScrollPage(int orient) const #endif // WXWIN_COMPATIBILITY +inline int GetScrollPosition(HWND hWnd, int wOrient) +{ +#ifdef __WXMICROWIN__ + return ::GetScrollPosWX(hWnd, wOrient); +#else + return ::GetScrollPos(hWnd, wOrient); +#endif +} + int wxWindowMSW::GetScrollPos(int orient) const { int wOrient; @@ -767,17 +783,11 @@ int wxWindowMSW::GetScrollPos(int orient) const wOrient = SB_HORZ; else wOrient = SB_VERT; + HWND hWnd = GetHwnd(); - if ( hWnd ) - { -#ifdef __WXMICROWIN__ - return ::GetScrollPosWX(hWnd, wOrient); -#else - return ::GetScrollPos(hWnd, wOrient); -#endif - } - else - return 0; + wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") ); + + return GetScrollPosition(hWnd, wOrient); } // This now returns the whole range, not just the number @@ -930,6 +940,46 @@ void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect) ::ScrollWindow(GetHwnd(), dx, dy, prect ? &rect : NULL, NULL); } +static bool ScrollVertically(HWND hwnd, int kind, int count) +{ + int posStart = GetScrollPosition(hwnd, SB_VERT); + + int pos = posStart; + for ( int n = 0; n < count; n++ ) + { + ::SendMessage(hwnd, WM_VSCROLL, kind, 0); + + int posNew = GetScrollPosition(hwnd, SB_VERT); + if ( posNew == pos ) + { + // don't bother to continue, we're already at top/bottom + break; + } + + pos = posNew; + } + + return pos != posStart; +} + +bool wxWindowMSW::ScrollLines(int lines) +{ + bool down = lines > 0; + + return ScrollVertically(GetHwnd(), + down ? SB_LINEDOWN : SB_LINEUP, + down ? lines : -lines); +} + +bool wxWindowMSW::ScrollPages(int pages) +{ + bool down = pages > 0; + + return ScrollVertically(GetHwnd(), + down ? SB_PAGEDOWN : SB_PAGEUP, + down ? pages : -pages); +} + // --------------------------------------------------------------------------- // subclassing // --------------------------------------------------------------------------- @@ -1184,6 +1234,25 @@ void wxWindowMSW::Clear() dc.Clear(); } +static inline void SendSetRedraw(HWND hwnd, bool on) +{ + ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0); +} + +void wxWindowMSW::Freeze() +{ + SendSetRedraw(GetHwnd(), FALSE); +} + +void wxWindowMSW::Thaw() +{ + SendSetRedraw(GetHwnd(), TRUE); + + // we need to refresh everything or otherwise he invalidated area is not + // repainted + Refresh(); +} + void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) { HWND hWnd = GetHwnd(); @@ -1774,18 +1843,13 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) bProcess = FALSE; } -#if wxUSE_BUTTON + // FIXME: this should be handled by + // wxNavigationKeyEvent handler and not here!! else { - wxPanel *panel = wxDynamicThisCast(this, wxPanel); - wxButton *btn = NULL; - if ( panel ) - { - // panel may have a default button which should - // be activated by Enter - btn = panel->GetDefaultItem(); - } - +#if wxUSE_BUTTON + wxButton *btn = wxDynamicCast(GetDefaultItem(), + wxButton); if ( btn && btn->IsEnabled() ) { // if we do have a default button, do press it @@ -1793,11 +1857,15 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) return TRUE; } - // else: but if it does not it makes sense to make - // it work like a TAB - and that's what we do. - // Note that Ctrl-Enter always works this way. - } + else // no default button #endif // wxUSE_BUTTON + { + // no special function for enter and don't even + // let IsDialogMessage() have it: it seems to + // do something really strange with it + return FALSE; + } + } } break; @@ -1814,20 +1882,11 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( GetEventHandler()->ProcessEvent(event) ) { -#if wxUSE_BUTTON - wxButton *btn = wxDynamicCast(FindFocus(), wxButton); - if ( btn ) - { - // the button which has focus should be default - btn->SetDefault(); - } -#endif // wxUSE_BUTTON - return TRUE; } } } -#else +#else // 0 // let ::IsDialogMessage() do almost everything and handle just the // things it doesn't here: Ctrl-TAB for switching notebook pages if ( msg->message == WM_KEYDOWN ) @@ -1855,7 +1914,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } } -#endif // 0 +#endif // 1/0 if ( ::IsDialogMessage(GetHwnd(), msg) ) { @@ -1887,6 +1946,12 @@ bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) #endif // wxUSE_ACCEL } +bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* pMsg) +{ + // preprocess all messages by default + return TRUE; +} + // --------------------------------------------------------------------------- // message params unpackers (different for Win16 and Win32) // --------------------------------------------------------------------------- @@ -3012,33 +3077,6 @@ bool wxWindowMSW::HandleDestroy() // activation/focus // --------------------------------------------------------------------------- -void wxWindowMSW::OnSetFocus(wxFocusEvent& event) -{ - // panel wants to track the window which was the last to have focus in it, - // so we want to set ourselves as the window which last had focus - // - // notice that it's also important to do it upwards the tree becaus - // otherwise when the top level panel gets focus, it won't set it back to - // us, but to some other sibling - wxWindow *win = (wxWindow *)this; - while ( win ) - { - wxWindow *parent = win->GetParent(); - wxPanel *panel = wxDynamicCast(parent, wxPanel); - if ( panel ) - { - panel->SetLastFocus(win); - } - - win = parent; - } - - wxLogTrace(_T("focus"), _T("%s (0x%08x) gets focus"), - GetClassInfo()->GetClassName(), GetHandle()); - - event.Skip(); -} - bool wxWindowMSW::HandleActivate(int state, bool WXUNUSED(minimized), WXHWND WXUNUSED(activate)) @@ -3053,6 +3091,11 @@ bool wxWindowMSW::HandleActivate(int state, bool wxWindowMSW::HandleSetFocus(WXHWND hwnd) { + // notify the parent keeping track of focus for the kbd navigation + // purposes that we got it + wxChildFocusEvent eventFocus(this); + (void)GetEventHandler()->ProcessEvent(eventFocus); + #if wxUSE_CARET // Deal with caret if ( m_caret ) @@ -3061,6 +3104,15 @@ bool wxWindowMSW::HandleSetFocus(WXHWND hwnd) } #endif // wxUSE_CARET +#if wxUSE_TEXTCTRL + // If it's a wxTextCtrl don't send the event as it will be done + // after the control gets to process it from EN_FOCUS handler + if ( wxDynamicCastThis(wxTextCtrl) ) + { + return FALSE; + } +#endif // wxUSE_TEXTCTRL + wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId); event.SetEventObject(this); @@ -3080,6 +3132,16 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) } #endif // wxUSE_CARET +#if wxUSE_TEXTCTRL + // If it's a wxTextCtrl don't send the event as it will be done + // after the control gets to process it. + wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl); + if ( ctrl ) + { + return FALSE; + } +#endif + wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId); event.SetEventObject(this); @@ -4160,14 +4222,11 @@ int wxCharCodeMSWToWX(int keySym) case VK_NUMPAD7: id = WXK_NUMPAD7; break; case VK_NUMPAD8: id = WXK_NUMPAD8; break; case VK_NUMPAD9: id = WXK_NUMPAD9; break; - case VK_MULTIPLY: id = WXK_MULTIPLY; break; - case 0xBB: // VK_OEM_PLUS - case VK_ADD: id = WXK_ADD; break; - case 0xBD: // VK_OEM_MINUS - case VK_SUBTRACT: id = WXK_SUBTRACT; break; - case 0xBE: // VK_OEM_PERIOD - case VK_DECIMAL: id = WXK_DECIMAL; break; - case VK_DIVIDE: id = WXK_DIVIDE; break; + case VK_MULTIPLY: id = WXK_NUMPAD_MULTIPLY; break; + case VK_ADD: id = WXK_NUMPAD_ADD; break; + case VK_SUBTRACT: id = WXK_NUMPAD_SUBTRACT; break; + case VK_DECIMAL: id = WXK_NUMPAD_DECIMAL; break; + case VK_DIVIDE: id = WXK_NUMPAD_DIVIDE; break; case VK_F1: id = WXK_F1; break; case VK_F2: id = WXK_F2; break; case VK_F3: id = WXK_F3; break; @@ -4237,11 +4296,11 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) case WXK_NUMPAD7: keySym = VK_NUMPAD7; break; case WXK_NUMPAD8: keySym = VK_NUMPAD8; break; case WXK_NUMPAD9: keySym = VK_NUMPAD9; break; - case WXK_MULTIPLY: keySym = VK_MULTIPLY; break; - case WXK_ADD: keySym = VK_ADD; break; - case WXK_SUBTRACT: keySym = VK_SUBTRACT; break; - case WXK_DECIMAL: keySym = VK_DECIMAL; break; - case WXK_DIVIDE: keySym = VK_DIVIDE; break; + case WXK_NUMPAD_MULTIPLY: keySym = VK_MULTIPLY; break; + case WXK_NUMPAD_ADD: keySym = VK_ADD; break; + case WXK_NUMPAD_SUBTRACT: keySym = VK_SUBTRACT; break; + case WXK_NUMPAD_DECIMAL: keySym = VK_DECIMAL; break; + case WXK_NUMPAD_DIVIDE: keySym = VK_DIVIDE; break; case WXK_F1: keySym = VK_F1; break; case WXK_F2: keySym = VK_F2; break; case WXK_F3: keySym = VK_F3; break; @@ -4325,19 +4384,27 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) #endif // wxUSE_SPINCTRL #endif // Win32 - - if ( !win ) - { - // hwnd is not a wxWindow, try its parent next below - hwnd = ::GetParent(hwnd); - } } } while ( hwnd && !win ) { - win = wxFindWinFromHandle((WXHWND)hwnd); + // this is a really ugly hack needed to avoid mistakenly returning the + // parent frame wxWindow for the find/replace modeless dialog HWND - + // this, in turn, is needed to call IsDialogMessage() from + // wxApp::ProcessMessage() as for this we must return NULL from here + // + // FIXME: this is clearly not the best way to do it but I think we'll + // need to change HWND <-> wxWindow code more heavily than I can + // do it now to fix it + if ( ::GetWindow(hwnd, GW_OWNER) ) + { + // it's a dialog box, don't go upwards + break; + } + hwnd = ::GetParent(hwnd); + win = wxFindWinFromHandle((WXHWND)hwnd); } return win;