]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Remove support for Gnome printing from wxGTK.
[wxWidgets.git] / src / msw / window.cpp
index eee4ca18ad676b821db3820fea3c8ac4704eb122..a08d1fa2ab3e6dd7e547e5e90b0dd42e126ac51a 100644 (file)
@@ -4,7 +4,6 @@
 // Author:      Julian Smart
 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
 // Created:     04/01/98
-// RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
@@ -60,6 +59,7 @@
 #include "wx/hashmap.h"
 #include "wx/evtloop.h"
 #include "wx/power.h"
+#include "wx/scopeguard.h"
 #include "wx/sysopt.h"
 
 #if wxUSE_DRAG_AND_DROP
@@ -81,6 +81,7 @@
 #include "wx/msw/private.h"
 #include "wx/msw/private/keyboard.h"
 #include "wx/msw/dcclient.h"
+#include "wx/private/textmeasure.h"
 
 #if wxUSE_TOOLTIPS
     #include "wx/tooltip.h"
     #include <windowsx.h>
 #endif
 
-#if !defined __WXWINCE__ && !defined NEED_PBT_H
-    #include <pbt.h>
-#endif
-
 #if defined(__WXWINCE__)
     #include "wx/msw/wince/missing.h"
 #ifdef __POCKETPC__
@@ -244,6 +241,9 @@ EraseBgHooks gs_eraseBgHooks;
 // needed.
 int gs_modalEntryWindowCount = 0;
 
+// Indicates whether we are currently processing WM_CAPTURECHANGED message.
+bool gs_insideCaptureChanged = false;
+
 } // anonymous namespace
 
 // ---------------------------------------------------------------------------
@@ -321,20 +321,23 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent)
 
 #endif // !__WXWINCE__
 
-#ifdef __WXWINCE__
-// On Windows CE, GetCursorPos can return an error, so use this function
-// instead
-bool GetCursorPosWinCE(POINT* pt)
+// GetCursorPos can return an error, so use this function
+// instead.
+// Error originally observed with WinCE, but later using Remote Desktop
+// to connect to XP.
+void wxGetCursorPosMSW(POINT* pt)
 {
     if (!GetCursorPos(pt))
     {
+#ifdef __WXWINCE__
+        wxLogLastError(wxT("GetCursorPos"));
+#endif
         DWORD pos = GetMessagePos();
-        pt->x = LOWORD(pos);
-        pt->y = HIWORD(pos);
+        // the coordinates may be negative in multi-monitor systems
+        pt->x = GET_X_LPARAM(pos);
+        pt->y = GET_Y_LPARAM(pos);
     }
-    return true;
 }
-#endif
 
 // ---------------------------------------------------------------------------
 // event tables
@@ -410,7 +413,7 @@ wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
 
         if ( !controlOnly
 #if wxUSE_CONTROLS
-                || parent->IsKindOf(CLASSINFO(wxControl))
+                || wxDynamicCast(parent, wxControl)
 #endif // wxUSE_CONTROLS
            )
         {
@@ -671,6 +674,7 @@ wxWindowMSW::MSWShowWithEffect(bool show,
                                wxShowEffect effect,
                                unsigned timeout)
 {
+#if wxUSE_DYNLIB_CLASS
     if ( effect == wxSHOW_EFFECT_NONE )
         return Show(show);
 
@@ -767,6 +771,9 @@ wxWindowMSW::MSWShowWithEffect(bool show,
     }
 
     return true;
+#else    // wxUSE_DYNLIB_CLASS
+    return Show(show);
+#endif
 }
 
 // Raise the window to the top of the Z order
@@ -801,6 +808,13 @@ void wxWindowMSW::DoReleaseMouse()
 
 /* static */ wxWindow *wxWindowBase::GetCapture()
 {
+    // When we receive WM_CAPTURECHANGED message, ::GetCapture() still returns
+    // the HWND that is losing the mouse capture. But as we must not release
+    // the capture for it (it's going to happen anyhow), pretend that there is
+    // no capture any more.
+    if ( gs_insideCaptureChanged )
+        return NULL;
+
     HWND hwnd = ::GetCapture();
     return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
 }
@@ -852,11 +866,7 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor)
             HWND hWnd = GetHwnd();
 
             POINT point;
