]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
compilation fix
[wxWidgets.git] / src / msw / window.cpp
index e762e88e84693d3b6405a720b7aa54cc09b0b300..0374b532cd6710a535e9bd91be69aca928295888 100644 (file)
@@ -5,8 +5,8 @@
 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:     wxWindows license
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ===========================================================================
     #include "wx/dnd.h"
 #endif
 
+#if wxUSE_ACCESSIBILITY
+    #include "wx/access.h"
+    #include <oleacc.h>
+    #ifndef WM_GETOBJECT
+        #define WM_GETOBJECT 0x003D
+    #endif
+    #ifndef OBJID_CLIENT
+        #define OBJID_CLIENT 0xFFFFFFFC
+    #endif
+#endif
+
 #include "wx/menuitem.h"
 #include "wx/log.h"
 
 
 #ifndef VK_OEM_1
     #define VK_OEM_1        0xBA
-    #define VK_OEM_PLUS     0xBB
-    #define VK_OEM_COMMA    0xBC
-    #define VK_OEM_MINUS    0xBD
-    #define VK_OEM_PERIOD   0xBE
     #define VK_OEM_2        0xBF
     #define VK_OEM_3        0xC0
     #define VK_OEM_4        0xDB
     #define VK_OEM_7        0xDE
 #endif
 
+#ifndef VK_OEM_COMMA
+    #define VK_OEM_PLUS     0xBB
+    #define VK_OEM_COMMA    0xBC
+    #define VK_OEM_MINUS    0xBD
+    #define VK_OEM_PERIOD   0xBE
+#endif
+
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
@@ -159,15 +173,25 @@ static bool gs_hasStdCmap = FALSE;
 // ---------------------------------------------------------------------------
 
 // the window proc for all our windows
+#ifdef __DIGITALMARS__
+extern "C" LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
+                                   WPARAM wParam, LPARAM lParam);
+#else
 LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
                                    WPARAM wParam, LPARAM lParam);
+#endif
+                                   
 
 #ifdef  __WXDEBUG__
     const char *wxGetMessageName(int message);
 #endif  //__WXDEBUG__
 
 void wxRemoveHandleAssociation(wxWindowMSW *win);
-void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+#ifdef __DIGITALMARS__
+extern "C" void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+#else
+extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+#endif
 wxWindow *wxFindWinFromHandle(WXHWND hWnd);
 
 // this magical function is used to translate VK_APPS key presses to right
@@ -312,14 +336,14 @@ void wxWindowMSW::Init()
     InitBase();
 
     // MSW specific
-    m_doubleClickAllowed = 0;
-
     m_isBeingDeleted = FALSE;
-    m_oldWndProc = 0;
+    m_oldWndProc = NULL;
     m_useCtl3D = FALSE;
     m_mouseInWindow = FALSE;
     m_lastKeydownProcessed = FALSE;
 
+    m_childrenDisabled = NULL;
+
     // wxWnd
     m_hMenu = 0;
 
@@ -348,12 +372,12 @@ wxWindowMSW::~wxWindowMSW()
     // 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);
+        wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
         if ( frame )
         {
             if ( frame->GetLastFocus() == this )
             {
-                frame->SetLastFocus((wxWindow*)NULL);
+                frame->SetLastFocus(NULL);
             }
             break;
         }
@@ -380,6 +404,8 @@ wxWindowMSW::~wxWindowMSW()
         // remove hWnd <-> wxWindow association
         wxRemoveHandleAssociation(this);
     }
+
+    delete m_childrenDisabled;
 }
 
 // real construction (Init() must have been called before!)
@@ -392,17 +418,6 @@ bool wxWindowMSW::Create(wxWindow *parent,
 {
     wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
 
-#if wxUSE_STATBOX
-    // wxGTK doesn't allow to create controls with static box as the parent so
-    // this will result in a crash when the program is ported to wxGTK - warn
-    // about it
-    //
-    // the correct solution is to create the controls as siblings of the
-    // static box
-    wxASSERT_MSG( !wxDynamicCast(parent, wxStaticBox),
-                  _T("wxStaticBox can't be used as a window parent!") );
-#endif // wxUSE_STATBOX
-
     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
         return FALSE;
 
@@ -500,19 +515,58 @@ bool wxWindowMSW::Enable(bool enable)
     if ( hWnd )
         ::EnableWindow(hWnd, (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 be reenabled too when you reenable the dialog!
-#if 0
-    wxWindowList::Node *node = GetChildren().GetFirst();
-    while ( node )
+    // the logic below doesn't apply to the top level windows -- otherwise
+    // showing a modal dialog would result in total greying out (and ungreying
+    // out later) of everything which would be really ugly
+    if ( IsTopLevel() )
+        return TRUE;
+
+    // when the parent is disabled, all of its children should be disabled as
+    // well but when it is enabled back, only those of the children which
+    // hadn't been already disabled in the beginning should be enabled again,
+    // so we have to keep the list of those children
+    for ( wxWindowList::Node *node = GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
     {
         wxWindow *child = node->GetData();
-        child->Enable(enable);
+        if ( child->IsTopLevel() )
+        {
+            // the logic below doesn't apply to top level children
+            continue;
+        }
 
-        node = node->GetNext();
+        if ( enable )
+        {
+            // enable the child back unless it had been disabled before us
+            if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) )
+                child->Enable();
+        }
+        else // we're being disabled
+        {
+            if ( child->IsEnabled() )
+            {
+                // disable it as children shouldn't stay enabled while the
+                // parent is not
+                child->Disable();
+            }
+            else // child already disabled, remember it
+            {
+                // have we created the list of disabled children already?
+                if ( !m_childrenDisabled )
+                    m_childrenDisabled = new wxWindowList;
+
+                m_childrenDisabled->Append(child);
+            }
+        }
+    }
+
+    if ( enable && m_childrenDisabled )
+    {
+        // we don't need this list any more, don't keep unused memory
+        delete m_childrenDisabled;
+        m_childrenDisabled = NULL;
     }
-#endif // 0
 
     return TRUE;
 }
@@ -645,11 +699,15 @@ void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const
 // scrolling stuff
 // ---------------------------------------------------------------------------
 
+// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT
+static inline int wxDirToWinStyle(int orient)
+{
+    return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
+}
+
 #if WXWIN_COMPATIBILITY
 void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh)
 {
-#if defined(__WIN95__)
-
     int range1 = range;
 
     // Try to adjust the range to cope with page size > 1
@@ -660,106 +718,31 @@ void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh)
         range1 += (pageSize - 1);
     }
 
