]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
added GetControlBounds for accessing contrl.rect
[wxWidgets.git] / src / msw / window.cpp
index 507019bbf8bc167790449d0b9d43535f753d6808..7b171f9f7cc9c4d11ec8c01ef07129881ab0c8e4 100644 (file)
@@ -46,6 +46,7 @@
     #include "wx/listbox.h"
     #include "wx/button.h"
     #include "wx/msgdlg.h"
+    #include "wx/settings.h"
 
     #include <stdio.h>
 #endif
     #include "wx/caret.h"
 #endif // wxUSE_CARET
 
+#if wxUSE_SPINCTRL
+    #include "wx/spinctrl.h"
+#endif // wxUSE_SPINCTRL
+
 #include "wx/intl.h"
 #include "wx/log.h"
 
 #define SIF_TRACKPOS 16
 #endif
 
+#if wxUSE_MOUSEWHEEL
+    #ifndef WM_MOUSEWHEEL
+        #define WM_MOUSEWHEEL           0x020A
+    #endif
+    #ifndef WHEEL_DELTA
+        #define WHEEL_DELTA             120
+    #endif
+    #ifndef SPI_GETWHEELSCROLLLINES
+        #define SPI_GETWHEELSCROLLLINES 104
+    #endif
+#endif
+
+
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
@@ -162,7 +180,7 @@ END_EVENT_TABLE()
 // Find an item given the MS Windows id
 wxWindow *wxWindow::FindItem(long id) const
 {
-    wxControl *item = wxDynamicCast(this, wxControl);
+    wxControl *item = wxDynamicThisCast(this, wxControl);
     if ( item )
     {
         // i it we or one of our "internal" children?
@@ -270,12 +288,27 @@ wxWindow::~wxWindow()
     m_isBeingDeleted = TRUE;
 
     MSWDetachWindowMenu();
+    
+    // VS: make sure there's no wxFrame with last focus set to us:
+    for (wxWindow *win = GetParent(); win; win = win->GetParent())
+    {
+        wxFrame *frame = wxDynamicCast(win, wxFrame);
+        if ( frame )
+        {
+            if ( frame->GetLastFocus() == this )
+                frame->SetLastFocus((wxWindow*)NULL);
+            break;
+        }
+    }
+
+    // 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
+    //     find their parent frame (see above).
+    DestroyChildren();
 
     if ( m_parent )
         m_parent->RemoveChild(this);
 
-    DestroyChildren();
-
     if ( m_hWnd )
     {
         // VZ: test temp removed to understand what really happens here
@@ -338,12 +371,10 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
                      DLGC_WANTTAB | DLGC_WANTMESSAGE;
     }
 
-    MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL,
-              pos.x, pos.y,
-              WidthDefault(size.x), HeightDefault(size.y),
-              msflags, NULL, exStyle);
-
-    return TRUE;
+    return MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL,
+                     pos.x, pos.y,
+                     WidthDefault(size.x), HeightDefault(size.y),
+                     msflags, NULL, exStyle);
 }
 
 // ---------------------------------------------------------------------------
@@ -363,7 +394,7 @@ wxWindow *wxWindowBase::FindFocus()
     HWND hWnd = ::GetFocus();
     if ( hWnd )
     {
-        return wxFindWinFromHandle((WXHWND) hWnd);
+        return wxGetWindowFromHWND((WXHWND)hWnd);
     }
 
     return NULL;
@@ -380,7 +411,7 @@ bool wxWindow::Enable(bool enable)
 
     // VZ: no, this is a bad idea: imagine that you have a dialog with some
     //     disabled controls and disable it - you really wouldn't like the
-    //     disabled controls eb reenabled too when you reenable the dialog!
+    //     disabled controls be reenabled too when you reenable the dialog!
 #if 0
     wxWindowList::Node *node = GetChildren().GetFirst();
     while ( node )
@@ -867,7 +898,8 @@ WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders)
             exStyle |= WS_EX_DLGMODALFRAME;
 #if defined(__WIN95__)
         if ( style & wxRAISED_BORDER )