-#ifdef __WXWINCE__
-            ::GetCursorPosWinCE(&point);
-#else
-            ::GetCursorPos(&point);
-#endif
+            ::wxGetCursorPosMSW(&point);
 
             RECT rect = wxGetWindowRect(hWnd);
 
@@ -875,13 +885,9 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor)
         // under the cursor and ask it to set its cursor itself as only it
         // knows what it is.
         POINT pt;
-        if ( !::GetCursorPos(&pt) )
-        {
-            wxLogLastError(wxT("GetCursorPos"));
-            return false;
-        }
+        wxGetCursorPosMSW(&pt);
 
-        const wxWindow* win = wxFindWindowAtPoint(wxPoint(pt.x, pt.y));
+        const wxWindowMSW* win = wxFindWindowAtPoint(wxPoint(pt.x, pt.y));
         if ( !win )
             win = this;
 
@@ -1194,6 +1200,11 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd)
     if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
     {
         wxSetWindowProc(hwnd, wxWndProc);
+
+        // If the window didn't use our window proc during its creation, the
+        // code in HandleCreate() hasn't been executed, so do it here.
+        if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
+            EnsureParentHasControlParentStyle(GetParent());
     }
     else
     {
@@ -1434,7 +1445,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
     // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
     // don't support overlapping windows and it only makes sense for them and,
     // presumably, gives the system some extra work (to manage more clipping
-    // regions), so avoid it alltogether
+    // regions), so avoid it altogether
 
 
     if ( flags & wxVSCROLL )
@@ -1517,11 +1528,7 @@ bool wxWindowMSW::IsMouseInWindow() const
 {
     // get the mouse position
     POINT pt;
-#ifdef __WXWINCE__
-    ::GetCursorPosWinCE(&pt);
-#else
-    ::GetCursorPos(&pt);
-#endif
+    wxGetCursorPosMSW(&pt);
 
     // find the window which currently has the cursor and go up the window
     // chain until we find this window - or exhaust it
@@ -2173,31 +2180,18 @@ void wxWindowMSW::DoGetTextExtent(const wxString& string,
                                   int *externalLeading,
                                   const wxFont *fontToUse) const
 {
-    wxASSERT_MSG( !fontToUse || fontToUse->IsOk(),
-                    wxT("invalid font in GetTextExtent()") );
-
-    HFONT hfontToUse;
-    if ( fontToUse )
-        hfontToUse = GetHfontOf(*fontToUse);
+    // ensure we work with a valid font
+    wxFont font;
+    if ( !fontToUse || !fontToUse->IsOk() )
+        font = GetFont();
     else
-        hfontToUse = GetHfontOf(GetFont());
-
-    WindowHDC hdc(GetHwnd());
-    SelectInHDC selectFont(hdc, hfontToUse);
+        font = *fontToUse;
 
-    SIZE sizeRect;
-    TEXTMETRIC tm;
-    ::GetTextExtentPoint32(hdc, string.wx_str(), string.length(), &sizeRect);
-    GetTextMetrics(hdc, &tm);
+    wxCHECK_RET( font.IsOk(), wxT("invalid font in GetTextExtent()") );
 
-    if ( x )
-        *x = sizeRect.cx;
-    if ( y )
-        *y = sizeRect.cy;
-    if ( descent )
-        *descent = tm.tmDescent;
-    if ( externalLeading )
-        *externalLeading = tm.tmExternalLeading;
+    const wxWindow* win = static_cast<const wxWindow*>(this);
+    wxTextMeasure txm(win, &font);
+    txm.GetTextExtent(string, x, y, descent, externalLeading);
 }
 
 // ---------------------------------------------------------------------------
@@ -2309,7 +2303,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
 {
     // wxUniversal implements tab traversal itself
 #ifndef __WXUNIVERSAL__
-    if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
+    // Notice that we check for WS_EX_CONTROLPARENT and not wxTAB_TRAVERSAL
+    // here. While usually they are both set or both unset, doing it like this
+    // also works if there is ever a bug that results in wxTAB_TRAVERSAL being
+    // set but not WS_EX_CONTROLPARENT as we must not call IsDialogMessage() in
+    // this case, it would simply hang (see #15458).
+    if ( m_hWnd != 0 && (wxGetWindowExStyle(this) & WS_EX_CONTROLPARENT) )
     {
         // intercept dialog navigation keys
         MSG *msg = (MSG *)pMsg;
@@ -2728,7 +2727,11 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w
     return rc;
 }
 
-WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+bool
+wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
+                              WXUINT message,
+                              WXWPARAM wParam,
+                              WXLPARAM lParam)
 {
     // did we process the message?
     bool processed = false;
@@ -2907,9 +2910,13 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 
 #if wxUSE_MOUSEWHEEL
         case WM_MOUSEWHEEL:
-            processed = HandleMouseWheel(wParam, lParam);
+            processed = HandleMouseWheel(wxMOUSE_WHEEL_VERTICAL, wParam, lParam);
             break;
-#endif
+
+        case WM_MOUSEHWHEEL:
+            processed = HandleMouseWheel(wxMOUSE_WHEEL_HORIZONTAL, wParam, lParam);
+            break;
+#endif // wxUSE_MOUSEWHEEL
 
         case WM_LBUTTONDOWN:
         case WM_LBUTTONUP:
@@ -3032,8 +3039,8 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
         case MM_JOY1BUTTONUP:
         case MM_JOY2BUTTONUP:
             processed = HandleJoystickEvent(message,
-                                            GET_X_LPARAM(lParam),
-                                            GET_Y_LPARAM(lParam),
+                                            LOWORD(lParam),
+                                            HIWORD(lParam),
                                             wParam);
             break;
 #endif // __WXMICROWIN__
@@ -3158,6 +3165,7 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                     case VK_OEM_5:
                     case VK_OEM_6:
                     case VK_OEM_7:
+                    case VK_OEM_102:
                     case VK_OEM_PLUS:
                     case VK_OEM_COMMA:
                     case VK_OEM_MINUS:
@@ -3445,26 +3453,31 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 #if !defined(__WXWINCE__)
         case WM_CONTEXTMENU:
             {
-                // we don't convert from screen to client coordinates as
-                // the event may be handled by a parent window
-                wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
-
-                wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
-
-                // we could have got an event from our child, reflect it back
-                // to it if this is the case
-                wxWindowMSW *win = NULL;
+                // Ignore the events that are propagated from a child window by
+                // DefWindowProc(): as wxContextMenuEvent is already propagated
+                // upwards the window hierarchy by us, not doing this would
+                // result in duplicate events being sent.
                 WXHWND hWnd = (WXHWND)wParam;
                 if ( hWnd != m_hWnd )
                 {
-                    win = FindItemByHWND(hWnd);
+                    wxWindowMSW *win = FindItemByHWND(hWnd);
+                    if ( win && IsDescendant(win) )
+                    {
+                        // We had already generated wxContextMenuEvent when we
+                        // got WM_CONTEXTMENU for that window.
+                        processed = true;
+                        break;
+                    }
                 }
 
-                if ( !win )
-                    win = this;
+                // we don't convert from screen to client coordinates as
+                // the event may be handled by a parent window
+                wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+                wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
+                evtCtx.SetEventObject(this);
 
-                evtCtx.SetEventObject(win);
-                processed = win->HandleWindowEvent(evtCtx);
+                processed = HandleWindowEvent(evtCtx);
             }
             break;
 #endif
@@ -3608,15 +3621,26 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
     }
 
     if ( !processed )
+        return false;
+
+    *result = rc.result;
+
+    return true;
+}
+
+WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+{
+    WXLRESULT result;
+    if ( !MSWHandleMessage(&result, message, wParam, lParam) )
     {
 #if wxDEBUG_LEVEL >= 2
         wxLogTrace("winmsg", wxT("Forwarding %s to DefWindowProc."),
                    wxGetMessageName(message));
 #endif // wxDEBUG_LEVEL >= 2
-        rc.result = MSWDefWindowProc(message, wParam, lParam);
+        result = MSWDefWindowProc(message, wParam, lParam);
     }
 
-    return rc.result;
+    return result;
 }
 
 // ----------------------------------------------------------------------------
@@ -3754,8 +3778,8 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     m_hWnd = (WXHWND)::CreateWindowEx
                        (
                         extendedStyle,
-                        className.wx_str(),
-                        title ? title : m_windowName.wx_str(),
+                        className.t_str(),
+                        title ? title : m_windowName.t_str(),
                         style,
                         x, y, w, h,
                         (HWND)MSWGetParent(),
@@ -3875,7 +3899,7 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
                     (
                         CP_ACP,
                         0,                      // no flags
-                        ttip.wx_str(),
+                        ttip.t_str(),
                         tipLength,
                         buf,
                         WXSIZEOF(buf) - 1
@@ -4189,14 +4213,7 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
         // first ask the user code - it may wish to set the cursor in some very
         // specific way (for example, depending on the current position)
         POINT pt;
-#ifdef __WXWINCE__
-        if ( !::GetCursorPosWinCE(&pt))
-#else
-        if ( !::GetCursorPos(&pt) )
-#endif
-        {
-            wxLogLastError(wxT("GetCursorPos"));
-        }
+        wxGetCursorPosMSW(&pt);
 
         int x = pt.x,
             y = pt.y;
@@ -4548,6 +4565,12 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
 
 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
 {
+    // Ensure that wxWindow::GetCapture() returns NULL if called from the event
+    // handlers invoked below. This is necessary to avoid wrongly calling
+    // ReleaseMouse() when we're already losing the mouse capture anyhow.
+    gs_insideCaptureChanged = true;
+    wxON_BLOCK_EXIT_SET(gs_insideCaptureChanged, false);
+
     // notify windows on the capture stack about lost capture
     // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
     wxWindowBase::NotifyCaptureLost();
@@ -4824,6 +4847,8 @@ bool wxWindowMSW::HandlePaint()
     // be called from inside the event handlers called above)
     m_updateRegion.Clear();
 
+    wxPaintDCImpl::EndPaint((wxWindow *)this);
+
     return processed;
 }
 
@@ -4843,6 +4868,16 @@ void wxWindowMSW::OnPaint(wxPaintEvent& event)
 
 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
 {
+    if ( IsBeingDeleted() )
+    {
+        // We can get WM_ERASEBKGND after starting the destruction of our top
+        // level parent. Handling it in this case is unnecessary and can be
+        // actually harmful as e.g. wxStaticBox::GetClientSize() doesn't work
+        // without a valid TLW parent (because it uses dialog units internally
+        // which use the dialog font), so just don't do anything then.
+        return false;
+    }
+
     switch ( GetBackgroundStyle() )
     {
         case wxBG_STYLE_ERASE:
@@ -4955,7 +4990,11 @@ wxWindowMSW::MSWGetBgBrushForChild(WXHDC hDC, wxWindowMSW *child)
 
         ::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1);
 
-        if ( !::SetBrushOrgEx((HDC)hDC, -rc.left, -rc.top, NULL) )
+        int x = rc.left,
+            y = rc.top;
+        MSWAdjustBrushOrg(&x, &y);
+
+        if ( !::SetBrushOrgEx((HDC)hDC, -x, -y, NULL) )
         {
             wxLogLastError(wxT("SetBrushOrgEx(bg brush)"));
         }
@@ -5095,11 +5134,9 @@ bool wxWindowMSW::HandleExitSizeMove()
     return HandleWindowEvent(event);
 }
 
-bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
+bool wxWindowMSW::BeginRepositioningChildren()
 {
 #if wxUSE_DEFERRED_SIZING
-    // when we resize this window, its children are probably going to be
-    // repositioned as well, prepare to use DeferWindowPos() for them
     int numChildren = 0;
     for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
           child;
@@ -5108,23 +5145,60 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
         numChildren ++;
     }
 
+    // Nothing is gained by deferring the repositioning of a single child.
+    if ( numChildren < 2 )
+        return false;
+
     // Protect against valid m_hDWP being overwritten
-    bool useDefer = false;
+    if ( m_hDWP )
+        return false;
 
-    if ( numChildren > 1 )
+    m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+    if ( !m_hDWP )
     {
-        if (!m_hDWP)
-        {
-            m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
-            if ( !m_hDWP )
-            {
-                wxLogLastError(wxT("BeginDeferWindowPos"));
-            }
-            if (m_hDWP)
-                useDefer = true;
-        }
+        wxLogLastError(wxT("BeginDeferWindowPos"));
+        return false;
+    }
+
+    // Return true to indicate that EndDeferWindowPos() should be called.
+    return true;
+#endif // wxUSE_DEFERRED_SIZING
+}
+
+void wxWindowMSW::EndRepositioningChildren()
+{
+#if wxUSE_DEFERRED_SIZING
+    wxASSERT_MSG( m_hDWP, wxS("Shouldn't be called") );
+
+    // reset m_hDWP to NULL so that child windows don't try to use our
+    // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
+    // happen anyhow normally but who knows what weird flow of control we
+    // may have depending on what the users EVT_SIZE handler does...)
+    HDWP hDWP = (HDWP)m_hDWP;
+    m_hDWP = NULL;
+
+    // do put all child controls in place at once
+    if ( !::EndDeferWindowPos(hDWP) )
+    {
+        wxLogLastError(wxT("EndDeferWindowPos"));
+    }
+
+    // Reset our children's pending pos/size values.
+    for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxWindowMSW * const child = node->GetData();
+        child->MSWEndDeferWindowPos();
     }
 #endif // wxUSE_DEFERRED_SIZING
+}
+
+bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
+{
+    // when we resize this window, its children are probably going to be
+    // repositioned as well, prepare to use DeferWindowPos() for them
+    ChildrenRepositioningGuard repositionGuard(this);
 
     // update this window size
     bool processed = false;
@@ -5157,34 +5231,6 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
             processed = HandleWindowEvent(event);
     }
 
-#if wxUSE_DEFERRED_SIZING
-    // and finally change the positions of all child windows at once
-    if ( useDefer && m_hDWP )
-    {
-        // reset m_hDWP to NULL so that child windows don't try to use our
-        // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
-        // happen anyhow normally but who knows what weird flow of control we
-        // may have depending on what the users EVT_SIZE handler does...)
-        HDWP hDWP = (HDWP)m_hDWP;
-        m_hDWP = NULL;
-
-        // do put all child controls in place at once
-        if ( !::EndDeferWindowPos(hDWP) )
-        {
-            wxLogLastError(wxT("EndDeferWindowPos"));
-        }
-
-        // Reset our children's pending pos/size values.
-        for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
-              node;
-              node = node->GetNext() )
-        {
-            wxWindowMSW * const child = node->GetData();
-            child->MSWEndDeferWindowPos();
-        }
-    }
-#endif // wxUSE_DEFERRED_SIZING
-
     return processed;
 }
 