-    SCROLLINFO info;
-    int dir;
-
-    if ( orient == wxHORIZONTAL ) {
-        dir = SB_HORZ;
-    } else {
-        dir = SB_VERT;
-    }
-
-    info.cbSize = sizeof(SCROLLINFO);
+    WinStruct<SCROLLINFO> info;
     info.nPage = pageSize; // Have to set this, or scrollbar goes awry
     info.nMin = 0;
     info.nMax = range1;
-    info.nPos = 0;
     info.fMask = SIF_RANGE | SIF_PAGE;
 
     HWND hWnd = GetHwnd();
     if ( hWnd )
-        ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
-    int wOrient;
-    if ( orient == wxHORIZONTAL )
-        wOrient = SB_HORZ;
-    else
-        wOrient = SB_VERT;
-
-    HWND hWnd = GetHwnd();
-    if ( hWnd )
-        ::SetScrollRange(hWnd, wOrient, 0, range, refresh);
-#endif
+        ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh);
 }
 
 void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh)
 {
-#if defined(__WIN95__)
-    SCROLLINFO info;
-    int dir;
-
-    if ( orient == wxHORIZONTAL ) {
-        dir = SB_HORZ;
-        m_xThumbSize = page;
-    } else {
-        dir = SB_VERT;
-        m_yThumbSize = page;
-    }
-
-    info.cbSize = sizeof(SCROLLINFO);
+    WinStruct<SCROLLINFO> info;
     info.nPage = page;
-    info.nMin = 0;
     info.fMask = SIF_PAGE;
 
     HWND hWnd = GetHwnd();
     if ( hWnd )
-        ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
-    if ( orient == wxHORIZONTAL )
-        m_xThumbSize = page;
-    else
-        m_yThumbSize = page;
-#endif
-}
-
-int wxWindowMSW::OldGetScrollRange(int orient) const
-{
-    int wOrient;
-    if ( orient == wxHORIZONTAL )
-        wOrient = SB_HORZ;
-    else
-        wOrient = SB_VERT;
-
-#if __WATCOMC__ && defined(__WINDOWS_386__)
-    short minPos, maxPos;
-#else
-    int minPos, maxPos;
-#endif
-    HWND hWnd = GetHwnd();
-    if ( hWnd )
-    {
-        ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos);
-#if defined(__WIN95__)
-        // Try to adjust the range to cope with page size > 1
-        // - a Windows API quirk
-        int pageSize = GetScrollPage(orient);
-        if ( pageSize > 1 )
-        {
-            maxPos -= (pageSize - 1);
-        }
-#endif
-        return maxPos;
-    }
-    else
-        return 0;
+        ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh);
 }
 
 int wxWindowMSW::GetScrollPage(int orient) const
 {
-    if ( orient == wxHORIZONTAL )
-        return m_xThumbSize;
-    else
-        return m_yThumbSize;
+    return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
 }
 
 #endif // WXWIN_COMPATIBILITY
@@ -775,61 +758,31 @@ inline int GetScrollPosition(HWND hWnd, int wOrient)
 
 int wxWindowMSW::GetScrollPos(int orient) const
 {
-    int wOrient;
-    if ( orient == wxHORIZONTAL )
-        wOrient = SB_HORZ;
-    else
-        wOrient = SB_VERT;
-
     HWND hWnd = GetHwnd();
     wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
 
-    return GetScrollPosition(hWnd, wOrient);
+    return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
 }
 
 // This now returns the whole range, not just the number
 // of positions that we can scroll.
 int wxWindowMSW::GetScrollRange(int orient) const
 {
-    int wOrient;
-    if ( orient == wxHORIZONTAL )
-        wOrient = SB_HORZ;
-    else
-        wOrient = SB_VERT;
-
-#if __WATCOMC__ && defined(__WINDOWS_386__)
-    short minPos, maxPos;
-#else
     int minPos, maxPos;
-#endif
     HWND hWnd = GetHwnd();
-    if ( hWnd )
-    {
-        ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos);
-#if defined(__WIN95__)
-        // Try to adjust the range to cope with page size > 1
-        // - a Windows API quirk
-        int pageSize = GetScrollThumb(orient);
-        if ( pageSize > 1 )
-        {
-            maxPos -= (pageSize - 1);
-        }
-        // October 10th: new range concept.
-        maxPos += pageSize;
-#endif
-
-        return maxPos;
-    }
-    else
+    if ( !hWnd )
         return 0;
+
+    ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
+                     &minPos, &maxPos);
+
+    // undo "range - 1" done in SetScrollbar()
+    return maxPos + 1;
 }
 
 int wxWindowMSW::GetScrollThumb(int orient) const
 {
-    if ( orient == wxHORIZONTAL )
-        return m_xThumbSize;
-    else
-        return m_yThumbSize;
+    return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
 }
 
 void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
@@ -837,77 +790,38 @@ void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
     HWND hWnd = GetHwnd();
     wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
 
-    int dir = orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
-
-#if defined(__WIN95__)
-    SCROLLINFO info;
-    info.cbSize = sizeof(SCROLLINFO);
+    WinStruct<SCROLLINFO> info;
     info.nPage = 0;
     info.nMin = 0;
     info.nPos = pos;
     info.fMask = SIF_POS;
 
-    ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else // !__WIN95__
-    ::SetScrollPos(hWnd, dir, pos, refresh);
-#endif // __WIN95__/!__WIN95__
+    ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
+                    &info, refresh);
 }
 
 // New function that will replace some of the above.
