]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Fix FileTestCase to really test strings with embedded NULs.
[wxWidgets.git] / src / msw / window.cpp
index 332e309cde3eb473cb69b6c3179ac8db814d8175..e7f505bf7bf35ad56f6f2bd0c113ffada1e0f2eb 100644 (file)
     #define wxHAS_XBUTTON
 #endif
 
+#ifndef MAPVK_VK_TO_CHAR
+    #define MAPVK_VK_TO_CHAR 2
+#endif
+
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
@@ -3229,7 +3233,11 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                                             wParam,
                                             lParam | (KF_EXTENDED << 16)
                                           );
-                        processed = HandleWindowEvent(event);
+
+                        // Don't produce events without any valid character
+                        // code (even if this shouldn't normally happen...).
+                        if ( event.m_keyCode != WXK_NONE )
+                            processed = HandleWindowEvent(event);
                 }
             }
             if (message == WM_SYSKEYDOWN)  // Let Windows still handle the SYSKEYs
@@ -4917,7 +4925,8 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
 
 bool wxWindowMSW::MSWHasEraseBgHook() const
 {
-    return gs_eraseBgHooks.find(this) != gs_eraseBgHooks.end();
+    return gs_eraseBgHooks.find(const_cast<wxWindowMSW *>(this))
+                != gs_eraseBgHooks.end();
 }
 
 void wxWindowMSW::MSWSetEraseBgHook(wxWindow *child)
@@ -5628,28 +5637,65 @@ void wxWindowMSW::GenerateMouseLeave()
 // keyboard handling
 // ---------------------------------------------------------------------------
 
+namespace
+{
+
+// Implementation of InitAnyKeyEvent() which can also be used when there is no
+// associated window: this can happen for the wxEVT_CHAR_HOOK events created by
+// the global keyboard hook (e.g. the event might have happened in a non-wx
+// window).
 void
-wxWindowMSW::InitAnyKeyEvent(wxKeyEvent& event,
-                             WXWPARAM wParam,
-                             WXLPARAM lParam) const
+MSWInitAnyKeyEvent(wxKeyEvent& event,
+                   WXWPARAM wParam,
+                   WXLPARAM lParam,
+                   const wxWindowBase *win /* may be NULL */)
 {
-    event.SetId(GetId());
+    if ( win )
+    {
+        event.SetId(win->GetId());
+        event.SetEventObject(const_cast<wxWindowBase *>(win));
+    }
+    else // No associated window.
+    {
+        // Use wxID_ANY for compatibility with the old code even if wxID_NONE
+        // would arguably make more sense.
+        event.SetId(wxID_ANY);
+    }
+
     event.m_shiftDown = wxIsShiftDown();
     event.m_controlDown = wxIsCtrlDown();
     event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
 
-    event.SetEventObject(const_cast<wxWindow *>(this));
-
     event.m_rawCode = (wxUint32) wParam;
     event.m_rawFlags = (wxUint32) lParam;
 #ifndef __WXWINCE__
     event.SetTimestamp(::GetMessageTime());
 #endif
 
-    // translate the position to client coordinates
-    const wxPoint mousePos = ScreenToClient(wxGetMousePosition());
-    event.m_x = mousePos.x;
-    event.m_y = mousePos.y;
+    // Event coordinates must be in window client coordinates system which
+    // doesn't make sense if there is no window.
+    //
+    // We could use screen coordinates for such events but this would make the
+    // logic of the event handlers more complicated: you'd need to test for the
+    // event object and interpret the coordinates differently according to
+    // whether it's NULL or not so unless somebody really asks for this let's
+    // just avoid the issue.
+    if ( win )
+    {
+        const wxPoint mousePos = win->ScreenToClient(wxGetMousePosition());
+        event.m_x = mousePos.x;
+        event.m_y = mousePos.y;
+    }
+}
+
+} // anonymous namespace
+
+void
+wxWindowMSW::InitAnyKeyEvent(wxKeyEvent& event,
+                             WXWPARAM wParam,
+                             WXLPARAM lParam) const
+{
+    MSWInitAnyKeyEvent(event, wParam, lParam, this);
 }
 
 wxKeyEvent
