]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
fix for handling TAB presses in readonly text controls
[wxWidgets.git] / src / msw / window.cpp
index 36162cb9a9be5fc03a20a1f3b8468ebb750efb90..07d4a17190f9ac956421f2bc1508111e0758c56f 100644 (file)
@@ -318,6 +318,8 @@ void wxWindowMSW::Init()
     m_mouseInWindow = FALSE;
     m_lastKeydownProcessed = FALSE;
 
+    m_childrenDisabled = NULL;
+
     // wxWnd
     m_hMenu = 0;
 
@@ -378,6 +380,8 @@ wxWindowMSW::~wxWindowMSW()
         // remove hWnd <-> wxWindow association
         wxRemoveHandleAssociation(this);
     }
+
+    delete m_childrenDisabled;
 }
 
 // real construction (Init() must have been called before!)
@@ -430,10 +434,7 @@ bool wxWindowMSW::Create(wxWindow *parent,
         msflags |= WS_VISIBLE;
     }
 
-    bool retVal = MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle);
-    if (retVal)
-        SetWindowLong( (HWND)m_hWnd, GWL_WNDPROC, (LONG)wxWndProc);
-    return retVal;
+    return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle);
 }
 
 // ---------------------------------------------------------------------------
@@ -501,19 +502,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;
 }
@@ -1028,35 +1068,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;
 }
 
 // ----------------------------------------------------------------------------
@@ -1437,11 +1463,15 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
 
 void wxWindowMSW::Update()
 {
+#ifdef __WXWINE__
+    ::UpdateWindow(GetHwnd());
+#else
     if ( !::UpdateWindow(GetHwnd()) )
     {
         wxLogLastError(_T("UpdateWindow"));
     }
-
+#endif
+    
 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
     // handler needs to be really drawn right now
@@ -2266,7 +2296,7 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w
     // trace all messages - useful for the debugging
 #ifdef __WXDEBUG__
     wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
-               wxGetMessageName(message), wParam, lParam);
+               wxGetMessageName(message), (long) wParam, lParam);
 #endif // __WXDEBUG__
 
     wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
@@ -2869,7 +2899,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__
@@ -3315,6 +3345,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);
 
@@ -4303,7 +4340,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) )
         {
@@ -4323,7 +4362,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
 
                 default:
                     ctrlDown = TRUE;
-                    id = id + 'a' - 1;
+                    break;
             }
         }
     }