-void wxWindowMSW::SetScrollbar(int orient, int pos, int thumbVisible,
-                            int range, bool refresh)
-{
-#if defined(__WIN95__)
-    int oldRange = range - thumbVisible;
-
-    int range1 = oldRange;
-
-    // Try to adjust the range to cope with page size > 1
-    // - a Windows API quirk
-    int pageSize = thumbVisible;
-    if ( pageSize > 1 && range > 0)
-    {
-        range1 += (pageSize - 1);
-    }
-
-    SCROLLINFO info;
-    int dir;
-
-    if ( orient == wxHORIZONTAL ) {
-        dir = SB_HORZ;
-    } else {
-        dir = SB_VERT;
-    }
-
-    info.cbSize = sizeof(SCROLLINFO);
-    info.nPage = pageSize; // Have to set this, or scrollbar goes awry
-    info.nMin = 0;
-    info.nMax = range1;
+void wxWindowMSW::SetScrollbar(int orient,
+                               int pos,
+                               int pageSize,
+                               int range,
+                               bool refresh)
+{
+    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;
     info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
 
-    HWND hWnd = GetHwnd();
-    if ( hWnd )
-        ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
-    int wOrient;
-    if ( orient == wxHORIZONTAL )
-        wOrient = SB_HORZ;
-    else
-        wOrient = SB_VERT;
-
     HWND hWnd = GetHwnd();
     if ( hWnd )
     {
-        ::SetScrollRange(hWnd, wOrient, 0, range, FALSE);
-        ::SetScrollPos(hWnd, wOrient, pos, refresh);
-    }
-#endif
-    if ( orient == wxHORIZONTAL ) {
-        m_xThumbSize = thumbVisible;
-    } else {
-        m_yThumbSize = thumbVisible;
+        ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
+                        &info, refresh);
     }
+
+    *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
 }
 
 void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
@@ -993,7 +907,10 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd)
     }
     else
     {
-        // don't bother restoring it neither
+        // don't bother restoring it neither: this also makes it easy to
+        // implement IsOfStandardClass() method which returns TRUE for the
+        // standard controls and FALSE for the wxWindows own windows as it can
+        // simply check m_oldWndProc
         m_oldWndProc = NULL;
     }
 }
@@ -1024,35 +941,21 @@ void wxWindowMSW::UnsubclassWin()
 
 bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc)
 {
-#if wxUSE_UNICODE_MSLU
-    // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
-    //     because it doesn't return pointer to the real wnd proc but rather a handle
-    //     of a fake proc that does Unicode<->ANSI translation.
-    //
-    //     The hack bellow works, 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.
-    //
-    //     FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
-    //            with RegisterClass!!
-
-    if ( wxUsingUnicowsDll() )
+    // 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.
+    WNDCLASS cls;
+    if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
     {
-        static wxChar buffer[512];
-        WNDCLASS cls;
+        wxLogLastError(_T("GetClassInfo"));
 
-        ::GetClassName((HWND)hWnd, buffer, 512);
-        ::GetClassInfo(wxGetInstance(), buffer, &cls);
-        return wndProc == (WXFARPROC)cls.lpfnWndProc;
-    }
-    else
-#endif
-    {
-        return wndProc == (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC);
+        return FALSE;
     }
+
+    return wndProc == (WXFARPROC)cls.lpfnWndProc;
 }
 
 // ----------------------------------------------------------------------------