@@ -6203,26 +6249,23 @@ int VKToWX(WXWORD vk, WXLPARAM lParam, wchar_t *uc)
                 // good idea.
                 wxk = WXK_NONE;
             }
-            else // Not a dead key.
-            {
-                // In any case return this as a Unicode character value.
-                if ( uc )
-                    *uc = wxk;
 
-                // For compatibility with the old non-Unicode code we continue
-                // returning key codes for Latin-1 characters directly
-                // (normally it would really only make sense to do it for the
-                // ASCII characters, not Latin-1 ones).
-                if ( wxk > 255 )
-                {
-                    // But for anything beyond this we can only return the key
-                    // value as a real Unicode character, not a wxKeyCode
-                    // because this enum values clash with Unicode characters
-                    // (e.g. WXK_LBUTTON also happens to be U+012C a.k.a.
-                    // "LATIN CAPITAL LETTER I WITH BREVE").
-                    wxk = WXK_NONE;
-                }
-                //
+            // In any case return this as a Unicode character value.
+            if ( uc )
+                *uc = wxk;
+
+            // For compatibility with the old non-Unicode code we continue
+            // returning key codes for Latin-1 characters directly
+            // (normally it would really only make sense to do it for the
+            // ASCII characters, not Latin-1 ones).
+            if ( wxk > 255 )
+            {
+                // But for anything beyond this we can only return the key
+                // value as a real Unicode character, not a wxKeyCode
+                // because this enum values clash with Unicode characters
+                // (e.g. WXK_LBUTTON also happens to be U+012C a.k.a.
+                // "LATIN CAPITAL LETTER I WITH BREVE").
+                wxk = WXK_NONE;
             }
             break;
 
@@ -6279,14 +6322,14 @@ int VKToWX(WXWORD vk, WXLPARAM lParam, wchar_t *uc)
                 // A simple alphanumeric key and the values of them coincide in
                 // Windows and wx for both ASCII and Unicode codes.
                 wxk = vk;
-
-                if ( uc )
-                    *uc = vk;
             }
             else // Something we simply don't know about at all.
             {
                 wxk = WXK_NONE;
             }
+
+            if ( uc )
+                *uc = vk;
     }
 
     return wxk;
@@ -6556,32 +6599,26 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
     DWORD hiWord = HIWORD(lParam);
     if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
     {
-        int id = wxMSWKeyboard::VKToWX(wParam, lParam);
-        if ( id >= WXK_START )
+        wchar_t uc;
+        int id = wxMSWKeyboard::VKToWX(wParam, lParam, &uc);
+        if ( id != WXK_NONE
+#if wxUSE_UNICODE
+                || static_cast<int>(uc) != WXK_NONE
+#endif // wxUSE_UNICODE
+                )
         {
+            const wxWindow * const win = wxGetActiveWindow();
+
             wxKeyEvent event(wxEVT_CHAR_HOOK);
-            if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
-                event.m_altDown = true;
+            MSWInitAnyKeyEvent(event, wParam, lParam, win);
 
-            event.SetEventObject(NULL);
             event.m_keyCode = id;
-            event.m_shiftDown = wxIsShiftDown();
-            event.m_controlDown = wxIsCtrlDown();
-#ifndef __WXWINCE__
-            event.SetTimestamp(::GetMessageTime());
-#endif
-            wxWindow *win = wxGetActiveWindow();
-            wxEvtHandler *handler;
-            if ( win )
-            {
-                handler = win->GetEventHandler();
-                event.SetId(win->GetId());
-            }
-            else
-            {
-                handler = wxTheApp;
-                event.SetId(wxID_ANY);
-            }
+#if wxUSE_UNICODE
+            event.m_uniChar = uc;
+#endif // wxUSE_UNICODE
+
+            wxEvtHandler * const handler = win ? win->GetEventHandler()
+                                               : wxTheApp;
 
             if ( handler && handler->ProcessEvent(event) )
             {