@@ -5283,10 +5329,10 @@ bool wxWindowMSW::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
     // the messages sent from the in-place edit control used by the treectrl
     // for label editing have id == 0, but they should _not_ be treated as menu
     // messages (they are EN_XXX ones, in fact) so don't translate anything
-    // coming from a control to wxEVT_COMMAND_MENU_SELECTED
+    // coming from a control to wxEVT_MENU
     if ( !control )
     {
-        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
+        wxCommandEvent event(wxEVT_MENU, id);
         event.SetEventObject(this);
         event.SetInt(id);
 
@@ -5447,7 +5493,7 @@ bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
     };
 
 #ifdef wxHAS_XBUTTON
-    // the same messages are used for both auxillary mouse buttons so we need
+    // the same messages are used for both auxiliary mouse buttons so we need
     // to adjust the index manually
     switch ( msg )
     {
@@ -5555,7 +5601,9 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
 }
 
 
-bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
+bool
+wxWindowMSW::HandleMouseWheel(wxMouseWheelAxis axis,
+                              WXWPARAM wParam, WXLPARAM lParam)
 {
 #if wxUSE_MOUSEWHEEL
     // notice that WM_MOUSEWHEEL position is in screen coords (as it's
@@ -5568,6 +5616,7 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
     InitMouseEvent(event, pt.x, pt.y, LOWORD(wParam));
     event.m_wheelRotation = (short)HIWORD(wParam);
     event.m_wheelDelta = WHEEL_DELTA;
+    event.m_wheelAxis = axis;
 
     static int s_linesPerRotation = -1;
     if ( s_linesPerRotation == -1 )
@@ -5583,7 +5632,20 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
         }
     }
 
