]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Ensure the tooltip has been created before enabling or setting the delay, or they...
[wxWidgets.git] / src / msw / window.cpp
index 1101fb474c0ad915f414d147009a6ad5598a9a00..827c12ec1685eced0d29544afc9f5d5d28f349ba 100644 (file)
     #define HAVE_TRACKMOUSEEVENT
 #endif // everything needed for TrackMouseEvent()
 
-// if this is set to 1, we use deferred window sizing to reduce flicker when
-// 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
 #ifdef __WXWINCE__
 extern wxMenu *wxCurrentPopupMenu;
 #endif
 
-#ifdef __WXWINCE__
-extern       wxChar *wxCanvasClassName;
-#else
-extern const wxChar *wxCanvasClassName;
-#endif
-
 // true if we had already created the std colour map, used by
 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT)
 static bool gs_hasStdCmap = false;
@@ -228,9 +212,9 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
                                    WPARAM wParam, LPARAM lParam);
 
 
-#ifdef  __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
     const wxChar *wxGetMessageName(int message);
-#endif  //__WXDEBUG__
+#endif  // wxDEBUG_LEVEL >= 2
 
 void wxRemoveHandleAssociation(wxWindowMSW *win);
 extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
@@ -281,12 +265,11 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent)
      */
     while ( parent && !parent->IsTopLevel() )
     {
-        LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+        LONG exStyle = wxGetWindowExStyle(parent);
         if ( !(exStyle & WS_EX_CONTROLPARENT) )
         {
             // force the parent to have this style
-            ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
-                            exStyle | WS_EX_CONTROLPARENT);
+            wxSetWindowExStyle(parent, exStyle | WS_EX_CONTROLPARENT);
         }
 
         parent = parent->GetParent();
@@ -525,19 +508,20 @@ bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
 void wxWindowMSW::Init()
 {
     // MSW specific
-    m_isBeingDeleted = false;
     m_oldWndProc = NULL;
     m_mouseInWindow = false;
     m_lastKeydownProcessed = false;
 
     m_hWnd = 0;
-    m_hDWP = 0;
 
     m_xThumbSize = 0;
     m_yThumbSize = 0;
 
+#if wxUSE_DEFERRED_SIZING
+    m_hDWP = 0;
     m_pendingPosition = wxDefaultPosition;
     m_pendingSize = wxDefaultSize;
+#endif // wxUSE_DEFERRED_SIZING
 
 #ifdef __POCKETPC__
     m_contextMenuEnabled = false;
@@ -547,7 +531,7 @@ void wxWindowMSW::Init()
 // Destructor
 wxWindowMSW::~wxWindowMSW()
 {
-    m_isBeingDeleted = true;
+    SendDestroyEvent();
 
 #ifndef __WXUNIVERSAL__
     // VS: make sure there's no wxFrame with last focus set to us:
@@ -590,6 +574,12 @@ wxWindowMSW::~wxWindowMSW()
 
 }
 
+/* static */
+const wxChar *wxWindowMSW::MSWGetRegisteredClassName()
+{
+    return wxApp::GetRegisteredClassName(_T("wxWindow"), COLOR_BTNFACE);
+}
+
 // real construction (Init() must have been called before!)
 bool wxWindowMSW::Create(wxWindow *parent,
                          wxWindowID id,
@@ -622,7 +612,8 @@ bool wxWindowMSW::Create(wxWindow *parent,
         msflags |= WS_VISIBLE;
     }
 
-    if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+    if ( !MSWCreate(MSWGetRegisteredClassName(),
+                    NULL, pos, size, msflags, exstyle) )
         return false;
 
     InheritAttributes();
@@ -639,13 +630,12 @@ void wxWindowMSW::SetFocus()
     HWND hWnd = GetHwnd();
     wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
 
-#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+#if !defined(__WXWINCE__)
     ::SetLastError(0);
 #endif
 
     if ( !::SetFocus(hWnd) )
     {
-#if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
         // was there really an error?
         DWORD dwRes = ::GetLastError();
         if ( dwRes )
@@ -656,7 +646,6 @@ void wxWindowMSW::SetFocus()
                 wxLogApiError(_T("SetFocus"), dwRes);
             }
         }
-#endif // Debug
     }
 }
 