-            exStyle |= WS_EX_WINDOWEDGE;
+            // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
+            exStyle |= WS_EX_DLGMODALFRAME; /* WS_EX_WINDOWEDGE */;
         if ( style & wxSTATIC_BORDER )
             exStyle |= WS_EX_STATICEDGE;
 #endif
@@ -972,7 +1004,7 @@ void wxWindow::SetupColours()
         SetBackgroundColour(GetParent()->GetBackgroundColour());
 }
 
-void wxWindow::OnIdle(wxIdleEvent& event)
+void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
 {
     // Check if we need to send a LEAVE event
     if ( m_mouseInWindow )
@@ -998,7 +1030,7 @@ void wxWindow::OnIdle(wxIdleEvent& event)
                 state |= MK_MBUTTON;
             if ( GetKeyState( VK_RBUTTON ) )
                 state |= MK_RBUTTON;
-  
+
             wxMouseEvent event(wxEVT_LEAVE_WINDOW);
             InitMouseEvent(event, pt.x, pt.y, state);
 
@@ -1010,7 +1042,7 @@ void wxWindow::OnIdle(wxIdleEvent& event)
 }
 
 // Set this window to be the child of 'parent'.
-bool wxWindow::Reparent(wxWindow *parent)
+bool wxWindow::Reparent(wxWindowBase *parent)
 {
     if ( !wxWindowBase::Reparent(parent) )
         return FALSE;
@@ -1146,11 +1178,14 @@ void wxWindow::DoGetPosition(int *x, int *y) const
             ::ScreenToClient(hParentWnd, &point);
         }
 
-        // We may be faking the client origin. So a window that's really at (0,
-        // 30) may appear (to wxWin apps) to be at (0, 0).
-        wxPoint pt(parent->GetClientAreaOrigin());
-        point.x -= pt.x;
-        point.y -= pt.y;
+        if ( parent )
+        {
+            // We may be faking the client origin. So a window that's really at (0,
+            // 30) may appear (to wxWin apps) to be at (0, 0).
+            wxPoint pt(parent->GetClientAreaOrigin());
+            point.x -= pt.x;
+            point.y -= pt.y;
+        }
     }
 
     if ( x )
@@ -1462,7 +1497,7 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
     ::ClientToScreen(hWnd, &point);
     wxCurrentPopupMenu = menu;
     ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
-    wxYield();
+    wxYieldIfNeeded();
     wxCurrentPopupMenu = NULL;
 
     menu->SetInvokingWindow(NULL);
