]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
let wxFRAME_EX_CONTEXTHELP override wxM{IN|AX}IMIZE_BOX as the latter are included...
[wxWidgets.git] / src / msw / window.cpp
index d424c7e0f182c52eae4a80401758c3c049cf9cb8..4dcdf623f0e0278dbcb4fafabaa658a446948c92 100644 (file)
     #pragma hdrstop
 #endif
 
+#include "wx/window.h"
+
 #ifndef WX_PRECOMP
     #include "wx/msw/wrapwin.h"
-    #include "wx/window.h"
     #include "wx/accel.h"
-    #include "wx/setup.h"
     #include "wx/menu.h"
     #include "wx/dc.h"
     #include "wx/dcclient.h"
@@ -44,6 +44,9 @@
     #include "wx/settings.h"
     #include "wx/statbox.h"
     #include "wx/sizer.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/textctrl.h"
 #endif
 
 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
@@ -52,6 +55,7 @@
 
 #include "wx/evtloop.h"
 #include "wx/module.h"
+#include "wx/power.h"
 #include "wx/sysopt.h"
 
 #if wxUSE_DRAG_AND_DROP
@@ -71,7 +75,6 @@
 #endif
 
 #include "wx/menuitem.h"
-#include "wx/log.h"
 
 #include "wx/msw/private.h"
 
     #include "wx/spinctrl.h"
 #endif // wxUSE_SPINCTRL
 
-#include "wx/intl.h"
-#include "wx/log.h"
-
-#include "wx/textctrl.h"
 #include "wx/notebook.h"
 #include "wx/listctrl.h"
 
     #include <windowsx.h>
 #endif
 
-#include <commctrl.h>
+// include <commctrl.h> "properly"
+#include "wx/msw/wrapcctl.h"
+
+#ifndef __WXWINCE__
+    #include <pbt.h>
+#endif
 
 #include "wx/msw/missing.h"
 
 #if defined(__WXWINCE__)
     #include "wx/msw/wince/missing.h"
+#ifdef __POCKETPC__
+    #include <windows.h>
+    #include <shellapi.h>
+    #include <ole2.h>
+    #include <aygshell.h>
+#endif
 #endif
 
 #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE)
 // resizing complicated window hierarchies, but this can in theory result in
 // different behaviour than the old code so we keep the possibility to use it
 // by setting this to 0 (in the future this should be removed completely)
+#ifdef __WXWINCE__
+#define USE_DEFERRED_SIZING 0
+#else
 #define USE_DEFERRED_SIZING 1
+#endif
 
 // set this to 1 to filter out duplicate mouse events, e.g. mouse move events
 // when mouse position didnd't change
@@ -484,6 +498,10 @@ void wxWindowMSW::Init()
 
     m_pendingPosition = wxDefaultPosition;
     m_pendingSize = wxDefaultSize;
+
+#ifdef __POCKETPC__
+    m_contextMenuEnabled = false;
+#endif
 }
 
 // Destructor
@@ -785,22 +803,10 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor)
         return false;
     }
 
-    if ( m_cursor.Ok() )
+    // don't "overwrite" busy cursor
+    if ( m_cursor.Ok() && !wxIsBusy() )
     {
-        HWND hWnd = GetHwnd();
-
-        // Change the cursor NOW if we're within the correct window
-        POINT point;
-#ifdef __WXWINCE__
-        ::GetCursorPosWinCE(&point);
-#else
-        ::GetCursorPos(&point);
-#endif
-
-        RECT rect = wxGetWindowRect(hWnd);
-
-        if ( ::PtInRect(&rect, point) && !wxIsBusy() )
-            ::SetCursor(GetHcursorOf(m_cursor));
+        ::SetCursor(GetHcursorOf(m_cursor));
     }
 
     return true;