@@ -1116,7 +1019,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags)
 WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
 {
     // translate the style
-    WXDWORD style = WS_CHILD;
+    WXDWORD style = WS_CHILD | WS_VISIBLE;
 
     if ( flags & wxCLIP_CHILDREN )
         style |= WS_CLIPCHILDREN;
@@ -1125,9 +1028,24 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
         style |= WS_CLIPSIBLINGS;
 
     wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
-    if ( border != wxBORDER_NONE && border != wxBORDER_DEFAULT )
+    
+    // Check if we want to automatically give it a sunken style.
+    // Note than because 'sunken' actually maps to WS_EX_CLIENTEDGE, which
+    // is a more neutral term, we don't necessarily get a sunken effect in
+    // Windows XP. Instead we get the appropriate style for the theme.
+
+    if (border == wxBORDER_DEFAULT && wxTheApp->GetAuto3D() && 
+        GetParent() && (GetParent()->IsKindOf(CLASSINFO(wxPanel)) ||
+                        GetParent()->IsKindOf(CLASSINFO(wxDialog))) &&
+        ((GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
+    {
+        border = (wxBorder)((flags & wxBORDER_MASK) | wxBORDER_SUNKEN);
+    }   
+    
+    // Only give it WS_BORDER for wxBORDER_SIMPLE
+    if (border & wxBORDER_SIMPLE)
         style |= WS_BORDER;
-
+    
     // now deal with ext style if the caller wants it
     if ( exstyle )
     {
@@ -1136,7 +1054,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
         if ( flags & wxTRANSPARENT_WINDOW )
             *exstyle |= WS_EX_TRANSPARENT;
 
-        switch ( flags & wxBORDER_MASK )
+        switch ( border )
         {
             default:
                 wxFAIL_MSG( _T("unknown border style") );
@@ -1152,11 +1070,12 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
                 break;
 
             case wxBORDER_RAISED:
-                *exstyle |= WS_EX_WINDOWEDGE;
+                *exstyle |= WS_EX_DLGMODALFRAME;
                 break;
 
             case wxBORDER_SUNKEN:
                 *exstyle |= WS_EX_CLIENTEDGE;
+                style &= ~WS_BORDER;
                 break;
 
             case wxBORDER_DOUBLE:
@@ -1164,109 +1083,20 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
                 break;
         }
 
+        // wxUniv doesn't use Windows dialog navigation functions at all
+#ifndef __WXUNIVERSAL__
         // to make the dialog navigation work with the nested panels we must
-        // use this style but, unfortunately, it hangs NT4 in some situations
-        // so we shouldn't use it -- even though it means that keyboard accels
-        // in, e.g. wxWizard, don't work
-#if 0
-        if ( flags & wxTAB_TRAVERSAL )
+        // use this style (top level windows such as dialogs don't need it)
+        if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
         {
             *exstyle |= WS_EX_CONTROLPARENT;
         }
-#endif // 0
+#endif // __WXUNIVERSAL__
     }
 
     return style;
 }
 
-// Make a Windows extended style from the given wxWindows window style
-WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders)
-{
-    WXDWORD exStyle = 0;
-    if ( style & wxTRANSPARENT_WINDOW )
-        exStyle |= WS_EX_TRANSPARENT;
-
-    if ( !eliminateBorders )
-    {
-        if ( style & wxSUNKEN_BORDER )
-            exStyle |= WS_EX_CLIENTEDGE;
-        if ( style & wxDOUBLE_BORDER )
-            exStyle |= WS_EX_DLGMODALFRAME;
-#if defined(__WIN95__)
-        if ( style & wxRAISED_BORDER )
-            // 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
-    }
-
-    return exStyle;
-}
-
-// Determines whether native 3D effects or CTL3D should be used,
-// applying a default border style if required, and returning an extended
-// style to pass to CreateWindowEx.
-WXDWORD wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle,
-                                        bool *want3D) const
-{
-    // If matches certain criteria, then assume no 3D effects
-    // unless specifically requested (dealt with in MakeExtendedStyle)
-    if ( !GetParent()
-#if wxUSE_CONTROLS
-            || !IsKindOf(CLASSINFO(wxControl))
-#endif // wxUSE_CONTROLS
-            || (m_windowStyle & wxNO_BORDER) )
-    {
-        *want3D = FALSE;
-        return MakeExtendedStyle(m_windowStyle);
-    }
-
-    // Determine whether we should be using 3D effects or not.
-    bool nativeBorder = FALSE; // by default, we don't want a Win95 effect
-
-    // 1) App can specify global 3D effects
-    *want3D = wxTheApp->GetAuto3D();
-
-    // 2) If the parent is being drawn with user colours, or simple border specified,
-    // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
-    if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) || (m_windowStyle & wxSIMPLE_BORDER) )
-        *want3D = FALSE;
-
-    // 3) Control can override this global setting by defining
-    // a border style, e.g. wxSUNKEN_BORDER
-    if ( m_windowStyle & wxSUNKEN_BORDER  )
-        *want3D = TRUE;
-
-    // 4) If it's a special border, CTL3D can't cope so we want a native border
-    if ( (m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
-        (m_windowStyle & wxSTATIC_BORDER) )
-    {
-        *want3D = TRUE;
-        nativeBorder = TRUE;
-    }
-
-    // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
-    // effects from extended style
-#if wxUSE_CTL3D
-    if ( *want3D )
-        nativeBorder = FALSE;
-#endif
-
-    DWORD exStyle = MakeExtendedStyle(m_windowStyle, !nativeBorder);
-
-    // If we want 3D, but haven't specified a border here,
-    // apply the default border style specified.
-    // TODO what about non-Win95 WIN32? Does it have borders?
-#if defined(__WIN95__) && !wxUSE_CTL3D
-    if ( defaultBorderStyle && (*want3D) && ! ((m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER ) ||
-        (m_windowStyle & wxSTATIC_BORDER) || (m_windowStyle & wxSIMPLE_BORDER) ))
-        exStyle |= defaultBorderStyle; // WS_EX_CLIENTEDGE;
-#endif
-
-    return exStyle;
-}
-
 #if WXWIN_COMPATIBILITY
 // If nothing defined for this, try the parent.
 // E.g. we may be a button loaded from a resource, with no callback function
@@ -1450,8 +1280,8 @@ void wxWindowMSW::Update()
 // drag and drop
 // ---------------------------------------------------------------------------
 
-#if wxUSE_DRAG_AND_DROP
 
+#if wxUSE_DRAG_AND_DROP
 void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
 {
     if ( m_dropTarget != 0 ) {
@@ -1463,7 +1293,6 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
     if ( m_dropTarget != 0 )
         m_dropTarget->Register(m_hWnd);
 }
-
 #endif // wxUSE_DRAG_AND_DROP
 
 // old style file-manager drag&drop support: we retain the old-style
@@ -1486,7 +1315,7 @@ void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
     wxWindowBase::DoSetToolTip(tooltip);
 
     if ( m_tooltip )
-        m_tooltip->SetWindow(this);
+        m_tooltip->SetWindow((wxWindow *)this);
 }
 
 #endif // wxUSE_TOOLTIPS
@@ -1858,6 +1687,10 @@ static void wxYieldForCommandsOnly()
     {
         wxTheApp->DoMessage((WXMSG *)&msg);
     }
+
+    // If we retrieved a WM_QUIT, insert back into the message queue.
+    if (msg.message == WM_QUIT)
+        ::PostQuitMessage(0);
 }
 
 bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
@@ -1899,7 +1732,11 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
     if ( m_oldWndProc )
+#ifdef __DIGITALMARS__
+        return ::CallWindowProc( (FARPROC) m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
+#else
         return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
+#endif
     else
         return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
 }
@@ -1916,14 +1753,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
         // here we try to do all the job which ::IsDialogMessage() usually does
         // internally
 #if 1