@@ -755,6 +744,11 @@ wxWindowMSW::MSWShowWithEffect(bool show,
     if ( !s_pfnAnimateWindow )
         return Show(show);
 
+    // Show() has a side effect of sending a WM_SIZE to the window, which helps
+    // ensuring that it's laid out correctly, but AnimateWindow() doesn't do
+    // this so send the event ourselves
+    SendSizeEvent();
+
     // prepare to use AnimateWindow()
 
     if ( !timeout )
@@ -871,7 +865,11 @@ bool wxWindowMSW::SetFont(const wxFont& font)
     HWND hWnd = GetHwnd();
     if ( hWnd != 0 )
     {
-        WXHANDLE hFont = m_font.GetResourceHandle();
+        // note the use of GetFont() instead of m_font: our own font could have
+        // just been reset and in this case we need to change the font used by
+        // the native window to the default for this class, i.e. exactly what
+        // GetFont() returns
+        WXHANDLE hFont = GetFont().GetResourceHandle();
 
         wxASSERT_MSG( hFont, wxT("should have valid font") );
 
@@ -954,6 +952,9 @@ void wxWindowMSW::MSWUpdateUIState(int action, int state)
 // scrolling stuff
 // ---------------------------------------------------------------------------
 
+namespace
+{
+
 inline int GetScrollPosition(HWND hWnd, int wOrient)
 {
 #ifdef __WXMICROWIN__
@@ -969,12 +970,19 @@ inline int GetScrollPosition(HWND hWnd, int wOrient)
 #endif
 }
 
+inline UINT WXOrientToSB(int orient)
+{
+    return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
+}
+
+} // anonymous namespace
+
 int wxWindowMSW::GetScrollPos(int orient) const
 {
     HWND hWnd = GetHwnd();
     wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
 
-    return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
+    return GetScrollPosition(hWnd, WXOrientToSB(orient));
 }
 
 // This now returns the whole range, not just the number
@@ -985,15 +993,9 @@ int wxWindowMSW::GetScrollRange(int orient) const
     HWND hWnd = GetHwnd();
     if ( !hWnd )
         return 0;
-#if 0
-    ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
-                     &minPos, &maxPos);
-#endif
     WinStruct<SCROLLINFO> scrollInfo;
     scrollInfo.fMask = SIF_RANGE;
-    if ( !::GetScrollInfo(hWnd,
-                          orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
-                          &scrollInfo) )
+    if ( !::GetScrollInfo(hWnd, WXOrientToSB(orient), &scrollInfo) )
     {
         // Most of the time this is not really an error, since the return
         // value can also be zero when there is no scrollbar yet.
@@ -1026,8 +1028,7 @@ void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
         info.fMask |= SIF_DISABLENOSCROLL;
     }
 
-    ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
-                    &info, refresh);
+    ::SetScrollInfo(hWnd, WXOrientToSB(orient), &info, refresh);
 }
 
 // New function that will replace some of the above.
@@ -1037,28 +1038,37 @@ void wxWindowMSW::SetScrollbar(int orient,
                                int range,
                                bool refresh)
 {
+    // We have to set the variables here to make them valid in events
+    // triggered by ::SetScrollInfo()
+    *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
+
+    HWND hwnd = GetHwnd();
+    if ( !hwnd )
+        return;
+
     WinStruct<SCROLLINFO> info;
-    info.nPage = pageSize;
-    info.nMin = 0;              // range is nMax - nMin + 1
-    info.nMax = range - 1;      //  as both nMax and nMax are inclusive
-    info.nPos = pos;
+    if ( range != -1 )
+    {
+        info.nPage = pageSize;
+        info.nMin = 0;              // range is nMax - nMin + 1
+        info.nMax = range - 1;      //  as both nMax and nMax are inclusive
+        info.nPos = pos;
+
+        // enable the scrollbar if it had been disabled before by specifying
+        // SIF_DISABLENOSCROLL below: as we can't know whether this had been
+        // done or not just do it always
+        ::EnableScrollBar(hwnd, WXOrientToSB(orient), ESB_ENABLE_BOTH);
+    }
+    //else: leave all the fields to be 0
+
     info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
-    if ( HasFlag(wxALWAYS_SHOW_SB) )
+    if ( HasFlag(wxALWAYS_SHOW_SB) || range == -1 )
     {
         // disable scrollbar instead of removing it then
         info.fMask |= SIF_DISABLENOSCROLL;
     }
 
-    HWND hWnd = GetHwnd();
-    if ( hWnd )
-    {
-        // 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);
-    }
+    ::SetScrollInfo(hwnd, WXOrientToSB(orient), &info, refresh);
 }
 
 void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