+    static int s_columnsPerRotation = -1;
+    if ( s_columnsPerRotation == -1 )
+    {
+        if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
+                                     &s_columnsPerRotation, 0))
+        {
+            // this setting is not supported on Windows 2000/XP, so use the value of 1
+            // http://msdn.microsoft.com/en-us/library/ms997498.aspx
+            s_columnsPerRotation = 1;
+        }
+    }
+
     event.m_linesPerAction = s_linesPerRotation;
+    event.m_columnsPerAction = s_columnsPerRotation;
     return HandleWindowEvent(event);
 
 #else // !wxUSE_MOUSEWHEEL
@@ -5613,14 +5675,7 @@ void wxWindowMSW::GenerateMouseLeave()
         state |= MK_RBUTTON;
 
     POINT pt;
-#ifdef __WXWINCE__
-    if ( !::GetCursorPosWinCE(&pt) )
-#else
-    if ( !::GetCursorPos(&pt) )
-#endif
-    {
-        wxLogLastError(wxT("GetCursorPos"));
-    }
+    wxGetCursorPosMSW(&pt);
 
     // we need to have client coordinates here for symmetry with
     // wxEVT_ENTER_WINDOW
@@ -5672,21 +5727,6 @@ MSWInitAnyKeyEvent(wxKeyEvent& event,
 #ifndef __WXWINCE__
     event.SetTimestamp(::GetMessageTime());
 #endif
-
-    // Event coordinates must be in window client coordinates system which
-    // doesn't make sense if there is no window.
-    //
-    // We could use screen coordinates for such events but this would make the
-    // logic of the event handlers more complicated: you'd need to test for the
-    // event object and interpret the coordinates differently according to
-    // whether it's NULL or not so unless somebody really asks for this let's
-    // just avoid the issue.
-    if ( win )
-    {
-        const wxPoint mousePos = win->ScreenToClient(wxGetMousePosition());
-        event.m_x = mousePos.x;
-        event.m_y = mousePos.y;
-    }
 }
 
 } // anonymous namespace