@@ -1557,12 +1592,23 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg)
                         }
                         else if ( lDlgCode & DLGC_BUTTON )
                         {
-                            // buttons want process Enter themselevs
+                            // let IsDialogMessage() handle this for all
+                            // buttons except the owner-drawn ones which it
+                            // just seems to ignore
+                            long style = ::GetWindowLong(msg->hwnd, GWL_STYLE);
+                            if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
+                            {
+                                // emulate the button click
+                                wxWindow *btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
+                                if ( btn )
+                                    btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+                            }
+
                             bProcess = FALSE;
                         }
                         else
                         {
-                            wxPanel *panel = wxDynamicCast(this, wxPanel);
+                            wxPanel *panel = wxDynamicThisCast(this, wxPanel);
                             wxButton *btn = NULL;
                             if ( panel )
                             {
@@ -1846,7 +1892,7 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
             break;
 
         case WM_MOVE:
-            processed = HandleMove(LOWORD(lParam), HIWORD(lParam));
+            processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
             break;
 
         case WM_SIZE:
@@ -1887,17 +1933,20 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
             break;
 
         case WM_MOUSEMOVE:
-           {
-                short x = LOWORD(lParam);
-                short y = HIWORD(lParam);
+            processed = HandleMouseMove(GET_X_LPARAM(lParam),
+                                        GET_Y_LPARAM(lParam),
+                                        wParam);
+            break;
 
-                processed = HandleMouseMove(x, y, wParam);
-           }
-           break;
+#if wxUSE_MOUSEWHEEL
+        case WM_MOUSEWHEEL:
+            processed = HandleMouseWheel(wParam, lParam);
+            break;
+#endif
 
         case WM_LBUTTONDOWN:
            // set focus to this window
-           if ((GetExtraStyle() & wxWS_EX_NO_AUTOFOCUS) != wxWS_EX_NO_AUTOFOCUS)
+           if (AcceptsFocus())
                 SetFocus();
 
            // fall through
@@ -1910,12 +1959,10 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
         case WM_MBUTTONDOWN:
         case WM_MBUTTONUP:
         case WM_MBUTTONDBLCLK:
-            {
-                short x = LOWORD(lParam);
-                short y = HIWORD(lParam);
-
-                processed = HandleMouseEvent(message, x, y, wParam);
-            }
+            processed = HandleMouseEvent(message,
+                                         GET_X_LPARAM(lParam),
+                                         GET_Y_LPARAM(lParam),
+                                         wParam);
             break;
 
         case MM_JOY1MOVE:
@@ -1926,12 +1973,10 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
         case MM_JOY2BUTTONDOWN:
         case MM_JOY1BUTTONUP:
         case MM_JOY2BUTTONUP:
-            {
-                int x = LOWORD(lParam);
-                int y = HIWORD(lParam);
-
-                processed = HandleJoystickEvent(message, x, y, wParam);
-            }
+            processed = HandleJoystickEvent(message,
+                                            GET_X_LPARAM(lParam),
+                                            GET_Y_LPARAM(lParam),
+                                            wParam);
             break;
 
         case WM_SYSCOMMAND:
@@ -2171,36 +2216,55 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
                 rc.result = TRUE;
             }
             break;
+
 #ifdef __WIN32__
         case WM_HELP:
-        {
-            HELPINFO* info = (HELPINFO*) lParam;
-            // Don't yet process menu help events, just windows
-            if (info->iContextType == HELPINFO_WINDOW)
             {
-                wxWindow* subjectOfHelp = this;
-                bool eventProcessed = FALSE;
-                while (subjectOfHelp && !eventProcessed)
+                HELPINFO* info = (HELPINFO*) lParam;
+                // Don't yet process menu help events, just windows
+                if (info->iContextType == HELPINFO_WINDOW)
                 {
-                    wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), wxPoint(info->MousePos.x, info->MousePos.y) ) ; // info->iCtrlId);
+                    wxWindow* subjectOfHelp = this;
+                    bool eventProcessed = FALSE;
+                    while (subjectOfHelp && !eventProcessed)
+                    {
+                        wxHelpEvent helpEvent(wxEVT_HELP,
+                                              subjectOfHelp->GetId(),
+                                              wxPoint(info->MousePos.x,
+                                              info->MousePos.y) );
+                        helpEvent.SetEventObject(this);
+                        eventProcessed =
+                            GetEventHandler()->ProcessEvent(helpEvent);
+
+                        // Go up the window hierarchy until the event is
+                        // handled (or not)
+                        subjectOfHelp = subjectOfHelp->GetParent();
+                    }
+
+                    processed = eventProcessed;
+                }
+                else if (info->iContextType == HELPINFO_MENUITEM)
+                {
+                    wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
                     helpEvent.SetEventObject(this);
-                    eventProcessed = GetEventHandler()->ProcessEvent(helpEvent);
+                    processed = GetEventHandler()->ProcessEvent(helpEvent);
 
-                    // Go up the window hierarchy until the event is handled (or not)
-                    subjectOfHelp = subjectOfHelp->GetParent();
                 }
-                processed = eventProcessed;
+                //else: processed is already FALSE
             }
-            else if (info->iContextType == HELPINFO_MENUITEM)
+            break;
+
+        case WM_CONTEXTMENU:
             {
-                wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId) ;
-                helpEvent.SetEventObject(this);
-                processed = GetEventHandler()->ProcessEvent(helpEvent);
+                // 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);
+                processed = GetEventHandler()->ProcessEvent(evtCtx);
             }
-            else processed = FALSE;
             break;
-        }
-#endif
+#endif // __WIN32__
     }
 
     if ( !processed )
@@ -2217,7 +2281,7 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
 
 // Dialog window proc
 LONG APIENTRY _EXPORT
-wxDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+wxDlgProc(HWND WXUNUSED(hWnd), UINT message, WPARAM WXUNUSED(wParam), LPARAM WXUNUSED(lParam))
 {
     if ( message == WM_INITDIALOG )
     {
@@ -2293,24 +2357,25 @@ void wxWindow::MSWDetachWindowMenu()
 {
     if ( m_hMenu )
     {
+        wxChar buf[1024];
         HMENU hMenu = (HMENU)m_hMenu;
 
         int N = ::GetMenuItemCount(hMenu);
-        int i;
-        for (i = 0; i < N; i++)
+        for ( int i = 0; i < N; i++ )
         {
-            wxChar buf[100];
-            int chars = GetMenuString(hMenu, i, buf, 100, MF_BYPOSITION);
-            if ( !chars )
+            if ( !::GetMenuString(hMenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION) )
             {
                 wxLogLastError(wxT("GetMenuString"));
 
                 continue;
             }
 
-            if ( wxStrcmp(buf, wxT("&Window")) == 0 )
+            if ( wxStrcmp(buf, _("&Window")) == 0 )
             {
-                RemoveMenu(hMenu, i, MF_BYPOSITION);
+                if ( !::RemoveMenu(hMenu, i, MF_BYPOSITION) )
+                {
+                    wxLogLastError(wxT("RemoveMenu"));
+                }
 
                 break;
             }
@@ -2321,7 +2386,7 @@ void wxWindow::MSWDetachWindowMenu()
 bool wxWindow::MSWCreate(int id,
                          wxWindow *parent,
                          const wxChar *wclass,
-                         wxWindow *wx_win,
+                         wxWindow *WXUNUSED(wx_win),
                          const wxChar *title,
                          int x,
                          int y,
@@ -2347,10 +2412,14 @@ bool wxWindow::MSWCreate(int id,
         height1 = parent_rect.bottom - parent_rect.top;
     }
 
-    if ( x > -1 ) x1 = x;
-    if ( y > -1 ) y1 = y;
-    if ( width > -1 ) width1 = width;
-    if ( height > -1 ) height1 = height;
+    if ( x != -1 )
+        x1 = x;
+    if ( y != -1 )
+        y1 = y;
+    if ( width != -1 )
+        width1 = width;
+    if ( height != -1 )
+        height1 = height;
 
     // unfortunately, setting WS_EX_CONTROLPARENT only for some windows in the
     // hierarchy with several embedded panels (and not all of them) causes the
@@ -2366,14 +2435,22 @@ bool wxWindow::MSWCreate(int id,
     }
 #endif // 0
 
-    HWND hParent = (HWND)NULL;
-    if ( parent )
-        hParent = (HWND) parent->GetHWND();
+    HWND hParent = parent ? GetHwndOf(parent) : NULL;
 
     wxWndHook = this;
 
     if ( dialog_template )
     {
+        // for the dialogs without wxDIALOG_NO_PARENT style, use the top level
+        // app window as parent - this avoids creating modal dialogs without
+        // parent
+        if ( !hParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
+        {
+            wxWindow *winTop = wxTheApp->GetTopWindow();
+            if ( winTop )
+                hParent = GetHwndOf(winTop);
+        }
+
         m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(),
                                         dialog_template,
                                         hParent,
@@ -2381,27 +2458,37 @@ bool wxWindow::MSWCreate(int id,
 
         if ( m_hWnd == 0 )
         {
-            wxLogError(_("Can't find dummy dialog template!\nCheck resource include path for finding wx.rc."));
+            wxLogError(_("Can't find dialog template '%s'!\nCheck resource include path for finding wx.rc."),
+                       dialog_template);
 
             return FALSE;
         }
-        if (extendedStyle != 0)
+
+        if ( extendedStyle != 0 )
         {
             ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, extendedStyle);
             ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0,
-                SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+                           SWP_NOSIZE |
+                           SWP_NOMOVE |
+                           SWP_NOZORDER |
+                           SWP_NOACTIVATE);
         }
+
 #if defined(__WIN95__)
         // For some reason, the system menu is activated when we use the
         // WS_EX_CONTEXTHELP style, so let's set a reasonable icon
         if (extendedStyle & WS_EX_CONTEXTHELP)
         {
-            if (wxTheApp->GetTopWindow() && (wxTheApp->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame))))
+            wxFrame *winTop = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
+            if ( winTop )
             {
-                wxIcon icon = ((wxFrame*)wxTheApp->GetTopWindow())->GetIcon();
-                if (icon.Ok())
-                    SendMessage(GetHwnd(), WM_SETICON,
-                        (WPARAM)TRUE, (LPARAM)(HICON) icon.GetHICON());
+                wxIcon icon = winTop->GetIcon();
+                if ( icon.Ok() )
+                {
+                    ::SendMessage(GetHwnd(), WM_SETICON,
+                                  (WPARAM)TRUE,
+                                  (LPARAM)GetHiconOf(icon));
+                }
             }
         }
 #endif // __WIN95__
@@ -2426,15 +2513,14 @@ bool wxWindow::MSWCreate(int id,
             wxLogLastError(wxT("MoveWindow"));
         }
     }
-    else
+    else // creating a normal window, not a dialog
     {
         int controlId = 0;
         if ( style & WS_CHILD )
-          {
             controlId = id;
-            // all child windows should clip their siblings
-            // style |= /* WS_CLIPSIBLINGS */ ;
-          }
+
+        if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
+          style |= WS_CLIPSIBLINGS;
 
         wxString className(wclass);
         if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
@@ -2462,6 +2548,7 @@ bool wxWindow::MSWCreate(int id,
     }
 
     wxWndHook = NULL;
+
 #ifdef __WXDEBUG__
     wxNode* node = wxWinHandleList->Member(this);
     if (node)
@@ -2472,9 +2559,12 @@ bool wxWindow::MSWCreate(int id,
             wxLogError(wxT("A second HWND association is being added for the same window!"));
         }
     }
-#endif
+#endif // Debug
+
     wxAssociateWinWithHandle((HWND) m_hWnd, this);
 
+    SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+
     return TRUE;
 }
 
@@ -2581,7 +2671,7 @@ bool wxWindow::HandleEndSession(bool endSession, long logOff)
 // window creation/destruction
 // ---------------------------------------------------------------------------
 
-bool wxWindow::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
+bool wxWindow::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
 {
     // TODO: should generate this event from WM_NCCREATE
     wxWindowCreateEvent event(this);
@@ -2691,7 +2781,7 @@ bool wxWindow::HandleKillFocus(WXHWND WXUNUSED(hwnd))
 // miscellaneous
 // ---------------------------------------------------------------------------
 
-bool wxWindow::HandleShow(bool show, int status)
+bool wxWindow::HandleShow(bool show, int WXUNUSED(status))
 {
     wxShowEvent event(GetId(), show);
     event.m_eventObject = this;
@@ -2742,7 +2832,7 @@ bool wxWindow::HandleDropFiles(WXWPARAM wParam)
     return rc;
 }
 
-bool wxWindow::HandleSetCursor(WXHWND hWnd,
+bool wxWindow::HandleSetCursor(WXHWND WXUNUSED(hWnd),
                                short nHitTest,
                                int WXUNUSED(mouseMsg))
 {
@@ -2842,19 +2932,20 @@ bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
 
         wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
 
-        // prepare to call OnDrawItem()
-        wxDC dc;
-        dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE);
+        // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
+        // the DC from being released
+        wxDCTemp dc((WXHDC)pDrawStruct->hDC);
         wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
                     pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
                     pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
 
         return pMenuItem->OnDrawItem
-                          (
-                            dc, rect,
-                            (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
-                            (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
-                          );
+               (
+                dc,
+                rect,
+                (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
+                (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
+               );
     }
 
     wxWindow *item = FindItem(id);
@@ -2931,12 +3022,12 @@ bool wxWindow::HandleCtlColor(WXHBRUSH *brush,
 }
 
 // Define for each class of dialog and control
-WXHBRUSH wxWindow::OnCtlColor(WXHDC hDC,
-                              WXHWND hWnd,
-                              WXUINT nCtlColor,
-                              WXUINT message,
-                              WXWPARAM wParam,
-                              WXLPARAM lParam)
+WXHBRUSH wxWindow::OnCtlColor(WXHDC WXUNUSED(hDC),
+                              WXHWND WXUNUSED(hWnd),
+                              WXUINT WXUNUSED(nCtlColor),
+                              WXUINT WXUNUSED(message),
+                              WXWPARAM WXUNUSED(wParam),
+                              WXLPARAM WXUNUSED(lParam))
 {
     return (WXHBRUSH)0;
 }
@@ -3022,9 +3113,8 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
     if ( ::IsIconic(GetHwnd()) )
         return TRUE;
 
-    wxDC dc;
+    wxDCTemp dc(hdc);
 
-    dc.SetHDC(hdc);
     dc.SetWindow(this);
     dc.BeginDrawing();
 
@@ -3033,8 +3123,9 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
     bool rc = GetEventHandler()->ProcessEvent(event);
 
     dc.EndDrawing();
+
+    // must be called manually as ~wxDC doesn't do anything for wxDCTemp
     dc.SelectOldObjects(hdc);
-    dc.SetHDC((WXHDC) NULL);
 
     return rc;
 }
@@ -3130,6 +3221,7 @@ bool wxWindow::HandleGetMinMaxInfo(void *mmInfo)
 }
 
 // generate an artificial resize event
+/* FUNCTION IS NOW A MEMBER OF wxFrame - gt
 void wxWindow::SendSizeEvent()
 {
     RECT r;
@@ -3145,6 +3237,7 @@ void wxWindow::SendSizeEvent()
     (void)::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED,
                         MAKELPARAM(r.right - r.left, r.bottom - r.top));
 }
+*/
 
 // ---------------------------------------------------------------------------
 // command messages
@@ -3195,11 +3288,22 @@ bool wxWindow::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
 
         return GetEventHandler()->ProcessEvent(event);
     }
+#if wxUSE_SPINCTRL
+    else
+    {
+        // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
+        // notifications to its parent which we want to reflect back to
+        // wxSpinCtrl
+        wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
+        if ( spin && spin->ProcessTextCommand(cmd, id) )
+            return TRUE;
+    }
+#endif // wxUSE_SPINCTRL
 
     return FALSE;
 }
 
-bool wxWindow::HandleSysCommand(WXWPARAM wParam, WXLPARAM lParam)
+bool wxWindow::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
 {
     // 4 bits are reserved
     switch ( wParam & 0xFFFFFFF0 )
@@ -3285,7 +3389,7 @@ bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
     if ( (m_lastMouseEvent == wxEVT_RIGHT_DOWN ||
           m_lastMouseEvent == wxEVT_LEFT_DOWN ||
           m_lastMouseEvent == wxEVT_MIDDLE_DOWN) &&
-         (m_lastMouseX == event.m_x && m_lastMouseY == event.m_y) )
+         (m_lastMouseX == x && m_lastMouseY == y) )
     {
         m_lastMouseEvent = wxEVT_MOTION;
 
@@ -3296,6 +3400,46 @@ bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
     return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags);
 }
 
+
+bool wxWindow::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
+{
+#if wxUSE_MOUSEWHEEL
+    wxMouseEvent event(wxEVT_MOUSEWHEEL);
+    InitMouseEvent(event,
+                   GET_X_LPARAM(lParam),
+                   GET_Y_LPARAM(lParam),
+                   LOWORD(wParam));
+    event.m_wheelRotation = (short)HIWORD(wParam);
+    event.m_wheelDelta = WHEEL_DELTA;
+
+#ifdef __WIN32__
+    static int s_linesPerRotation = -1;
+    if ( s_linesPerRotation == -1 )
+    {
+        if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
+                                     &s_linesPerRotation, 0))
+        {
+            // this is not supposed to happen
+            wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
+
+            // the default is 3, so use it if SystemParametersInfo() failed
+            s_linesPerRotation = 3;
+        }
+    }
+#else // Win16
+    // no SystemParametersInfo() under Win16
+    static const int s_linesPerRotation = 3;
+#endif
+
+    event.m_linesPerAction = s_linesPerRotation;
+    return GetEventHandler()->ProcessEvent(event);
+
+#else
+    return FALSE;
+#endif
+}
+
+
 // ---------------------------------------------------------------------------
 // keyboard handling
 // ---------------------------------------------------------------------------
@@ -3332,7 +3476,7 @@ wxKeyEvent wxWindow::CreateKeyEvent(wxEventType evType,
 
 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
 // WM_KEYDOWN one
-bool wxWindow::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII)
+bool wxWindow::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
 {
     bool ctrlDown = FALSE;
 
@@ -3385,7 +3529,7 @@ bool wxWindow::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII)
     return FALSE;
 }
 
