X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d7e0024b09f3141bc0c14e74b376cd2fb9567335..ad4e3f7be6f20d5a164a608b44c51056231ddad9:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 2067b22fa5..07f84ec60e 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/msw/windows.cpp -// Purpose: wxWindow +// Name: src/msw/window.cpp +// Purpose: wxWindowMSW // Author: Julian Smart // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation // Created: 04/01/98 @@ -17,10 +17,6 @@ // headers // --------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "window.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -127,6 +123,14 @@ // by setting this to 0 (in the future this should be removed completely) #define USE_DEFERRED_SIZING 1 +// set this to 1 to filter out duplicate mouse events, e.g. mouse move events +// when mouse position didnd't change +#ifdef __WXWINCE__ + #define wxUSE_MOUSEEVENT_HACK 0 +#else + #define wxUSE_MOUSEEVENT_HACK 1 +#endif + // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- @@ -145,6 +149,18 @@ extern const wxChar *wxCanvasClassName; // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT) static bool gs_hasStdCmap = false; +// last mouse event information we need to filter out the duplicates +#if wxUSE_MOUSEEVENT_HACK +static struct MouseEventInfoDummy +{ + // mouse position (in screen coordinates) + wxPoint pos; + + // last mouse event type + wxEventType type; +} gs_lastMouseEvent; +#endif // wxUSE_MOUSEEVENT_HACK + // --------------------------------------------------------------------------- // private functions // --------------------------------------------------------------------------- @@ -204,7 +220,7 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent) get back to the initial (focused) window: as we do have this style, GetNextDlgTabItem() will leave this window and continue in its parent, but if the parent doesn't have it, it wouldn't recurse inside it later - on and so wouldn't have a chance of getting back to this window neither. + on and so wouldn't have a chance of getting back to this window either. */ while ( parent && !parent->IsTopLevel() ) { @@ -378,7 +394,7 @@ wxWindow *wxWindowMSW::FindItem(long id) const wxControl *item = wxDynamicCastThis(wxControl); if ( item ) { - // is it we or one of our "internal" children? + // is it us or one of our "internal" children? if ( item->GetId() == id #ifndef __WXUNIVERSAL__ || (item->GetSubcontrols().Index(id) != wxNOT_FOUND) @@ -466,12 +482,6 @@ void wxWindowMSW::Init() m_xThumbSize = 0; m_yThumbSize = 0; -#if wxUSE_MOUSEEVENT_HACK - m_lastMouseX = - m_lastMouseY = -1; - m_lastMouseEvent = -1; -#endif // wxUSE_MOUSEEVENT_HACK - m_pendingPosition = wxDefaultPosition; m_pendingSize = wxDefaultSize; } @@ -503,7 +513,7 @@ wxWindowMSW::~wxWindowMSW() #endif // __WXUNIVERSAL__ // VS: destroy children first and _then_ detach *this from its parent. - // If we'd do it the other way around, children wouldn't be able + // If we did it the other way around, children wouldn't be able // find their parent frame (see above). DestroyChildren(); @@ -655,7 +665,7 @@ bool wxWindowMSW::Enable(bool enable) if ( enable ) { - // enable the child back unless it had been disabled before us + // re-enable the child unless it had been disabled before us if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) ) child->Enable(); } @@ -694,12 +704,18 @@ bool wxWindowMSW::Show(bool show) return false; HWND hWnd = GetHwnd(); - int cshow = show ? SW_SHOW : SW_HIDE; - ::ShowWindow(hWnd, cshow); - if ( show && IsTopLevel() ) + // we could be called before the underlying window is created (this is + // actually useful to prevent it from being initially shown), e.g. + // + // wxFoo *foo = new wxFoo; + // foo->Hide(); + // foo->Create(parent, ...); + // + // should work without errors + if ( hWnd ) { - wxBringWindowToTop(hWnd); + ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE); } return true; @@ -718,16 +734,6 @@ void wxWindowMSW::Lower() SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } -void wxWindowMSW::SetTitle( const wxString& title) -{ - SetWindowText(GetHwnd(), title.c_str()); -} - -wxString wxWindowMSW::GetTitle() const -{ - return wxGetWindowText(GetHWND()); -} - void wxWindowMSW::DoCaptureMouse() { HWND hWnd = GetHwnd(); @@ -810,9 +816,9 @@ void wxWindowMSW::WarpPointer(int x, int y) } } -void wxWindowMSW::MSWUpdateUIState() +void wxWindowMSW::MSWUpdateUIState(int action, int state) { - // WM_UPDATEUISTATE only appeared in Windows 2000 so it can do us no good + // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good // to use it on older systems -- and could possibly do some harm static int s_needToUpdate = -1; if ( s_needToUpdate == -1 ) @@ -824,12 +830,9 @@ void wxWindowMSW::MSWUpdateUIState() if ( s_needToUpdate ) { - // NB: it doesn't seem to matter what we put in wParam, whether we - // include just one UISF_XXX or both, both are affected, no idea - // why - ::SendMessage(GetHwnd(), WM_UPDATEUISTATE, - MAKEWPARAM(UIS_INITIALIZE, - UISF_HIDEFOCUS | UISF_HIDEACCEL), 0); + // we send WM_CHANGEUISTATE so if nothing needs changing then the system + // won't send WM_UPDATEUISTATE + ::SendMessage(GetHwnd(), WM_CHANGEUISTATE, MAKEWPARAM(action, state), 0); } } @@ -845,15 +848,10 @@ inline int GetScrollPosition(HWND hWnd, int wOrient) WinStruct scrollInfo; scrollInfo.cbSize = sizeof(SCROLLINFO); scrollInfo.fMask = SIF_POS; - if ( !::GetScrollInfo(hWnd, - wOrient, - &scrollInfo) ) - { - // Not necessarily an error, if there are no scrollbars yet. - // wxLogLastError(_T("GetScrollInfo")); - } + ::GetScrollInfo(hWnd, wOrient, &scrollInfo ); + return scrollInfo.nPos; -// return ::GetScrollPos(hWnd, wOrient); + #endif } @@ -1036,7 +1034,7 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd) } else { - // don't bother restoring it neither: this also makes it easy to + // don't bother restoring it either: this also makes it easy to // implement IsOfStandardClass() method which returns true for the // standard controls and false for the wxWidgets own windows as it can // simply check m_oldWndProc @@ -1117,8 +1115,8 @@ bool wxCheckWindowWndProc(WXHWND hWnd, str == wxMDIChildFrameClassNameNoRedraw || str == _T("wxTLWHiddenParent")) return true; // Effectively means don't subclass - else - return false; + + return false; #else WNDCLASS cls; if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) ) @@ -1200,7 +1198,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const // using this flag results in very significant reduction in flicker, // especially with controls inside the static boxes (as the interior of the - // box is not redrawn twice).but sometimes results in redraw problems, so + // box is not redrawn twice), but sometimes results in redraw problems, so // optionally allow the old code to continue to use it provided a special // system option is turned on if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) @@ -1444,7 +1442,7 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) } #endif // wxUSE_DRAG_AND_DROP -// old style file-manager drag&drop support: we retain the old-style +// old-style file manager drag&drop support: we retain the old-style // DragAcceptFiles in parallel with SetDropTarget. void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept)) { @@ -1737,7 +1735,7 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) void wxWindowMSW::DoSetClientSize(int width, int height) { - // setting the client size is less obvious than it it could have been + // setting the client size is less obvious than it could have been // because in the result of changing the total size the window scrollbar // may [dis]appear and/or its menubar may [un]wrap and so the client size // will not be correct as the difference between the total and client size @@ -1905,7 +1903,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) #endif ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL); - // we need to do it righ now as otherwise the events are never going to be + // we need to do it right now as otherwise the events are never going to be // sent to wxCurrentPopupMenu from HandleCommand() // // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't @@ -2046,6 +2044,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) else // no default button #endif // wxUSE_BUTTON { +#ifdef __WXWINCE__ + wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN); + event.SetEventObject(this); + if(GetEventHandler()->ProcessEvent(event)) + return true; +#endif // this is a quick and dirty test for a text // control if ( !(lDlgCode & DLGC_HASSETSEL) ) @@ -2086,9 +2090,8 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) { // as we don't call IsDialogMessage(), which would take of // this by default, we need to manually send this message - // so that controls could change their appearance - // appropriately - MSWUpdateUIState(); + // so that controls can change their UI state if needed + MSWUpdateUIState(UIS_CLEAR, UISF_HIDEFOCUS); return true; } @@ -2103,7 +2106,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) { // ::IsDialogMessage() is broken and may sometimes hang the // application by going into an infinite loop, so we try to detect - // [some of] the situatations when this may happen and not call it + // [some of] the situations when this may happen and not call it // then // assume we can call it by default @@ -2124,7 +2127,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) #if !defined(__WXWINCE__) if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { - // passimistic by default + // pessimistic by default canSafelyCallIsDlgMsg = false; for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; @@ -2674,7 +2677,7 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l { switch ( wParam ) { - // we consider these message "not interesting" to OnChar, so + // we consider these messages "not interesting" to OnChar, so // just don't do anything more with them case VK_SHIFT: case VK_CONTROL: @@ -3194,8 +3197,6 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // WM_NOTIFY // --------------------------------------------------------------------------- -#ifdef __WIN95__ - bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { #ifndef __WXMICROWIN__ @@ -3339,8 +3340,6 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), return false; } -#endif // __WIN95__ - // --------------------------------------------------------------------------- // end session messages // --------------------------------------------------------------------------- @@ -3529,6 +3528,20 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) return GetEventHandler()->ProcessEvent(event); } +// --------------------------------------------------------------------------- +// labels +// --------------------------------------------------------------------------- + +void wxWindowMSW::SetLabel( const wxString& label) +{ + SetWindowText(GetHwnd(), label.c_str()); +} + +wxString wxWindowMSW::GetLabel() const +{ + return wxGetWindowText(GetHWND()); +} + // --------------------------------------------------------------------------- // miscellaneous // --------------------------------------------------------------------------- @@ -4498,9 +4511,8 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, event.SetId(GetId()); #if wxUSE_MOUSEEVENT_HACK - m_lastMouseX = x; - m_lastMouseY = y; - m_lastMouseEvent = event.GetEventType(); + gs_lastMouseEvent.pos = ClientToScreen(wxPoint(x, y)); + gs_lastMouseEvent.type = event.GetEventType(); #endif // wxUSE_MOUSEEVENT_HACK } @@ -4626,19 +4638,36 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) (void)GetEventHandler()->ProcessEvent(event); } } +#ifdef HAVE_TRACKMOUSEEVENT + else + { + // Check if we need to send a LEAVE event + // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so + // send it here if we are using native mouse leave tracking + if ( HasCapture() && !IsMouseInWindow() ) + { + GenerateMouseLeave(); + } + } +#endif // HAVE_TRACKMOUSEEVENT #if wxUSE_MOUSEEVENT_HACK - // Window gets a click down message followed by a mouse move message even - // if position isn't changed! We want to discard the trailing move event - // if x and y are the same. - if ( (m_lastMouseEvent == wxEVT_RIGHT_DOWN || - m_lastMouseEvent == wxEVT_LEFT_DOWN || - m_lastMouseEvent == wxEVT_MIDDLE_DOWN) && - (m_lastMouseX == x && m_lastMouseY == y) ) - { - m_lastMouseEvent = wxEVT_MOTION; + // Windows often generates mouse events even if mouse position hasn't + // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576) + // + // Filter this out as it can result in unexpected behaviour compared to + // other platforms + if ( gs_lastMouseEvent.type == wxEVT_RIGHT_DOWN || + gs_lastMouseEvent.type == wxEVT_LEFT_DOWN || + gs_lastMouseEvent.type == wxEVT_MIDDLE_DOWN || + gs_lastMouseEvent.type == wxEVT_MOTION ) + { + if ( ClientToScreen(wxPoint(x, y)) == gs_lastMouseEvent.pos ) + { + gs_lastMouseEvent.type = wxEVT_MOTION; - return false; + return false; + } } #endif // wxUSE_MOUSEEVENT_HACK @@ -6169,4 +6198,3 @@ void wxWindowMSW::OnInitDialog( wxInitDialogEvent& event ) event.Skip(); } #endif -