@@ -5805,9 +5845,7 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
 #ifndef __WXWINCE__
     const HMENU hmenu = (HMENU)lParam;
 
-    MENUITEMINFO mii;
-    wxZeroMemory(mii);
-    mii.cbSize = sizeof(MENUITEMINFO);
+    WinStruct<MENUITEMINFO> mii;
 
     // we could use MIIM_FTYPE here as we only need to know if the item is
     // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but
@@ -5832,7 +5870,7 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
                 wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
 
                 const wxString label(item->GetItemLabel());
-                const wxChar *p = wxStrchr(label.wx_str(), wxT('&'));
+                const wxChar *p = wxStrchr(label.t_str(), wxT('&'));
                 while ( p++ )
                 {
                     if ( *p == wxT('&') )
@@ -5872,9 +5910,9 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
 
 bool wxWindowMSW::HandleClipboardEvent(WXUINT nMsg)
 {
-    const wxEventType type = nMsg == WM_CUT       ? wxEVT_COMMAND_TEXT_CUT
-                           : nMsg == WM_COPY      ? wxEVT_COMMAND_TEXT_COPY
-                           : /* nMsg == WM_PASTE */ wxEVT_COMMAND_TEXT_PASTE;
+    const wxEventType type = nMsg == WM_CUT       ? wxEVT_TEXT_CUT
+                           : nMsg == WM_COPY      ? wxEVT_TEXT_COPY
+                           : /* nMsg == WM_PASTE */ wxEVT_TEXT_PASTE;
     wxClipboardTextEvent evt(type, GetId());
 
     evt.SetEventObject(this);
@@ -5961,7 +5999,10 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
     }
 
     wxJoystickEvent event(eventType, buttons, joystick, change);
-    event.SetPosition(wxPoint(x, y));
+    if ( eventType == wxEVT_JOY_ZMOVE )
+        event.SetZPosition(x);
+    else
+        event.SetPosition(wxPoint(x, y));
     event.SetEventObject(this);
 
     return HandleWindowEvent(event);
@@ -6246,6 +6287,7 @@ int VKToWX(WXWORD vk, WXLPARAM lParam, wchar_t *uc)
         case VK_OEM_5:
         case VK_OEM_6:
         case VK_OEM_7:
+        case VK_OEM_102:
             // MapVirtualKey() returns 0 if it fails to convert the virtual
             // key which nicely corresponds to our WXK_NONE.
             wxk = ::MapVirtualKey(vk, MAPVK_VK_TO_CHAR);
@@ -6318,12 +6360,18 @@ int VKToWX(WXWORD vk, WXLPARAM lParam, wchar_t *uc)
 
         case VK_DELETE:
             wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
+
+            if ( uc )
+                *uc = WXK_DELETE;
             break;
 
         case VK_RETURN:
             // don't use ChooseNormalOrExtended() here as the keys are reversed
             // here: numpad enter is the extended one
             wxk = HIWORD(lParam) & KF_EXTENDED ? WXK_NUMPAD_ENTER : WXK_RETURN;
+
+            if ( uc )
+                *uc = WXK_RETURN;
             break;
 
         default:
@@ -6506,7 +6554,7 @@ wxMouseState wxGetMouseState()
 {
     wxMouseState ms;
     POINT pt;
-    GetCursorPos( &pt );
+    wxGetCursorPosMSW(&pt);
 
     ms.SetX(pt.x);
     ms.SetY(pt.y);
@@ -6609,7 +6657,7 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
     DWORD hiWord = HIWORD(lParam);
     if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
     {
-        wchar_t uc;
+        wchar_t uc = 0;
         int id = wxMSWKeyboard::VKToWX(wParam, lParam, &uc);
 
         // Don't intercept keyboard entry (notably Escape) if a modal window
@@ -6629,7 +6677,14 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
 #endif // wxUSE_UNICODE
                     )
             {
-                const wxWindow * const win = wxGetActiveWindow();
+                wxWindow const* win = wxWindow::DoFindFocus();
+                if ( !win )
+                {
+                    // Even if the focus got lost somehow, still send the event
+                    // to the top level parent to allow a wxDialog to always
+                    // close on Escape.
+                    win = wxGetActiveWindow();
+                }
 
                 wxKeyEvent event(wxEVT_CHAR_HOOK);
                 MSWInitAnyKeyEvent(event, wParam, lParam, win);
@@ -6644,8 +6699,11 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
 
                 if ( handler && handler->ProcessEvent(event) )
                 {
-                    // processed
-                    return 1;
+                    if ( !event.IsNextEventAllowed() )
+                    {
+                        // Stop processing of this event.
+                        return 1;
+                    }
                 }
             }
         }
@@ -7201,6 +7259,26 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
     pt2.y = pt.y;
 
     HWND hWnd = ::WindowFromPoint(pt2);
+    if ( hWnd )
+    {
+        // WindowFromPoint() ignores the disabled children but we're supposed
+        // to take them into account, so check if we have a child at this
+        // coordinate using ChildWindowFromPointEx().
+        for ( ;; )
+        {
+            pt2.x = pt.x;
+            pt2.y = pt.y;
+            ::ScreenToClient(hWnd, &pt2);
+            HWND child = ::ChildWindowFromPointEx(hWnd, pt2, CWP_SKIPINVISIBLE);
+            if ( child == hWnd || !child )
+                break;
+
+            // ChildWindowFromPointEx() only examines the immediate children
+            // but we want to get the deepest (top in Z-order) one, so continue
+            // iterating for as long as it finds anything.
+            hWnd = child;
+        }
+    }
 
     return wxGetWindowFromHWND((WXHWND)hWnd);
 }
@@ -7209,11 +7287,7 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
 wxPoint wxGetMousePosition()
 {
     POINT pt;
-#ifdef __WXWINCE__
-    GetCursorPosWinCE(&pt);
-#else
-    GetCursorPos( & pt );
-#endif
+    wxGetCursorPosMSW(&pt);
 
     return wxPoint(pt.x, pt.y);
 }
@@ -7283,8 +7357,6 @@ bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
     return true;
 }
 
-#if wxUSE_ACCEL
-
 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
 {
     int win_modifiers = LOWORD(lParam);
@@ -7299,8 +7371,6 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
     return HandleWindowEvent(event);
 }
 
-#endif // wxUSE_ACCEL
-
 #endif // wxUSE_HOTKEY
 
 // Not tested under WinCE
@@ -7371,7 +7441,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule, wxModule)
 #if wxUSE_STATBOX
 static void wxAdjustZOrder(wxWindow* parent)
 {
-    if (parent->IsKindOf(CLASSINFO(wxStaticBox)))
+    if (wxDynamicCast(parent, wxStaticBox))
     {
         // Set the z-order correctly
         SetWindowPos((HWND) parent->GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);