-bool wxWindow::HandleKeyDown(WXWORD wParam, WXLPARAM lParam)
+bool wxWindow::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
 {
     int id = wxCharCodeMSWToWX(wParam);
 
@@ -3407,7 +3551,7 @@ bool wxWindow::HandleKeyDown(WXWORD wParam, WXLPARAM lParam)
     return FALSE;
 }
 
-bool wxWindow::HandleKeyUp(WXWORD wParam, WXLPARAM lParam)
+bool wxWindow::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
 {
     int id = wxCharCodeMSWToWX(wParam);
 
@@ -3811,24 +3955,37 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
         win = wxFindWinFromHandle((WXHWND)hwnd);
         if ( !win )
         {
-            // the radiobox pointer is stored in GWL_USERDATA only under Win32
+            // all these hacks only work under Win32 anyhow
 #ifdef __WIN32__
+
+#if wxUSE_RADIOBOX
             // native radiobuttons return DLGC_RADIOBUTTON here and for any
             // wxWindow class which overrides WM_GETDLGCODE processing to
             // do it as well, win would be already non NULL
-            if ( ::SendMessage((HWND)hwnd, WM_GETDLGCODE,
-                               0, 0) & DLGC_RADIOBUTTON )
+            if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON )
             {
                 win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA);
             }