@@ -941,7 +947,7 @@ void wxWindowMSW::SetScrollbar(int orient,
         // We have to set the variables here to make them valid in events
         // triggered by ::SetScrollInfo()
         *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
-        
+
         ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
                         &info, refresh);
     }
@@ -1042,6 +1048,10 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd)
         // simply check m_oldWndProc
         m_oldWndProc = NULL;
     }
+
+    // we're officially created now, send the event
+    wxWindowCreateEvent event((wxWindow *)this);
+    (void)GetEventHandler()->ProcessEvent(event);
 }
 
 void wxWindowMSW::UnsubclassWin()
@@ -1090,20 +1100,19 @@ void wxWindowMSW::DissociateHandle()
 
 
 bool wxCheckWindowWndProc(WXHWND hWnd,
-                          WXFARPROC WXUNUSED_IN_WINCE(wndProc))
+                          WXFARPROC WXUNUSED(wndProc))
 {
-    // Unicows note: the code below works, but only because WNDCLASS contains
-    // original window handler rather that the unicows fake one. This may not
-    // be on purpose, though; if it stops working with future versions of
-    // unicows.dll, we can override unicows hooks by setting
-    // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
-    // versions that keep track of fake<->real wnd proc mapping.
+// TODO: This list of window class names should be factored out so they can be
+// managed in one place and then accessed from here and other places, such as
+// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
 
-    // On WinCE (at least), the wndproc comparison doesn't work,
-    // so have to use something like this.
 #ifdef __WXWINCE__
     extern       wxChar *wxCanvasClassName;
     extern       wxChar *wxCanvasClassNameNR;
+#else
+    extern const wxChar *wxCanvasClassName;
+    extern const wxChar *wxCanvasClassNameNR;
+#endif
     extern const wxChar *wxMDIFrameClassName;
     extern const wxChar *wxMDIFrameClassNameNoRedraw;
     extern const wxChar *wxMDIChildFrameClassName;
@@ -1111,25 +1120,18 @@ bool wxCheckWindowWndProc(WXHWND hWnd,
     wxString str(wxGetWindowClass(hWnd));
     if (str == wxCanvasClassName ||
         str == wxCanvasClassNameNR ||
+#if wxUSE_GLCANVAS
+        str == _T("wxGLCanvasClass") ||
+        str == _T("wxGLCanvasClassNR") ||
+#endif // wxUSE_GLCANVAS
         str == wxMDIFrameClassName ||
         str == wxMDIFrameClassNameNoRedraw ||
         str == wxMDIChildFrameClassName ||
         str == wxMDIChildFrameClassNameNoRedraw ||
         str == _T("wxTLWHiddenParent"))
         return true; // Effectively means don't subclass
-
-    return false;
-#else
-    WNDCLASS cls;
-    if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
-    {
-        wxLogLastError(_T("GetClassInfo"));
-
+    else
         return false;
-    }
-
-    return wndProc == (WXFARPROC)cls.lpfnWndProc;
-#endif
 }
 
 // ----------------------------------------------------------------------------
@@ -1145,14 +1147,48 @@ void wxWindowMSW::SetWindowStyleFlag(long flags)
     // update the internal variable
     wxWindowBase::SetWindowStyleFlag(flags);
 
+    // and the real window flags
+    MSWUpdateStyle(flagsOld, GetExtraStyle());
+}
+
+void wxWindowMSW::SetExtraStyle(long exflags)
+{
+    long exflagsOld = GetExtraStyle();
+    if ( exflags == exflagsOld )
+        return;
+
+    // update the internal variable
+    wxWindowBase::SetExtraStyle(exflags);
+
+    // and the real window flags
+    MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld);
+}
+
+void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
+{
     // now update the Windows style as well if needed - and if the window had
     // been already created
     if ( !GetHwnd() )
         return;
 
-    WXDWORD exstyle, exstyleOld;
-    long style = MSWGetStyle(flags, &exstyle),
-         styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+    // we may need to call SetWindowPos() when we change some styles
+    bool callSWP = false;
+
+    WXDWORD exstyle;
+    long style = MSWGetStyle(GetWindowStyleFlag(), &exstyle);
+
+    // this is quite a horrible hack but we need it because MSWGetStyle()
+    // doesn't take exflags as parameter but uses GetExtraStyle() internally
+    // and so we have to modify the window exflags temporarily to get the
+    // correct exstyleOld
+    long exflagsNew = GetExtraStyle();
+    wxWindowBase::SetExtraStyle(exflagsOld);
+
+    WXDWORD exstyleOld;
+    long styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+
+    wxWindowBase::SetExtraStyle(exflagsNew);
+
 
     if ( style != styleOld )
     {
@@ -1165,17 +1201,34 @@ void wxWindowMSW::SetWindowStyleFlag(long flags)
         styleReal |= style;
 
         ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
+
+        // we need to call SetWindowPos() if any of the styles affecting the
+        // frame appearance have changed
+        callSWP = ((styleOld ^ style ) & (WS_BORDER |
+                                      WS_THICKFRAME |
+                                      WS_CAPTION |
+                                      WS_DLGFRAME |
+                                      WS_MAXIMIZEBOX |
+                                      WS_MINIMIZEBOX |
+                                      WS_SYSMENU) ) != 0;
     }
 
     // and the extended style
+    long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+
     if ( exstyle != exstyleOld )
     {
-        long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
         exstyleReal &= ~exstyleOld;
         exstyleReal |= exstyle;
 
         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
 
+        // ex style changes don't take effect without calling SetWindowPos
+        callSWP = true;
+    }
+
+    if ( callSWP )
+    {
         // we must call SetWindowPos() to flush the cached extended style and
         // also to make the change to wxSTAY_ON_TOP style take effect: just
         // setting the style simply doesn't work
@@ -1183,7 +1236,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags)
                              exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
                                                          : HWND_NOTOPMOST,
                              0, 0, 0, 0,
-                             SWP_NOMOVE | SWP_NOSIZE) )
+                             SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) )
         {
             wxLogLastError(_T("SetWindowPos"));
         }