-        bool bProcess = TRUE;
-        if ( msg->message != WM_KEYDOWN )
-            bProcess = FALSE;
-
-        if ( bProcess && (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN )
-            bProcess = FALSE;
-
-        if ( bProcess )
+        if ( msg->message == WM_KEYDOWN )
         {
             bool bCtrlDown = wxIsCtrlDown();
             bool bShiftDown = wxIsShiftDown();
@@ -1935,11 +1765,21 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
             if ( !bCtrlDown )
             {
                 lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
+
+                // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
+                // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
+                // it, of course, implies them
+                if ( lDlgCode & DLGC_WANTALLKEYS )
+                {
+                    lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS;
+                }
             }
 
             bool bForward = TRUE,
                  bWindowChange = FALSE;
 
+            // should we process this message specially?
+            bool bProcess = TRUE;
             switch ( msg->wParam )
             {
                 case VK_TAB:
@@ -2022,6 +1862,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
                                     // eat the Enter events sometimes
                                     return FALSE;
                                 }
+                                else if (!IsTopLevel())
+                                {
+                                    // if not a top level window, let parent
+                                    // handle it
+                                    return FALSE;
+                                }
                                 //else: treat Enter as TAB: pass to the next
                                 //      control as this is the best thing to do
                                 //      if the text doesn't handle Enter itself
@@ -2084,7 +1930,35 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
         // place edit control from being closed with Escape in a dialog
         if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE )
         {
-            if ( ::IsDialogMessage(GetHwnd(), msg) )
+            // ::IsDialogMessage() can enter in an infinite loop when the
+            // currently focused window is disabled or hidden and its parent
+            // has WS_EX_CONTROLPARENT style, so don't call it in this case
+            bool canSafelyCallIsDlgMsg = TRUE;
+
+            HWND hwndFocus = ::GetFocus();
+            while ( hwndFocus )
+            {
+                if ( !::IsWindowEnabled(hwndFocus) ||
+                        !::IsWindowVisible(hwndFocus) )
+                {
+                    // it would enter an infinite loop if we do this!
+                    canSafelyCallIsDlgMsg = FALSE;
+
+                    break;
+                }
+
+                if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
+                {
+                    // it's a top level window, don't go further -- e.g. even
+                    // if the parent of a dialog is disabled, this doesn't
+                    // break navigation inside the dialog
+                    break;
+                }
+
+                hwndFocus = ::GetParent(hwndFocus);
+            }
+
+            if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
             {
                 // IsDialogMessage() did something...
                 return TRUE;
@@ -2239,8 +2113,10 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w
 {
     // trace all messages - useful for the debugging
 #ifdef __WXDEBUG__
+#if wxUSE_LOG
     wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
-               wxGetMessageName(message), wParam, lParam);
+               wxGetMessageName(message), (long) wParam, lParam);
+#endif // wxUSE_LOG
 #endif // __WXDEBUG__
 
     wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
@@ -2423,28 +2299,42 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
                         break;
                 }
 
-                if (!processed)
+                if ( processed )
+                    break;
+
 #endif // __WXMICROWIN__
+                int x = GET_X_LPARAM(lParam),
+                    y = GET_Y_LPARAM(lParam);
+
+                // redirect the event to a static control if necessary by
+                // finding one under mouse
+                wxWindowMSW *win;
+                if ( GetCapture() == this )
                 {
-                    // VZ: why do we need it here? DefWindowProc() is supposed
-                    //     to do this for us anyhow
-                    if ( message == WM_LBUTTONDOWN && AcceptsFocus() )
-                        SetFocus();
+                    // but don't do it if the mouse is captured by this window
+                    // because then it should really get this event itself
+                    win = this;
+                }
+                else
+                {
+                    win = FindWindowForMouseEvent(this, &x, &y);
 
-                    int x = GET_X_LPARAM(lParam),
-                        y = GET_Y_LPARAM(lParam);
+                    // this should never happen
+                    wxCHECK_MSG( win, 0,
+                                 _T("FindWindowForMouseEvent() returned NULL") );
 
-                    // redirect the event to a static control if necessary
-                    if (this == GetCapture())
-                    {
-                        processed = HandleMouseEvent(message, x, y, wParam);
-                    }
-                    else
+                    // for the standard classes their WndProc sets the focus to
+                    // them anyhow and doing it from here results in some weird
+                    // problems, but for our windows we want them to acquire
+                    // focus when clicked
+                    if ( !win->IsOfStandardClass() )
                     {
-                        wxWindowMSW *win = FindWindowForMouseEvent(this, &x, &y); //TW:REQ:Univ
-                        processed = win->HandleMouseEvent(message, x, y, wParam);
+                        if ( message == WM_LBUTTONDOWN && win->AcceptsFocus() )
+                            win->SetFocus();
                     }
                 }
+
+                processed = win->HandleMouseEvent(message, x, y, wParam);
             }
             break;
 
@@ -2508,11 +2398,19 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
 #endif // defined(WM_DRAWITEM)
 
         case WM_GETDLGCODE:
-            if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+            if ( !IsOfStandardClass() )
             {
-                // want everything: i.e. all keys and WM_CHAR message
-                rc.result = DLGC_WANTARROWS | DLGC_WANTCHARS |
-                            DLGC_WANTTAB | DLGC_WANTMESSAGE;
+                // we always want to get the char events
+                rc.result = DLGC_WANTCHARS;
+
+                if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+                {
+                    // in fact, we want everything
+                    rc.result |= DLGC_WANTARROWS |
+                                 DLGC_WANTTAB |
+                                 DLGC_WANTALLKEYS;
+                }
+
                 processed = TRUE;
             }
             //else: get the dlg code from the DefWindowProc()
@@ -2526,71 +2424,73 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
             if ( m_lastKeydownProcessed )
             {
                 processed = TRUE;
-                break;
             }
 
