X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/48d597ed967da2ff414b9580f499c6e43e0159d6..537a0880d225ab023024f6f5fc8955666b7641b8:/src/msw/window.cpp?ds=sidebyside diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 21055bce76..f7b7c2f982 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -437,6 +437,7 @@ void wxWindowMSW::Init() m_frozenness = 0; m_hWnd = 0; + m_hDWP = 0; m_xThumbSize = 0; m_yThumbSize = 0; @@ -1242,6 +1243,7 @@ bool wxWindowMSW::IsMouseInWindow() const void wxWindowMSW::OnInternalIdle() { +#ifdef __WXWINCE__ // Check if we need to send a LEAVE event if ( m_mouseInWindow ) { @@ -1249,44 +1251,10 @@ void wxWindowMSW::OnInternalIdle() // or doesn't have mouse capture if ( !IsMouseInWindow() ) { - // Generate a LEAVE event - m_mouseInWindow = false; - - // Unfortunately the mouse button and keyboard state may have - // changed by the time the OnInternalIdle function is called, so 'state' - // may be meaningless. - int state = 0; - if ( wxIsShiftDown() ) - state |= MK_SHIFT; - if ( wxIsCtrlDown() ) - state |= MK_CONTROL; - - // Only the high-order bit should be tested - if ( GetKeyState( VK_LBUTTON ) & (1<<15) ) - state |= MK_LBUTTON; - if ( GetKeyState( VK_MBUTTON ) & (1<<15) ) - state |= MK_MBUTTON; - if ( GetKeyState( VK_RBUTTON ) & (1<<15) ) - state |= MK_RBUTTON; - - POINT pt; - if ( !::GetCursorPos(&pt) ) - { - wxLogLastError(_T("GetCursorPos")); - } - - // we need to have client coordinates here for symmetry with - // wxEVT_ENTER_WINDOW - RECT rect = wxGetWindowRect(GetHwnd()); - pt.x -= rect.left; - pt.y -= rect.top; - - wxMouseEvent event2(wxEVT_LEAVE_WINDOW); - InitMouseEvent(event2, pt.x, pt.y, state); - - (void)GetEventHandler()->ProcessEvent(event2); + GenerateMouseLeave(); } } +#endif // !__WXWINCE__ if (wxUpdateUIEvent::CanUpdate(this)) UpdateWindowUI(wxUPDATE_UI_FROMIDLE); @@ -1531,9 +1499,31 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height) if (height < 0) height = 0; - if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) ) + // if our parent had prepared a defer window handle for us, use it (unless + // we are a top level window) + wxWindowMSW *parent = GetParent(); + HDWP hdwp = (parent && !IsTopLevel()) ? (HDWP)parent->m_hDWP : NULL; + if ( hdwp ) { - wxLogLastError(wxT("MoveWindow")); + hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL, + x, y, width, height, + SWP_NOZORDER); + if ( !hdwp ) + { + wxLogLastError(_T("DeferWindowPos")); + } + + // hdwp must be updated as it may have been changed + parent->m_hDWP = (WXHANDLE)hdwp; + } + + // otherwise (or if deferring failed) move the window in place immediately + if ( !hdwp ) + { + if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) ) + { + wxLogLastError(wxT("MoveWindow")); + } } } @@ -1876,8 +1866,21 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) case VK_ESCAPE: { #if wxUSE_BUTTON - wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL), - wxButton); + wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL),wxButton); + + // our own wxLogDialog should react to Esc + // without Cancel button but this is a private class + // so let's try recognize it by content + #if wxUSE_LOG_DIALOG + if ( !btn && + wxDynamicCast(this,wxDialog) && + FindWindow(wxID_MORE) && + FindWindow(wxID_OK) && + !FindWindow(wxID_CANCEL) && + GetTitle().MakeLower().StartsWith(wxTheApp->GetAppName().c_str()) + ) + btn = wxDynamicCast(FindWindow(wxID_OK),wxButton); + #endif // wxUSE_LOG_DIALOG if ( btn && btn->IsEnabled() ) { // if we do have a cancel button, do press it @@ -1918,7 +1921,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) bProcess = false; } // FIXME: this should be handled by - // wxNavigationKeyEvent handler and not here!! + // wxNavigationKeyEvent handler and not here! else { #if wxUSE_BUTTON @@ -2227,6 +2230,49 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l (void)HandleDestroy(); break; +#ifndef __SMARTPHONE__ // or wxWinCE in general ? + case WM_WINDOWPOSCHANGING: + { + WINDOWPOS *wp = wx_reinterpret_cast(WINDOWPOS *, lParam); + + if ( wp->flags & SWP_NOSIZE ) + break; + + // when we resize this window, its children are probably going + // to be repositioned as well, prepare to use DeferWindowPos() + // for them + const int numChildren = GetChildren().GetCount(); + if ( numChildren > 1 ) + { + m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren); + if ( !m_hDWP ) + { + wxLogLastError(_T("BeginDeferWindowPos")); + } + } + } + break; + + case WM_WINDOWPOSCHANGED: + // first let DefWindowProc() handle the message: it will generate + // WM_MOVE and WM_SIZE as needed + processed = MSWDefWindowProc(message, wParam, lParam) == 0; + + // then change the positions of all child windows at once + if ( m_hDWP ) + { + HDWP hDWP = (HDWP)m_hDWP; + m_hDWP = NULL; + + // put all child controls in place at once now + if ( !::EndDeferWindowPos(hDWP) ) + { + wxLogLastError(_T("EndDeferWindowPos")); + } + } + break; +#endif // __SMARTPHONE__ + case WM_SIZE: processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam); break; @@ -2356,61 +2402,23 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l wParam); break; - // Seems to be broken currently -#if 0 // ndef __WXWINCE__ +#ifdef WM_MOUSELEAVE case WM_MOUSELEAVE: - { - wxASSERT_MSG( !m_mouseInWindow, wxT("the mouse should be in a window to generate this event!") ); - - // only process this message if the mouse is not in the window, - // This can also check for children in composite windows. - // however, this may mean the the wxEVT_LEAVE_WINDOW is never sent - // if the mouse does not enter the window from it's child before - // leaving the scope of the window. ( perhaps this can be picked - // up in the OnIdle code as before, for this special case ) - if ( /*IsComposite() && */ !IsMouseInWindow() ) { - m_mouseInWindow = false; - - // Unfortunately no mouse state is passed with a WM_MOUSE_LEAVE - int state = 0; - if ( wxIsShiftDown() ) - state |= MK_SHIFT; - if ( wxIsCtrlDown() ) - state |= MK_CONTROL; - if ( GetKeyState( VK_LBUTTON ) ) - state |= MK_LBUTTON; - if ( GetKeyState( VK_MBUTTON ) ) - state |= MK_MBUTTON; - if ( GetKeyState( VK_RBUTTON ) ) - state |= MK_RBUTTON; - - POINT pt; - if ( !::GetCursorPos(&pt) ) + // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least) + if ( m_mouseInWindow ) { - wxLogLastError(_T("GetCursorPos")); + GenerateMouseLeave(); } - // we need to have client coordinates here for symmetry with - // wxEVT_ENTER_WINDOW - RECT rect = wxGetWindowRect(GetHwnd()); - pt.x -= rect.left; - pt.y -= rect.top; - - wxMouseEvent event2(wxEVT_LEAVE_WINDOW); - InitMouseEvent(event2, pt.x, pt.y, state); - - (void)GetEventHandler()->ProcessEvent(event2); + // always pass processed back as false, this allows the window + // manager to process the message too. This is needed to + // ensure windows XP themes work properly as the mouse moves + // over widgets like buttons. + processed = false; } - // always pass processed back as false, this allows the window - // manager to process the message too. This is needed to ensure - // windows XP themes work properly as the mouse moves over widgets - // like buttons. - processed = false; - } - break; -#endif - // __WXWINCE__ + break; +#endif // WM_MOUSELEAVE #if wxUSE_MOUSEWHEEL case WM_MOUSEWHEEL: @@ -3467,7 +3475,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status)) { wxShowEvent event(GetId(), show); - event.m_eventObject = this; + event.SetEventObject(this); return GetEventHandler()->ProcessEvent(event); } @@ -3475,7 +3483,7 @@ bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status)) bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) { wxInitDialogEvent event(GetId()); - event.m_eventObject = this; + event.SetEventObject(this); return GetEventHandler()->ProcessEvent(event); } @@ -3510,7 +3518,7 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) DragFinish (hFilesInfo); wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files); - event.m_eventObject = this; + event.SetEventObject(this); POINT dropPoint; DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint); @@ -4001,9 +4009,10 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc) void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) { - // standard controls always erase their background themselves (although the - // user may try to override it in a derived class) - if ( IsOfStandardClass() ) + // standard non top level controls (i.e. except the dialogs) always erase + // their background themselves in HandleCtlColor() or have some control- + // specific ways to set the colours (common controls) + if ( IsOfStandardClass() && !IsTopLevel() ) { event.Skip(); return; @@ -4019,21 +4028,26 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) // do default background painting - wxDC& dc = *event.GetDC(); - HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC()); - if ( hBrush ) - { - RECT rc; - ::GetClientRect(GetHwnd(), &rc); - ::FillRect(GetHdcOf(dc), &rc, hBrush); - } - else + if ( !DoEraseBackground(*event.GetDC()) ) { // let the system paint the background event.Skip(); } } +bool wxWindowMSW::DoEraseBackground(wxDC& dc) +{ + HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC()); + if ( !hBrush ) + return false; + + RECT rc; + ::GetClientRect(GetHwnd(), &rc); + ::FillRect(GetHdcOf(dc), &rc, hBrush); + + return true; +} + WXHBRUSH wxWindowMSW::MSWGetSolidBgBrushForChild(wxWindow *child) { wxColour col = MSWGetBgColourForChild(child); @@ -4050,9 +4064,24 @@ WXHBRUSH wxWindowMSW::MSWGetSolidBgBrushForChild(wxWindow *child) wxColour wxWindowMSW::MSWGetBgColourForChild(wxWindow *child) { - return m_inheritBgCol || (m_hasBgCol && child == this) - ? GetBackgroundColour() - : wxNullColour; + if ( m_hasBgCol ) + { + // our background colour applies to: + // 1. this window itself, always + // 2. all children unless the colour is "not inheritable" + // 3. immediate transparent children which should show the same + // background as we do, but not for transparent grandchildren + // which use the background of their immediate parent instead + if ( m_inheritBgCol || + child == this || + (child->HasTransparentBackground() && + child->GetParent() == this) ) + { + return GetBackgroundColour(); + } + } + + return wxNullColour; } WXHBRUSH wxWindowMSW::MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC) @@ -4296,16 +4325,13 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, event.m_leftDown = (flags & MK_LBUTTON) != 0; event.m_middleDown = (flags & MK_MBUTTON) != 0; event.m_rightDown = (flags & MK_RBUTTON) != 0; - // event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; - // Returns different negative values on WinME and WinNT, - // so simply test for negative value. event.m_altDown = ::GetKeyState(VK_MENU) < 0; #ifndef __WXWINCE__ event.SetTimestamp(::GetMessageTime()); #endif - event.m_eventObject = this; + event.SetEventObject(this); event.SetId(GetId()); #if wxUSE_MOUSEEVENT_HACK @@ -4417,7 +4443,6 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { // Generate an ENTER event m_mouseInWindow = true; -#if _WIN32_WINNT >= 0x0400 #ifndef __WXWINCE__ TRACKMOUSEEVENT trackinfo; @@ -4428,8 +4453,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) // appropriate TrackMouseEvent or emulate it ( win95 ) // else we need _WIN32_WINNT >= 0x0400 _TrackMouseEvent(&trackinfo); -#endif -#endif +#endif // __WXWINCE__ wxMouseEvent event(wxEVT_ENTER_WINDOW); InitMouseEvent(event, x, y, flags); @@ -4484,14 +4508,49 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) event.m_linesPerAction = s_linesPerRotation; return GetEventHandler()->ProcessEvent(event); -#else - (void) wParam; - (void) lParam; +#else // !wxUSE_MOUSEWHEEL + wxUnusedVar(wParam); + wxUnusedVar(lParam); return false; -#endif +#endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL } +void wxWindowMSW::GenerateMouseLeave() +{ + m_mouseInWindow = false; + + int state = 0; + if ( wxIsShiftDown() ) + state |= MK_SHIFT; + if ( wxIsCtrlDown() ) + state |= MK_CONTROL; + + // Only the high-order bit should be tested + if ( GetKeyState( VK_LBUTTON ) & (1<<15) ) + state |= MK_LBUTTON; + if ( GetKeyState( VK_MBUTTON ) & (1<<15) ) + state |= MK_MBUTTON; + if ( GetKeyState( VK_RBUTTON ) & (1<<15) ) + state |= MK_RBUTTON; + + POINT pt; + if ( !::GetCursorPos(&pt) ) + { + wxLogLastError(_T("GetCursorPos")); + } + + // we need to have client coordinates here for symmetry with + // wxEVT_ENTER_WINDOW + RECT rect = wxGetWindowRect(GetHwnd()); + pt.x -= rect.left; + pt.y -= rect.top; + + wxMouseEvent event(wxEVT_LEAVE_WINDOW); + InitMouseEvent(event, pt.x, pt.y, state); + + (void)GetEventHandler()->ProcessEvent(event); +} // --------------------------------------------------------------------------- // keyboard handling @@ -4510,7 +4569,7 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, event.m_controlDown = wxIsCtrlDown(); event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN; - event.m_eventObject = (wxWindow *)this; // const_cast + event.SetEventObject((wxWindow *)this); // const_cast event.m_keyCode = id; #if wxUSE_UNICODE event.m_uniChar = (wxChar) wParam; @@ -4813,32 +4872,32 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, wxScrollWinEvent event; event.SetPosition(pos); event.SetOrientation(orientation); - event.m_eventObject = this; + event.SetEventObject(this); switch ( wParam ) { case SB_TOP: - event.m_eventType = wxEVT_SCROLLWIN_TOP; + event.SetEventType(wxEVT_SCROLLWIN_TOP); break; case SB_BOTTOM: - event.m_eventType = wxEVT_SCROLLWIN_BOTTOM; + event.SetEventType(wxEVT_SCROLLWIN_BOTTOM); break; case SB_LINEUP: - event.m_eventType = wxEVT_SCROLLWIN_LINEUP; + event.SetEventType(wxEVT_SCROLLWIN_LINEUP); break; case SB_LINEDOWN: - event.m_eventType = wxEVT_SCROLLWIN_LINEDOWN; + event.SetEventType(wxEVT_SCROLLWIN_LINEDOWN); break; case SB_PAGEUP: - event.m_eventType = wxEVT_SCROLLWIN_PAGEUP; + event.SetEventType(wxEVT_SCROLLWIN_PAGEUP); break; case SB_PAGEDOWN: - event.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN; + event.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN); break; case SB_THUMBPOSITION: @@ -4864,9 +4923,9 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, event.SetPosition(scrollInfo.nTrackPos); } - event.m_eventType = wParam == SB_THUMBPOSITION + event.SetEventType( wParam == SB_THUMBPOSITION ? wxEVT_SCROLLWIN_THUMBRELEASE - : wxEVT_SCROLLWIN_THUMBTRACK; + : wxEVT_SCROLLWIN_THUMBTRACK ); break; default: @@ -5234,7 +5293,7 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) event.m_altDown = true; - event.m_eventObject = NULL; + event.SetEventObject(NULL); event.m_keyCode = id; event.m_shiftDown = wxIsShiftDown(); event.m_controlDown = wxIsCtrlDown();