@@ -1364,7 +1417,7 @@ void wxWindowMSW::Thaw()
 {
     wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
 
-    if ( !--m_frozenness )
+    if ( --m_frozenness == 0 )
     {
         if ( IsShown() )
         {
@@ -1429,6 +1482,26 @@ void wxWindowMSW::Update()
 // drag and drop
 // ---------------------------------------------------------------------------
 
+// we need to lower the sibling static boxes so controls contained within can be
+// a drop target
+static inline void AdjustStaticBoxZOrder(wxWindow *parent)
+{
+    // no sibling static boxes if we have no parent (ie TLW)
+    if ( !parent )
+        return;
+
+    for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxStaticBox *statbox = wxDynamicCast(node->GetData(), wxStaticBox);
+        if ( statbox )
+        {
+            ::SetWindowPos(GetHwndOf(statbox), HWND_BOTTOM, 0, 0, 0, 0,
+                           SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+        }
+    }
+}
 
 #if wxUSE_DRAG_AND_DROP
 void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
@@ -1440,7 +1513,10 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
 
     m_dropTarget = pDropTarget;
     if ( m_dropTarget != 0 )
+    {
+        AdjustStaticBoxZOrder(GetParent());
         m_dropTarget->Register(m_hWnd);
+    }
 }
 #endif // wxUSE_DRAG_AND_DROP
 
@@ -1451,7 +1527,10 @@ void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
 #ifndef __WXWINCE__
     HWND hWnd = GetHwnd();
     if ( hWnd )
+    {
+        AdjustStaticBoxZOrder(GetParent());
         ::DragAcceptFiles(hWnd, (BOOL)accept);
+    }
 #endif
 }
 
@@ -1513,9 +1592,10 @@ void wxWindowMSW::DoGetSize(int *x, int *y) const
 // Get size *available for subwindows* i.e. excluding menu bar etc.
 void wxWindowMSW::DoGetClientSize(int *x, int *y) const
 {
+#if USE_DEFERRED_SIZING
     if ( IsTopLevel() || m_pendingSize == wxDefaultSize )
-    {
-        // top level windows resizing is never deferred, so we can safely use
+#endif
+    {        // top level windows resizing is never deferred, so we can safely use
         // the current size here
         RECT rect = wxGetClientRect(GetHwnd());
 
@@ -1524,13 +1604,24 @@ void wxWindowMSW::DoGetClientSize(int *x, int *y) const
         if ( y )
             *y = rect.bottom;
     }
-    else // non top level
+#if USE_DEFERRED_SIZING
+    else // non top level and using deferred sizing
     {
-        // size is the same as client size for non top level windows, so
-        // forward to GetSize() to take into account deferred sizing (which
-        // wxGetClientRect() doesn't)
-        DoGetSize(x, y);
+        // we need to calculate the *pending* client size here
+        RECT rect;
+        rect.left = m_pendingPosition.x;
+        rect.top = m_pendingPosition.y;
+        rect.right = rect.left + m_pendingSize.x;
+        rect.bottom = rect.top + m_pendingSize.y;
+
+        ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
+
+        if ( x )
+            *x = rect.right - rect.left;
+        if ( y )
+            *y = rect.bottom - rect.top;
     }
+#endif
 }
 
 void wxWindowMSW::DoGetPosition(int *x, int *y) const
@@ -1749,9 +1840,10 @@ void wxWindowMSW::DoSetClientSize(int width, int height)
 {
     // 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
-    // changes - so we keep changing it until we get it right
+    // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
+    // doesn't take neither into account) and so the client size will not be
+    // correct as the difference between the total and client size changes --
+    // so we keep changing it until we get it right
     //
     // normally this loop shouldn't take more than 3 iterations (usually 1 but
     // if scrollbars [dis]appear as the result of the first call, then 2 and it
@@ -1792,7 +1884,9 @@ void wxWindowMSW::DoSetClientSize(int width, int height)
         }
 
         // don't call DoMoveWindow() because we want to move window immediately
-        // and not defer it here
+        // and not defer it here as otherwise the value returned by
+        // GetClient/WindowRect() wouldn't change as the window wouldn't be
+        // really resized
         if ( !::MoveWindow(GetHwnd(),
                            rectWin.left,
                            rectWin.top,
@@ -1911,7 +2005,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
 #if defined(__WXWINCE__)
     UINT flags = 0;
 #else
-    UINT flags = TPM_RIGHTBUTTON;
+    UINT flags = TPM_RIGHTBUTTON | TPM_RECURSE;
 #endif
     ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
 
@@ -2204,7 +2298,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
         // relay mouse move events to the tooltip control
         MSG *msg = (MSG *)pMsg;
         if ( msg->message == WM_MOUSEMOVE )
-            m_tooltip->RelayEvent(pMsg);
+            wxToolTip::RelayEvent(pMsg);
     }
 #endif // wxUSE_TOOLTIPS
 
@@ -2546,6 +2640,36 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                     wxCHECK_MSG( win, 0,
                                  _T("FindWindowForMouseEvent() returned NULL") );
                 }
+#ifdef __POCKETPC__
+                if (IsContextMenuEnabled() && message == WM_LBUTTONDOWN)
+                {
+                    SHRGINFO shrgi = {0};
+
+                    shrgi.cbSize = sizeof(SHRGINFO);
+                    shrgi.hwndClient = (HWND) GetHWND();
+                    shrgi.ptDown.x = x;
+                    shrgi.ptDown.y = y;
+
+                    shrgi.dwFlags = SHRG_RETURNCMD;
+                    // shrgi.dwFlags = SHRG_NOTIFYPARENT;
+
+                    if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi))
+                    {
+                        wxPoint pt(x, y);
+                        pt = ClientToScreen(pt);
+
+                        wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
+
+                        evtCtx.SetEventObject(this);
+                        if (GetEventHandler()->ProcessEvent(evtCtx))
+                        {
+                            processed = true;
+                            return true;
+                        }
+                    }
+                }
+#endif
+
 #else // !__WXWINCE__
                 wxWindowMSW *win = this;
 #endif // __WXWINCE__/!__WXWINCE__