@@ -1133,10 +1143,10 @@ void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
 #ifdef __WXWINCE__
     wxUnusedVar(dir);
 #else
-    const HWND hwnd = GetHwnd();
-    wxCHECK_RET( hwnd, _T("layout direction must be set after window creation") );
+    wxCHECK_RET( GetHwnd(),
+                 _T("layout direction must be set after window creation") );
 
-    LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
+    LONG styleOld = wxGetWindowExStyle(this);
 
     LONG styleNew = styleOld;
     switch ( dir )
@@ -1156,7 +1166,7 @@ void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
 
     if ( styleNew != styleOld )
     {
-        ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
+        wxSetWindowExStyle(this, styleNew);
     }
 #endif
 }
@@ -1166,12 +1176,10 @@ wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
 #ifdef __WXWINCE__
     return wxLayout_Default;
 #else
-    const HWND hwnd = GetHwnd();
-    wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+    wxCHECK_MSG( GetHwnd(), wxLayout_Default, _T("invalid window") );
 
-    return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
-                ? wxLayout_RightToLeft
-                : wxLayout_LeftToRight;
+    return wxHasWindowExStyle(this, WS_EX_LAYOUTRTL) ? wxLayout_RightToLeft
+                                                     : wxLayout_LeftToRight;
 #endif
 }
 
@@ -1270,36 +1278,12 @@ void wxWindowMSW::DissociateHandle()
 bool wxCheckWindowWndProc(WXHWND hWnd,
                           WXFARPROC WXUNUSED(wndProc))
 {
-// 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()
+    const wxString str(wxGetWindowClass(hWnd));
 
-#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;
-    extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
-    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
-    else
-        return false;
+    // TODO: get rid of wxTLWHiddenParent special case (currently it's not
+    //       registered by wxApp but using ad hoc code in msw/toplevel.cpp);
+    //       there is also a hidden window class used by sockets &c
+    return wxApp::IsRegisteredClassName(str) || str == _T("wxTLWHiddenParent");
 }
 
 // ----------------------------------------------------------------------------
@@ -1382,14 +1366,14 @@ void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
     }
 
     // and the extended style
-    long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+    long exstyleReal = wxGetWindowExStyle(this);
 
     if ( exstyle != exstyleOld )
     {
         exstyleReal &= ~exstyleOld;
         exstyleReal |= exstyle;
 
-        ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
+        wxSetWindowExStyle(this, exstyleReal);
 
         // ex style changes don't take effect without calling SetWindowPos
         callSWP = true;
@@ -1597,7 +1581,7 @@ bool wxWindowMSW::Reparent(wxWindowBase *parent)
     ::SetParent(hWndChild, hWndParent);
 
 #ifndef __WXWINCE__
-    if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
+    if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
     {
         EnsureParentHasControlParentStyle(GetParent());
     }
@@ -1769,11 +1753,11 @@ void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
 
 bool wxWindowMSW::IsSizeDeferred() const
 {
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
     if ( m_pendingPosition != wxDefaultPosition ||
          m_pendingSize     != wxDefaultSize )
         return true;
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
 
     return false;
 }
@@ -1781,7 +1765,7 @@ bool wxWindowMSW::IsSizeDeferred() const
 // Get total size
 void wxWindowMSW::DoGetSize(int *x, int *y) const
 {
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
     // if SetSize() had been called at wx level but not realized at Windows
     // level yet (i.e. EndDeferWindowPos() not called), we still should return
     // the new and not the old position to the other wx code
@@ -1793,7 +1777,7 @@ void wxWindowMSW::DoGetSize(int *x, int *y) const
             *y = m_pendingSize.y;
     }
     else // use current size
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
     {
         RECT rect = wxGetWindowRect(GetHwnd());
 
@@ -1807,7 +1791,7 @@ 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 wxUSE_DEFERRED_SIZING
     if ( m_pendingSize != wxDefaultSize )
     {
         // we need to calculate the client size corresponding to pending size
@@ -1825,7 +1809,7 @@ void wxWindowMSW::DoGetClientSize(int *x, int *y) const
             *y = rect.bottom - rect.top;
     }
     else
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
     {
         RECT rect = wxGetClientRect(GetHwnd());
 
@@ -1926,7 +1910,7 @@ void wxWindowMSW::DoClientToScreen(int *x, int *y) const
 bool
 wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
 {
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
     // if our parent had prepared a defer window handle for us, use it (unless
     // we are a top level window)
     wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
@@ -1956,13 +1940,13 @@ wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
     }
 
     // otherwise (or if deferring failed) move the window in place immediately
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
     if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
     {
         wxLogLastError(wxT("MoveWindow"));
     }
 
-    // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
+    // if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move,
     // ignored otherwise
     return false;
 }
@@ -1978,10 +1962,15 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
 
     if ( DoMoveSibling(m_hWnd, x, y, width, height) )
     {
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
         m_pendingPosition = wxPoint(x, y);
         m_pendingSize = wxSize(width, height);
-#endif // USE_DEFERRED_SIZING
+    }
+    else // window was moved immediately, without deferring it
+    {
+        m_pendingPosition = wxDefaultPosition;
+        m_pendingSize = wxDefaultSize;
+#endif // wxUSE_DEFERRED_SIZING
     }
 }
 
@@ -2008,6 +1997,12 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
          width == currentW && height == currentH &&
             !(sizeFlags & wxSIZE_FORCE) )
     {
+        if (sizeFlags & wxSIZE_FORCE_EVENT)
+        {
+            wxSizeEvent event( wxSize(width,height), GetId() );
+            event.SetEventObject( this );
+            HandleWindowEvent( event );
+        }
         return;
     }
 