-            switch ( wParam )
+            if ( !processed )
             {
-                // we consider these message "not interesting" to OnChar, so
-                // just don't do anything more with them
-                case VK_SHIFT:
-                case VK_CONTROL:
-                case VK_MENU:
-                case VK_CAPITAL:
-                case VK_NUMLOCK:
-                case VK_SCROLL:
-                    processed = TRUE;
-                    break;
-
-                // avoid duplicate messages to OnChar for these ASCII keys:
-                // they will be translated by TranslateMessage() and received
-                // in WM_CHAR
-                case VK_ESCAPE:
-                case VK_SPACE:
-                case VK_RETURN:
-                case VK_BACK:
-                case VK_TAB:
-                case VK_ADD:
-                case VK_SUBTRACT:
-                case VK_MULTIPLY:
-                case VK_DIVIDE:
-                case VK_OEM_1:
-                case VK_OEM_2:
-                case VK_OEM_3:
-                case VK_OEM_4:
-                case VK_OEM_5:
-                case VK_OEM_6:
-                case VK_OEM_7:
-                case VK_OEM_PLUS:
-                case VK_OEM_COMMA:
-                case VK_OEM_MINUS:
-                case VK_OEM_PERIOD:
-                    // but set processed to FALSE, not TRUE to still pass them
-                    // to the control's default window proc - otherwise
-                    // built-in keyboard handling won't work
-                    processed = FALSE;
+                switch ( wParam )
+                {
+                    // we consider these message "not interesting" to OnChar, so
+                    // just don't do anything more with them
+                    case VK_SHIFT:
+                    case VK_CONTROL:
+                    case VK_MENU:
+                    case VK_CAPITAL:
+                    case VK_NUMLOCK:
+                    case VK_SCROLL:
+                        processed = TRUE;
+                        break;
 
-                    break;
+                    // avoid duplicate messages to OnChar for these ASCII keys:
+                    // they will be translated by TranslateMessage() and received
+                    // in WM_CHAR
+                    case VK_ESCAPE:
+                    case VK_SPACE:
+                    case VK_RETURN:
+                    case VK_BACK:
+                    case VK_TAB:
+                    case VK_ADD:
+                    case VK_SUBTRACT:
+                    case VK_MULTIPLY:
+                    case VK_DIVIDE:
+                    case VK_OEM_1:
+                    case VK_OEM_2:
+                    case VK_OEM_3:
+                    case VK_OEM_4:
+                    case VK_OEM_5:
+                    case VK_OEM_6:
+                    case VK_OEM_7:
+                    case VK_OEM_PLUS:
+                    case VK_OEM_COMMA:
+                    case VK_OEM_MINUS:
+                    case VK_OEM_PERIOD:
+                        // but set processed to FALSE, not TRUE to still pass them
+                        // to the control's default window proc - otherwise
+                        // built-in keyboard handling won't work
+                        processed = FALSE;
+                        break;
 
 #ifdef VK_APPS
-                // special case of VK_APPS: treat it the same as right mouse
-                // click because both usually pop up a context menu
-                case VK_APPS:
-                    {
-                        WPARAM flags;
-                        int x, y;
+                    // special case of VK_APPS: treat it the same as right mouse
+                    // click because both usually pop up a context menu
+                    case VK_APPS:
+                        {
+                            WPARAM flags;
+                            int x, y;
 
-                        TranslateKbdEventToMouse(this, &x, &y, &flags);
-                        processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
-                    }
-                    break;
+                            TranslateKbdEventToMouse(this, &x, &y, &flags);
+                            processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
+                        }
+                        break;
 #endif // VK_APPS
 
-                default:
-                    // do generate a CHAR event
-                    processed = HandleChar((WORD)wParam, lParam);
-
+                    default:
+                        // do generate a CHAR event
+                        processed = HandleChar((WORD)wParam, lParam);
+                }
             }
+            if (message == WM_SYSKEYDOWN)  // Let Windows still handle the SYSKEYs
+                processed = FALSE;
             break;
 
         case WM_SYSKEYUP:
@@ -2742,6 +2642,20 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
             }
             break;
 
+#if wxUSE_ACCESSIBILITY
+        case WM_GETOBJECT:
+            {
+                //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
+                LPARAM dwObjId = (LPARAM) (DWORD) lParam;
+
+                if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible())
+                {
+                    return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
+                }
+                break;
+            }
+#endif
+
 #if defined(__WIN32__) && defined(WM_HELP)
         case WM_HELP:
             {
@@ -2789,14 +2703,30 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
                 processed = GetEventHandler()->ProcessEvent(evtCtx);
             }
             break;
+
+        case WM_MENUCHAR:
+            // we're only interested in our own menus, not MF_SYSMENU
+            if ( HIWORD(wParam) == MF_POPUP )
+            {
+                // handle menu chars for ownerdrawn menu items
+                int i = HandleMenuChar(toupper(LOWORD(wParam)), lParam);
+                if ( i != wxNOT_FOUND )
+                {
+                    rc.result = MAKELRESULT(i, MNC_EXECUTE);
+                    processed = TRUE;
+                }
+            }
+            break;
 #endif // __WIN32__
     }
 
     if ( !processed )
     {
 #ifdef __WXDEBUG__
+#if wxUSE_LOG
         wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
                    wxGetMessageName(message));
+#endif // wxUSE_LOG
 #endif // __WXDEBUG__
         rc.result = MSWDefWindowProc(message, wParam, lParam);
     }
@@ -2827,7 +2757,7 @@ void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
     if ( oldWin && (oldWin != win) )
     {
         wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
-                   hWnd, win->GetClassInfo()->GetClassName());
+                   (int) hWnd, win->GetClassInfo()->GetClassName());
     }
     else
 #endif // __WXDEBUG__
@@ -2916,7 +2846,7 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
 
 WXHWND wxWindowMSW::MSWGetParent() const
 {
-    return m_parent ? m_parent->GetHWND() : NULL;
+    return m_parent ? m_parent->GetHWND() : WXHWND(NULL);
 }
 
 bool wxWindowMSW::MSWCreate(const wxChar *wclass,
@@ -2932,20 +2862,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
 
     // controlId is menu handle for the top level windows, so set it to 0
     // unless we're creating a child window
-    int controlId;
-    if ( style & WS_CHILD )
-    {
-        controlId = GetId();
-
-        if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
-        {
-            style |= WS_CLIPSIBLINGS;
-        }
-    }
-    else // !child
-    {
-        controlId = 0;
-    }
+    int controlId = style & WS_CHILD ? GetId() : 0;
 
     // for each class "Foo" we have we also have "FooNR" ("no repaint") class
     // which is the same but without CS_[HV]REDRAW class styles so using it
@@ -2995,7 +2912,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
 // ---------------------------------------------------------------------------
 
 #ifdef __WIN95__
-// FIXME: VZ: I'm not sure at all that the order of processing is correct
+
 bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
 #ifndef __WXMICROWIN__
@@ -3003,12 +2920,19 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
     HWND hWnd = hdr->hwndFrom;
     wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd);
 