-            else
+            //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
+#endif // wxUSE_RADIOBOX
+
+            // spin control text buddy window should be mapped to spin ctrl
+            // itself so try it too
+#if wxUSE_SPINCTRL
+            if ( !win )
+            {
+                win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
+            }
+#endif // wxUSE_SPINCTRL
+
 #endif // Win32
+
+            if ( !win )
             {
                 // hwnd is not a wxWindow, try its parent next below
                 hwnd = ::GetParent(hwnd);
             }
         }
-        //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
     }
 
     while ( hwnd && !win )
@@ -3865,9 +4022,10 @@ void wxSetKeyboardHook(bool doIt)
     else
     {
         UnhookWindowsHookEx(wxTheKeyboardHook);
-        // avoids mingw warning about statement with no effect (FreeProcInstance
+
+        // avoids warning about statement with no effect (FreeProcInstance
         // doesn't do anything under Win32)
-#ifndef __GNUC__
+#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
         FreeProcInstance(wxTheKeyboardHookProc);
 #endif
     }
@@ -4047,6 +4205,7 @@ const char *wxGetMessageName(int message)
         case 0x0207: return "WM_MBUTTONDOWN";
         case 0x0208: return "WM_MBUTTONUP";
         case 0x0209: return "WM_MBUTTONDBLCLK";
+        case 0x020A: return "WM_MOUSEWHEEL";
         case 0x0210: return "WM_PARENTNOTIFY";
         case 0x0211: return "WM_ENTERMENULOOP";
         case 0x0212: return "WM_EXITMENULOOP";
@@ -4388,7 +4547,7 @@ static TEXTMETRIC wxGetTextMetrics(const wxWindow *win)
 
 // Find the wxWindow at the current mouse position, returning the mouse
 // position.
-wxWindow* wxFindWindowAtPointer(wxPoint& pt)
+wxWindow* wxFindWindowAtPointer(wxPoint& WXUNUSED(pt))
 {
     return wxFindWindowAtPoint(wxGetMousePosition());
 }