@@ -2541,8 +2536,7 @@ bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* msg)
         {
             wxWindow * const win = node->GetData();
             if ( win->CanAcceptFocus() &&
-                    !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
-                        WS_EX_CONTROLPARENT) )
+                    !wxHasWindowExStyle(win, WS_EX_CONTROLPARENT) )
             {
                 // it shouldn't hang...
                 canSafelyCallIsDlgMsg = true;
@@ -2651,12 +2645,13 @@ wxWindowCreationHook::~wxWindowCreationHook()
 // Main window proc
 LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-    // trace all messages - useful for the debugging
-#ifdef __WXDEBUG__
+    // trace all messages: useful for the debugging but noticeably slows down
+    // the code so don't do it by default
+#if wxDEBUG_LEVEL >= 2
     wxLogTrace(wxTraceMessages,
                wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"),
                wxGetMessageName(message), hWnd, (long)wParam, lParam);
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
 
     wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
 
@@ -3413,12 +3408,12 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                     rc.result = MSWDefWindowProc(message, wParam, lParam);
                     processed = true;
 
-                    // now alter the client size making room for drawing a themed border
-                    NCCALCSIZE_PARAMS *csparam = NULL;
+                    // now alter the client size making room for drawing a
+                    // themed border
                     RECT *rect;
                     if ( wParam )
                     {
-                        csparam = (NCCALCSIZE_PARAMS *)lParam;
+                        NCCALCSIZE_PARAMS *csparam = (NCCALCSIZE_PARAMS *)lParam;
                         rect = &csparam->rgrc[0];
                     }
                     else
@@ -3508,10 +3503,10 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 
     if ( !processed )
     {
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
         wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
                    wxGetMessageName(message));
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
         rc.result = MSWDefWindowProc(message, wParam, lParam);
     }
 
@@ -3535,20 +3530,24 @@ void wxAssociateWinWithHandle(HWND hwnd, wxWindowMSW *win)
     wxCHECK_RET( hwnd != (HWND)NULL,
                  wxT("attempt to add a NULL hwnd to window list ignored") );
 
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
     WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
     if ( i != gs_windowHandles.end() )
     {
         if ( i->second != win )
         {
-            wxLogDebug(wxT("HWND %p already associated with another window (%s)"),
-                       hwnd, win->GetClassInfo()->GetClassName());
+            wxFAIL_MSG(
+                wxString::Format(
+                    wxT("HWND %p already associated with another window (%s)"),
+                    hwnd, win->GetClassInfo()->GetClassName()
+                )
+            );
         }
         //else: this actually happens currently because we associate the window
         //      with its HWND during creation (if we create it) and also when
         //      SubclassWin() is called later, this is ok
     }
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL
 
     gs_windowHandles[hwnd] = (wxWindow *)win;
 }