-    // is this one of our windows?
+    // if the control is one of our windows, let it handle the message itself
     if ( win )
     {
         return win->MSWOnNotify(idCtrl, lParam, result);
     }
 
+    // VZ: why did we do it? normally this is unnecessary and, besides, it
+    //     breaks the message processing for the toolbars because the tooltip
+    //     notifications were being forwarded to the toolbar child controls
+    //     (if it had any) before being passed to the toolbar itself, so in my
+    //     example the tooltip for the combobox was always shown instead of the
+    //     correct button tooltips
+#if 0
     // try all our children
     wxWindowList::Node *node = GetChildren().GetFirst();
     while ( node )
@@ -3021,32 +2945,78 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
         node = node->GetNext();
     }
+#endif // 0
 
-    // finally try this window too (catches toolbar case)
+    // by default, handle it ourselves
     return MSWOnNotify(idCtrl, lParam, result);
 #else // __WXMICROWIN__
     return FALSE;
 #endif
 }
 
+#if wxUSE_TOOLTIPS
+
+bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
+                                      WXLPARAM lParam,
+                                      const wxString& ttip)
+{
+    // I don't know why it happens, but the versions of comctl32.dll starting
+    // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
+    // this message is supposed to be sent to Unicode programs only) -- hence
+    // we need to handle it as well, otherwise no tooltips will be shown in
+    // this case
+
+    if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() )
+    {
+        // not a tooltip message or no tooltip to show anyhow
+        return FALSE;
+    }
+
+    LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
+
+#if !wxUSE_UNICODE
+    if ( code == (WXUINT) TTN_NEEDTEXTA )
+    {
+        // we pass just the pointer as we store the string internally anyhow
+        ttText->lpszText = (char *)ttip.c_str();
+    }
+    else // TTN_NEEDTEXTW
+#endif // !Unicode
+    {
+#if wxUSE_UNICODE
+        // in Unicode mode this is just what we need
+        ttText->lpszText = (wxChar *)ttip.c_str();
+#else // !Unicode
+        MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1,
+                            (wchar_t *)ttText->szText,
+                            sizeof(ttText->szText) / sizeof(wchar_t));
+#endif // Unicode/!Unicode
+    }
+
+    return TRUE;
+}
+
+#endif // wxUSE_TOOLTIPS
+
 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
-                           WXLPARAM lParam,
-                           WXLPARAM* WXUNUSED(result))
+                              WXLPARAM lParam,
+                              WXLPARAM* WXUNUSED(result))
 {
 #if wxUSE_TOOLTIPS
-    NMHDR* hdr = (NMHDR *)lParam;
-    if ( (int)hdr->code == TTN_NEEDTEXT && m_tooltip )
+    if ( m_tooltip )
     {
-        TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
-        ttt->lpszText = (wxChar *)m_tooltip->GetTip().c_str();
-
-        // processed
-        return TRUE;
+        NMHDR* hdr = (NMHDR *)lParam;
+        if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip()))
+        {
+            // processed
+            return TRUE;
+        }
     }
 #endif // wxUSE_TOOLTIPS
 
     return FALSE;
 }
+
 #endif // __WIN95__
 
 // ---------------------------------------------------------------------------
@@ -3094,8 +3064,33 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
 // window creation/destruction
 // ---------------------------------------------------------------------------
 
-bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
+bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
 {
+    // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
+    // parent as well as otherwise several Win32 functions using
+    // GetNextDlgTabItem() to iterate over all controls such as
+    // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
+    // all of them iterate over all the controls starting from the focus and
+    // stop iterating when they get back to the focus but unless all parents
+    // have WS_EX_CONTROLPARENT bit set, they would never get back to focus
+    if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
+    {
+        // there is no need to do anything for the top level windows
+        const wxWindow *parent = GetParent();
+        while ( parent && !parent->IsTopLevel() )
+        {
+            LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+            if ( !(exStyle & WS_EX_CONTROLPARENT) )
+            {
+                // force the parent to have this style
+                ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
+                                exStyle | WS_EX_CONTROLPARENT);
+            }
+
+            parent = parent->GetParent();
+        }
+    }
+
     // TODO: should generate this event from WM_NCCREATE
     wxWindowCreateEvent event((wxWindow *)this);
     (void)GetEventHandler()->ProcessEvent(event);
@@ -3107,8 +3102,7 @@ bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
 
 bool wxWindowMSW::HandleDestroy()
 {
-    wxWindowDestroyEvent event((wxWindow *)this);
-    (void)GetEventHandler()->ProcessEvent(event);
+    SendDestroyEvent();
 
     // delete our drop target if we've got one
 #if wxUSE_DRAG_AND_DROP
@@ -3194,6 +3188,13 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
     }
 #endif
 
+    // Don't send the event when in the process of being deleted.  This can
+    // only cause problems if the event handler tries to access the object.
+    if ( m_isBeingDeleted )
+    {
+        return FALSE;
+    }
+
     wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
     event.SetEventObject(this);
 
@@ -3225,7 +3226,9 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
 
 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
 {
-#ifndef __WXMICROWIN__
+#if defined (__WXMICROWIN__) 
+    return FALSE;
+#else // __WXMICROWIN__
     HDROP hFilesInfo = (HDROP) wParam;
 
     // Get the total number of files dropped
@@ -3260,11 +3263,13 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
     event.m_pos.y = dropPoint.y;
 
     return GetEventHandler()->ProcessEvent(event);
-#else // __WXMICROWIN__
-    return FALSE;
 #endif
 }
 