@@ -2690,6 +2814,16 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                     case VK_SUBTRACT:
                     case VK_MULTIPLY:
                     case VK_DIVIDE:
+                    case VK_NUMPAD0:
+                    case VK_NUMPAD1:
+                    case VK_NUMPAD2:
+                    case VK_NUMPAD3:
+                    case VK_NUMPAD4:
+                    case VK_NUMPAD5:
+                    case VK_NUMPAD6:
+                    case VK_NUMPAD7:
+                    case VK_NUMPAD8:
+                    case VK_NUMPAD9:
                     case VK_OEM_1:
                     case VK_OEM_2:
                     case VK_OEM_3:
@@ -2813,6 +2947,10 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
             processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
             break;
 
+        case WM_SETTINGCHANGE:
+            processed = HandleSettingChange(wParam, lParam);
+            break;
+
         case WM_QUERYNEWPALETTE:
             processed = HandleQueryNewPalette();
             break;
@@ -2887,50 +3025,48 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 #if defined(WM_HELP)
         case WM_HELP:
             {
-                // HELPINFO doesn't seem to be supported on WinCE.
+                // by default, WM_HELP is propagated by DefWindowProc() upwards
+                // to the window parent but as we do it ourselves already
+                // (wxHelpEvent is derived from wxCommandEvent), we don't want
+                // to get the other events if we process this message at all
+                processed = true;
+
+                // WM_HELP doesn't use lParam under CE
 #ifndef __WXWINCE__
                 HELPINFO* info = (HELPINFO*) lParam;
-                // Don't yet process menu help events, just windows
-                if (info->iContextType == HELPINFO_WINDOW)
+                if ( info->iContextType == HELPINFO_WINDOW )
                 {
-#endif
-                    wxWindowMSW* subjectOfHelp = this;
-                    bool eventProcessed = false;
-                    while (subjectOfHelp && !eventProcessed)
-                    {
-                        wxHelpEvent helpEvent(wxEVT_HELP,
-                                              subjectOfHelp->GetId(),
+#endif // !__WXWINCE__
+                    wxHelpEvent helpEvent
+                                (
+                                    wxEVT_HELP,
+                                    GetId(),
 #ifdef __WXWINCE__
-                                              wxPoint(0,0)
+                                    wxGetMousePosition() // what else?
 #else
-                                              wxPoint(info->MousePos.x, info->MousePos.y)
+                                    wxPoint(info->MousePos.x, info->MousePos.y)
 #endif
-                                              );
+                                );
 
-                        helpEvent.SetEventObject(this);
-                        eventProcessed =
-                            GetEventHandler()->ProcessEvent(helpEvent);
-
-                        // Go up the window hierarchy until the event is
-                        // handled (or not)
-                        subjectOfHelp = subjectOfHelp->GetParent();
-                    }
-
-                    processed = eventProcessed;
+                    helpEvent.SetEventObject(this);
+                    GetEventHandler()->ProcessEvent(helpEvent);
 #ifndef __WXWINCE__
                 }
-                else if (info->iContextType == HELPINFO_MENUITEM)
+                else if ( info->iContextType == HELPINFO_MENUITEM )
                 {
                     wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
                     helpEvent.SetEventObject(this);
-                    processed = GetEventHandler()->ProcessEvent(helpEvent);
+                    GetEventHandler()->ProcessEvent(helpEvent);
 
                 }
-                //else: processed is already false
-#endif
+                else // unknown help event?
+                {
+                    processed = false;
+                }
+#endif // !__WXWINCE__
             }
             break;