@@ -3675,6 +3674,11 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     // especially for wxTLWs
     wxCHECK_MSG( !m_hWnd, true, "window can't be recreated" );
 
+    // this can happen if this function is called using the return value of
+    // wxApp::GetRegisteredClassName() which failed
+    wxCHECK_MSG( wclass, false, "failed to register window class?" );
+
+
     // choose the position/size for the new window
     int x, y, w, h;
     (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
@@ -3689,7 +3693,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     wxString className(wclass);
     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
     {
-        className += wxT("NR");
+        className += wxApp::GetNoRedrawClassSuffix();
     }
 
     // do create the window
@@ -3840,8 +3844,7 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
         // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
         // to copy the string we have into the buffer
         static wxChar buf[513];
-        wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
-        buf[WXSIZEOF(buf) - 1] = _T('\0');
+        wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
         ttText->lpszText = buf;
     }
 
@@ -3946,8 +3949,6 @@ bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED_IN_WINCE(cs),
 
 bool wxWindowMSW::HandleDestroy()
 {
-    SendDestroyEvent();
-
     // delete our drop target if we've got one
 #if wxUSE_DRAG_AND_DROP
     if ( m_dropTarget != NULL )
@@ -4097,7 +4098,6 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
         ::DragQueryFile(hFilesInfo, wIndex,
                         wxStringBuffer(files[wIndex], len), len);
     }
-    DragFinish (hFilesInfo);
 
     wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
     event.SetEventObject(this);
@@ -4107,6 +4107,8 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
     event.m_pos.x = dropPoint.x;
     event.m_pos.y = dropPoint.y;
 
+    DragFinish(hFilesInfo);
+
     return HandleWindowEvent(event);
 #endif
 }
@@ -4257,21 +4259,22 @@ bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
 
 bool wxWindowMSW::IsDoubleBuffered() const
 {
-    const wxWindowMSW *wnd = this;
-    do {
-        long style = ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE);
-        if ( (style & WS_EX_COMPOSITED) != 0 )
+    for ( const wxWindowMSW *win = this; win; win = win->GetParent() )
+    {
+        if ( wxHasWindowExStyle(win, WS_EX_COMPOSITED) )
             return true;
-        wnd = wnd->GetParent();
-    } while ( wnd && !wnd->IsTopLevel() );
-        
+
+        if ( win->IsTopLevel() )
+            break;
+    }
+
     return false;
 }
 
 void wxWindowMSW::SetDoubleBuffered(bool on)
 {
     // Get the current extended style bits
-    long exstyle = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+    long exstyle = wxGetWindowExStyle(this);
 
     // Twiddle the bit as needed
     if ( on )
@@ -4280,7 +4283,7 @@ void wxWindowMSW::SetDoubleBuffered(bool on)
         exstyle &= ~WS_EX_COMPOSITED;
 
     // put it back
-    ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle);
+    wxSetWindowExStyle(this, exstyle);
 }
 
 // ---------------------------------------------------------------------------
@@ -4903,7 +4906,7 @@ bool wxWindowMSW::HandleExitSizeMove()
 
 bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
 {
-#if USE_DEFERRED_SIZING
+#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;
@@ -4930,7 +4933,7 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
                 useDefer = true;
         }
     }
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
 
     // update this window size
     bool processed = false;
@@ -4963,7 +4966,7 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
             processed = HandleWindowEvent(event);
     }
 
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
     // and finally change the positions of all child windows at once
     if ( useDefer && m_hDWP )
     {
@@ -4985,12 +4988,11 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
               node;
               node = node->GetNext() )
         {
-            wxWindowMSW *child = node->GetData();
-            child->m_pendingPosition = wxDefaultPosition;
-            child->m_pendingSize = wxDefaultSize;
+            wxWindowMSW * const child = node->GetData();
+            child->MSWEndDeferWindowPos();
         }
     }
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
 
     return processed;
 }