+#ifdef __DIGITALMARS__
+extern "C" HCURSOR wxGetCurrentBusyCursor();
+#endif
+
 bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
                                   short nHitTest,
                                   int WXUNUSED(mouseMsg))
@@ -3341,6 +3346,8 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
 
     if ( hcursor )
     {
+//        wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor);
+
         ::SetCursor(hcursor);
 
         // cursor set, stop here
@@ -3498,7 +3505,7 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
     if ( hWndPalChange != GetHWND() )
     {
         // check to see if we our our parents have a custom palette
-        wxWindow *win = this;
+        wxWindowMSW *win = this;
         while ( win && !win->HasCustomPalette() )
         {
             win = win->GetParent();
@@ -3547,7 +3554,7 @@ bool wxWindowMSW::HandleQueryNewPalette()
 
 #if wxUSE_PALETTE
     // check to see if we our our parents have a custom palette
-    wxWindow *win = this;
+    wxWindowMSW *win = this;
     while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent();
     if (win->HasCustomPalette()) {
         /* realize the palette to see whether redrawing is needed */
@@ -4182,7 +4189,9 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
     int id;
     if ( isASCII )
     {
-        // If 1 -> 26, translate to CTRL plus a letter.
+        // 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) )
         {
@@ -4202,7 +4211,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
 
                 default:
                     ctrlDown = TRUE;
-                    id = id + 'a' - 1;
+                    break;
             }
         }
     }
@@ -4218,9 +4227,18 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
     }
 
     wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam, wParam));
-    if ( ctrlDown )
+
+    // the alphanumeric keys produced by pressing AltGr+something on European
+    // keyboards have both Ctrl and Alt modifiers which may confuse the user
+    // code as, normally, keys with Ctrl and/or Alt don't result in anything
+    // alphanumeric, so pretend that there are no modifiers at all (the
+    // KEY_DOWN event would still have the correct modifiers if they're really
+    // needed)
+    if ( event.m_controlDown && event.m_altDown &&
+            (id >= 32 && id < 256) )
     {
-        event.m_controlDown = TRUE;
+        event.m_controlDown =
+        event.m_altDown = FALSE;
     }
 
     return GetEventHandler()->ProcessEvent(event);
@@ -4268,6 +4286,69 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
     return FALSE;
 }
 
+#ifdef __WIN32__
+
+int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
+{
+    const HMENU hmenu = (HMENU)lParam;
+
+    MENUITEMINFO mii;
+    wxZeroMemory(mii);
+    mii.cbSize = sizeof(MENUITEMINFO);
+    mii.fMask = MIIM_TYPE | MIIM_DATA;
+
+    // find if we have this letter in any owner drawn item
+    const int count = ::GetMenuItemCount(hmenu);
+    for ( int i = 0; i < count; i++ )
+    {
+        if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
+        {
+            if ( mii.fType == MFT_OWNERDRAW )
+            {
+                //  dwItemData member of the MENUITEMINFO is a
+                //  pointer to the associated wxMenuItem -- see the
+                //  menu creation code
+                wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
+
+                const wxChar *p = wxStrchr(item->GetText(), _T('&'));
+                while ( p++ )
+                {
+                    if ( *p == _T('&') )
+                    {
+                        // this is not the accel char, find the real one
+                        p = wxStrchr(p + 1, _T('&'));
+                    }
+                    else // got the accel char
+                    {
+                        // FIXME-UNICODE: this comparison doesn't risk to work
+                        // for non ASCII accelerator characters I'm afraid, but
+                        // what can we do?
+                        if ( wxToupper(*p) == chAccel )
+                        {
+                            return i;
+                        }
+                        else
+                        {
+                            // this one doesn't match
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        else // failed ot get the menu text?
+        {
+            // it's not fatal, so don't show error, but still log
+            // it
+            wxLogLastError(_T("GetMenuItemInfo"));
+        }
+    }
+
+    return wxNOT_FOUND;
+}
+
+#endif // __WIN32__
+
 // ---------------------------------------------------------------------------
 // joystick
 // ---------------------------------------------------------------------------
@@ -4410,9 +4491,7 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
         // be done only for these two SB_ events as they are the only one
         // carrying the scrollbar position)
         {
-            SCROLLINFO scrollInfo;
-            wxZeroMemory(scrollInfo);
-            scrollInfo.cbSize = sizeof(SCROLLINFO);
+            WinStruct<SCROLLINFO> scrollInfo;
             scrollInfo.fMask = SIF_TRACKPOS;
 
             if ( !::GetScrollInfo(GetHwnd(),
@@ -4560,6 +4639,12 @@ int wxCharCodeMSWToWX(int keySym)
         case VK_OEM_6:      id = ']'; break;
         case VK_OEM_7:      id = '\''; break;
 
+#ifdef VK_APPS
+        case VK_LWIN:       id = WXK_WINDOWS_LEFT; break;
+        case VK_RWIN:       id = WXK_WINDOWS_RIGHT; break;
+        case VK_APPS:       id = WXK_WINDOWS_MENU; break;
+#endif // VK_APPS defined
+
         default:
             id = 0;
     }
@@ -4749,7 +4834,7 @@ void wxSetKeyboardHook(bool doIt)
 
         // avoids warning about statement with no effect (FreeProcInstance
         // doesn't do anything under Win32)
-#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
+#if !defined(__WIN32__) && !defined(__NT__)
         FreeProcInstance(wxTheKeyboardHookProc);
 #endif
     }
@@ -5274,9 +5359,10 @@ static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
 
 // Find the wxWindow at the current mouse position, returning the mouse
 // position.
-wxWindow* wxFindWindowAtPointer(wxPoint& WXUNUSED(pt))
+wxWindow* wxFindWindowAtPointer(wxPoint& pt)
 {
-    return wxFindWindowAtPoint(wxGetMousePosition());
+    pt = wxGetMousePosition();
+    return wxFindWindowAtPoint(pt);
 }
 
 wxWindow* wxFindWindowAtPoint(const wxPoint& pt)