-#endif
+#endif // WM_HELP
 
 #if !defined(__WXWINCE__)
         case WM_CONTEXTMENU:
@@ -2971,6 +3107,16 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                 }
             }
             break;
+
+#ifndef __WXWINCE__
+        case WM_POWERBROADCAST:
+            {
+                bool vetoed;
+                processed = HandlePower(wParam, lParam, &vetoed);
+                rc.result = processed && vetoed ? BROADCAST_QUERY_DENY : TRUE;
+            }
+            break;
+#endif // __WXWINCE__
     }
 
     if ( !processed )
@@ -3270,7 +3416,7 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
         // Truncate tooltip length if needed as otherwise we might not have
         // enough space for it in the buffer and MultiByteToWideChar() would
         // return an error
-        size_t tipLength = wxMin(ttip.Len(), WXSIZEOF(buf) - 1);
+        size_t tipLength = wxMin(ttip.length(), WXSIZEOF(buf) - 1);
 
         // Convert to WideChar without adding the NULL character. The NULL
         // character is added afterwards (this is more efficient).
@@ -3398,10 +3544,6 @@ bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED_IN_WINCE(cs),
         EnsureParentHasControlParentStyle(GetParent());
 #endif // !__WXWINCE__
 
-    // TODO: should generate this event from WM_NCCREATE
-    wxWindowCreateEvent event((wxWindow *)this);
-    (void)GetEventHandler()->ProcessEvent(event);
-
     *mayCreate = true;
 
     return true;