@@ -5093,12 +5095,8 @@ bool wxWindowMSW::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
     // coming from a control to wxEVT_COMMAND_MENU_SELECTED
     if ( !control )
     {
-        // If no child window, it may be an accelerator, e.g. for a popup menu
-        // command
-
-        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
+        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
         event.SetEventObject(this);
-        event.SetId(id);
         event.SetInt(id);
 
         return HandleWindowEvent(event);
@@ -5299,20 +5297,16 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
             static bool s_initDone = false;
             if ( !s_initDone )
             {
-                wxLogNull noLog;
-
-                wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+                // see comment in wxApp::GetComCtl32Version() explaining the
+                // use of wxLoadedDLL
+                wxLoadedDLL dllComCtl32(_T("comctl32.dll"));
                 if ( dllComCtl32.IsLoaded() )
                 {
                     s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
-                        dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
+                        dllComCtl32.RawGetSymbol(_T("_TrackMouseEvent"));
                 }
 
                 s_initDone = true;
-
-                // notice that it's ok to unload comctl32.dll here as it won't
-                // be really unloaded, being still in use because we link to it
-                // statically too
             }
 
             if ( s_pfn_TrackMouseEvent )
@@ -5635,18 +5629,19 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
     return wxNOT_FOUND;
 }
 
-bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg )
+#endif // wxUSE_MENUS
+
+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_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 HandleWindowEvent(evt);
 }
-#endif // wxUSE_MENUS
 
 // ---------------------------------------------------------------------------
 // joystick
@@ -5797,8 +5792,7 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
             scrollInfo.fMask = SIF_TRACKPOS;
 
             if ( !::GetScrollInfo(GetHwnd(),
-                                  orientation == wxHORIZONTAL ? SB_HORZ
-                                                              : SB_VERT,
+                                  WXOrientToSB(orientation),
                                   &scrollInfo) )
             {
                 // Not necessarily an error, if there are no scrollbars yet.
@@ -6229,7 +6223,7 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
     // by code in msw/radiobox.cpp), for all the others we just search up the
     // window hierarchy
-    wxWindow *win = (wxWindow *)NULL;
+    wxWindow *win = NULL;
     if ( hwnd )
     {
         win = wxFindWinFromHandle(hwnd);
@@ -6287,28 +6281,8 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
 // in active frames and dialogs, regardless of where the focus is.
 static HHOOK wxTheKeyboardHook = 0;
-static FARPROC wxTheKeyboardHookProc = 0;
-int APIENTRY _EXPORT
-wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
-
-void wxSetKeyboardHook(bool doIt)
-{
-    if ( doIt )
-    {
-        wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
-        wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
-
-            GetCurrentThreadId()
-        //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
-            );
-    }
-    else
-    {
-        UnhookWindowsHookEx(wxTheKeyboardHook);
-    }
-}
 
-int APIENTRY _EXPORT
+int APIENTRY
 wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
 {
     DWORD hiWord = HIWORD(lParam);
@@ -6352,9 +6326,32 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
     return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
 }
 
+void wxSetKeyboardHook(bool doIt)
+{
+    if ( doIt )
+    {
+        wxTheKeyboardHook = ::SetWindowsHookEx
+                              (
+                                WH_KEYBOARD,
+                                (HOOKPROC)wxKeyboardHook,
+                                NULL,   // must be NULL for process hook
+                                ::GetCurrentThreadId()
+                              );
+        if ( !wxTheKeyboardHook )
+        {
+            wxLogLastError(_T("SetWindowsHookEx(wxKeyboardHook)"));
+        }
+    }
+    else // uninstall
+    {
+        if ( wxTheKeyboardHook )
+            ::UnhookWindowsHookEx(wxTheKeyboardHook);
+    }
+}
+
 #endif // !__WXMICROWIN__
 
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
 const wxChar *wxGetMessageName(int message)
 {
     switch ( message )
@@ -6512,6 +6509,10 @@ const wxChar *wxGetMessageName(int message)
         case 0x0120: return wxT("WM_MENUCHAR");
         case 0x0121: return wxT("WM_ENTERIDLE");
 
+        case 0x0127: return wxT("WM_CHANGEUISTATE");
+        case 0x0128: return wxT("WM_UPDATEUISTATE");
+        case 0x0129: return wxT("WM_QUERYUISTATE");
+
         case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
         case 0x0133: return wxT("WM_CTLCOLOREDIT");
         case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
@@ -6823,7 +6824,7 @@ const wxChar *wxGetMessageName(int message)
             return s_szBuf.c_str();
     }
 }
-#endif //__WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
 
 static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
 {