@@ -3682,6 +3824,69 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
     return false;
 }
 
+bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
+                              WXLPARAM WXUNUSED(lParam),
+                              bool *WXUNUSED_IN_WINCE(vetoed))
+{
+#ifdef __WXWINCE__
+    // FIXME
+    return false;
+#else
+    wxEventType evtType;
+    switch ( wParam )
+    {
+        case PBT_APMQUERYSUSPEND:
+            evtType = wxEVT_POWER_SUSPENDING;
+            break;
+
+        case PBT_APMQUERYSUSPENDFAILED:
+            evtType = wxEVT_POWER_SUSPEND_CANCEL;
+            break;
+
+        case PBT_APMSUSPEND:
+            evtType = wxEVT_POWER_SUSPENDED;
+            break;
+
+        case PBT_APMRESUMESUSPEND:
+#ifdef PBT_APMRESUMEAUTOMATIC
+        case PBT_APMRESUMEAUTOMATIC:
+#endif
+            evtType = wxEVT_POWER_RESUME;
+            break;
+
+        default:
+            wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam);
+            // fall through
+
+        // these messages are currently not mapped to wx events
+        case PBT_APMQUERYSTANDBY:
+        case PBT_APMQUERYSTANDBYFAILED:
+        case PBT_APMSTANDBY:
+        case PBT_APMRESUMESTANDBY:
+        case PBT_APMBATTERYLOW:
+        case PBT_APMPOWERSTATUSCHANGE:
+        case PBT_APMOEMEVENT:
+        case PBT_APMRESUMECRITICAL:
+            evtType = wxEVT_NULL;
+            break;
+    }
+
+    // don't handle unknown messages
+    if ( evtType == wxEVT_NULL )
+        return false;
+
+    // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
+
+    wxPowerEvent event(evtType);
+    if ( !GetEventHandler()->ProcessEvent(event) )
+        return false;
+
+    *vetoed = event.IsVetoed();
+
+    return true;
+#endif
+}
+
 // ---------------------------------------------------------------------------
 // owner drawn stuff
 // ---------------------------------------------------------------------------
@@ -3897,6 +4102,30 @@ bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
     return GetEventHandler()->ProcessEvent(event);
 }
 
+bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam)
+{
+    // despite MSDN saying "(This message cannot be sent directly to a window.)"
+    // we need to send this to child windows (it is only sent to top-level
+    // windows) so {list,tree}ctrls can adjust their font size if necessary
+    // this is exactly how explorer does it to enable the font size changes
+
+    wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+    while ( node )
+    {
+        // top-level windows already get this message from the system
+        wxWindow *win = node->GetData();
+        if ( !win->IsTopLevel() )
+        {
+            ::SendMessage(GetHwndOf(win), WM_SETTINGCHANGE, wParam, lParam);
+        }
+
+        node = node->GetNext();
+    }
+
+    // let the system handle it
+    return false;
+}
+
 bool wxWindowMSW::HandleQueryNewPalette()
 {
 
@@ -4073,14 +4302,11 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
 
     dc.SetHDC(hdc);
     dc.SetWindow((wxWindow *)this);
-    dc.BeginDrawing();
 
     wxEraseEvent event(m_windowId, &dc);
     event.SetEventObject(this);
     bool rc = GetEventHandler()->ProcessEvent(event);
 
-    dc.EndDrawing();
-
     // must be called manually as ~wxDC doesn't do anything for wxDCTemp
     dc.SelectOldObjects(hdc);
 
@@ -4797,35 +5023,14 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
     int id;
     if ( isASCII )
     {
-        // If 1 -> 26, translate to either special keycode or just set
-        // ctrlDown.  IOW, Ctrl-C should result in keycode == 3 and
-        // ControlDown() == true.
         id = wParam;
-        if ( (id > 0) && (id < 27) )
-        {
-            switch (id)
-            {
-                case 13:
-                    id = WXK_RETURN;
-                    break;
-
-                case 8:
-                    id = WXK_BACK;
-                    break;
-
-                case 9:
-                    id = WXK_TAB;
-                    break;
-
-                default:
-                    //ctrlDown = true;
-                    break;
-            }
-        }
     }
     else // we're called from WM_KEYDOWN
     {
-        id = wxCharCodeMSWToWX(wParam, lParam);
+        // don't pass lParam to wxCharCodeMSWToWX() here because we don't want
+        // to get numpad key codes: CHAR events should use the logical keys
+        // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events
+        id = wxCharCodeMSWToWX(wParam);
         if ( id == 0 )
         {
             // it's ASCII and will be processed here only when called from
@@ -4862,16 +5067,8 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
         id = wParam;
     }
 
-    if ( id != -1 ) // VZ: does this ever happen (FIXME)?
-    {
-        wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
-        if ( GetEventHandler()->ProcessEvent(event) )
-        {
-            return true;
-        }
-    }
-
-    return false;
+    wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
+    return GetEventHandler()->ProcessEvent(event);
 }
 
 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
@@ -4884,14 +5081,8 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
         id = wParam;
     }
 
-    if ( id != -1 ) // VZ: does this ever happen (FIXME)?
-    {
-        wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
-        if ( GetEventHandler()->ProcessEvent(event) )
-            return true;
-    }
-
-    return false;
+    wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
+    return GetEventHandler()->ProcessEvent(event);
 }
 
 int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
@@ -4964,6 +5155,18 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
     return wxNOT_FOUND;
 }
 
+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;
+    wxClipboardTextEvent evt(type, GetId());
+
+    evt.SetEventObject(this);
+
+    return GetEventHandler()->ProcessEvent(evt);
+}
+
 // ---------------------------------------------------------------------------
 // joystick
 // ---------------------------------------------------------------------------
@@ -5167,6 +5370,18 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font)
     //   the_font.ReleaseResource();
 }
 
+// use the "extended" bit (24) of lParam to distinguish extended keys
+// from normal keys as the same key is sent
+static inline
+int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended)
+{
+    // except that if lParam is 0, it means we don't have real lParam from
+    // WM_KEYDOWN but are just translating just a VK constant (e.g. done from
+    // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a
+    // non-numpad (hence extended) key as this is a more common case
+    return !lParam || (lParam & (1 << 24)) ? keyExtended : keyNormal;
+}
+
 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
 int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam)
@@ -5251,41 +5466,41 @@ int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam)
         case VK_APPS:       id = WXK_WINDOWS_MENU; break;
 #endif // VK_APPS defined
 
-        // use the "extended" bit (24) of lParam to distinguish extended keys
-        // from normal keys as the same key is sent
+        // handle extended keys
         case VK_PRIOR:
-            id = lParam & (1 << 24) ? WXK_PRIOR : WXK_NUMPAD_PRIOR;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP);
             break;
         case VK_NEXT:
-            id = lParam & (1 << 24) ? WXK_NEXT : WXK_NUMPAD_NEXT;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN);
             break;
         case VK_END:
-            id = lParam & (1 << 24) ? WXK_END : WXK_NUMPAD_END;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END);
             break;
         case VK_HOME:
-            id = lParam & (1 << 24) ? WXK_HOME : WXK_NUMPAD_HOME;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME);
             break;
         case VK_LEFT:
-            id = lParam & (1 << 24) ? WXK_LEFT : WXK_NUMPAD_LEFT;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT);
             break;
         case VK_UP:
-            id = lParam & (1 << 24) ? WXK_UP : WXK_NUMPAD_UP;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP);
             break;
         case VK_RIGHT:
-            id = lParam & (1 << 24) ? WXK_RIGHT : WXK_NUMPAD_RIGHT;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT);
             break;
         case VK_DOWN:
-            id = lParam & (1 << 24) ? WXK_DOWN : WXK_NUMPAD_DOWN;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN);
             break;
         case VK_INSERT:
-            id = lParam & (1 << 24) ? WXK_INSERT : WXK_NUMPAD_INSERT;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT);
             break;
         case VK_DELETE:
-            id = lParam & (1 << 24) ? WXK_DELETE : WXK_NUMPAD_DELETE;
+            id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
             break;
-        // this order is correct as the numpad enter is the extended key
         case VK_RETURN:
-            id = lParam & (1 << 24) ? WXK_NUMPAD_ENTER : WXK_RETURN;
+            // don't use ChooseNormalOrExtended() here as the keys are reversed
+            // here: numpad enter is the extended one
+            id = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN;
             break;
 
         default:
@@ -5308,8 +5523,8 @@ WXWORD wxCharCodeWXToMSW(int id, bool *isVirtual)
     case WXK_ALT:       keySym = VK_MENU; break;
     case WXK_PAUSE:     keySym = VK_PAUSE; break;
     case WXK_CAPITAL:   keySym = VK_CAPITAL; break;
-    case WXK_PRIOR:     keySym = VK_PRIOR; break;
-    case WXK_NEXT :     keySym = VK_NEXT; break;
+    case WXK_PAGEUP:    keySym = VK_PRIOR; break;
+    case WXK_PAGEDOWN:  keySym = VK_NEXT; break;
     case WXK_END:       keySym = VK_END; break;
     case WXK_HOME :     keySym = VK_HOME; break;
     case WXK_LEFT :     keySym = VK_LEFT; break;
@@ -6028,18 +6243,10 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
     POINT pt2;
     pt2.x = pt.x;
     pt2.y = pt.y;
-    HWND hWndHit = ::WindowFromPoint(pt2);
 
-    wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ;
-    HWND hWnd = hWndHit;
+    HWND hWnd = ::WindowFromPoint(pt2);
 
-    // Try to find a window with a wxWindow associated with it
-    while (!win && (hWnd != 0))
-    {
-        hWnd = ::GetParent(hWnd);
-        win = wxFindWinFromHandle((WXHWND) hWnd) ;
-    }
-    return win;
+    return wxGetWindowFromHWND((WXHWND)hWnd);
 }
 
 // Get the current mouse position.