]> git.saurik.com Git - wxWidgets.git/commitdiff
Use mouse position to find the item for selection events in wxMSW listbox.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 5 Jun 2010 22:58:05 +0000 (22:58 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 5 Jun 2010 22:58:05 +0000 (22:58 +0000)
Using LB_GETCARETINDEX doesn't work when the mouse is used to make selection
because it always returns the index of the last item, even if the mouse is
clicked below it, on an area without any listbox items. So use the mouse
position to find the item in this case but still use LB_GETCARETINDEX to find
the item when the keyboard is used.

This required adding a flag to wxListBox storing the kind of the last input
message that it received as there doesn't seem to be any way to determine how
the message was generated otherwise.

This code will be refactored/improved further in the next two commits.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64498 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/listbox.h
src/msw/listbox.cpp

index 38b1afcd158a889d3437634dfb07b84ba89e4cdd..9ccfa810a7684494b9f400658527afb824ec1d71 100644 (file)
@@ -149,6 +149,8 @@ public:
 
     virtual void OnInternalIdle();
 
+    virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
+
 protected:
     virtual wxSize DoGetBestClientSize() const;
 
@@ -190,6 +192,11 @@ private:
     // i.e. if we need to call SetHorizontalExtent() from OnInternalIdle()
     bool m_updateHorizontalExtent;
 
+    // flag set to true when we get a keyboard event and reset to false when we
+    // get a mouse one: this is used to find the correct item for the selection
+    // event
+    bool m_selectedByKeyboard;
+
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxListBox)
 };
 
index 8a2dd34eecf4a197f94cbd355dda4d6db0a1dae7..b8255628c84a7294c82516ae6c67d7cfa8dfac3c 100644 (file)
@@ -153,6 +153,7 @@ void wxListBox::Init()
 {
     m_noItems = 0;
     m_updateHorizontalExtent = false;
+    m_selectedByKeyboard = false;
 }
 
 bool wxListBox::Create(wxWindow *parent,
@@ -644,16 +645,28 @@ wxSize wxListBox::DoGetBestClientSize() const
 bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
 {
     wxEventType evtType;
-    int n;
+    int n = wxNOT_FOUND;
     if ( param == LBN_SELCHANGE )
     {
         if ( HasMultipleSelection() )
             return CalcAndSendEvent();
 
         evtType = wxEVT_COMMAND_LISTBOX_SELECTED;
-        n = SendMessage(GetHwnd(), LB_GETCARETINDEX, 0, 0);
 
-        // NB: conveniently enough, LB_ERR is the same as wxNOT_FOUND
+        if ( m_selectedByKeyboard )
+        {
+            // We shouldn't use the mouse position to find the item as mouse
+            // can be anywhere, ask the listbox itself. Notice that this can't
+            // be used when the item is selected using the mouse however as
+            // LB_GETCARETINDEX will always return a valid item, even if the
+            // mouse is clicked below all the items, which is why we find the
+            // item ourselves below in this case.
+            n = SendMessage(GetHwnd(), LB_GETCARETINDEX, 0, 0);
+        }
+        else
+        {
+            n = HitTest(ScreenToClient(wxGetMousePosition()));
+        }
     }
     else if ( param == LBN_DBLCLK )
     {
@@ -670,6 +683,20 @@ bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
     return n != wxNOT_FOUND && SendEvent(evtType, n, true /* selection */);
 }
 
+WXLRESULT
+wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
+    // Remember whether there was a keyboard or mouse event before
+    // LBN_SELCHANGE: this allows us to correctly determine the item affected
+    // by it in MSWCommand() above in any case.
+    if ( WM_KEYFIRST <= nMsg && nMsg <= WM_KEYLAST )
+        m_selectedByKeyboard = true;
+    else if ( WM_MOUSEFIRST <= nMsg && nMsg <= WM_MOUSELAST )
+        m_selectedByKeyboard = false;
+
+    return wxListBoxBase::MSWWindowProc(nMsg, wParam, lParam);
+}
+
 // ----------------------------------------------------------------------------
 // owner-drawn list boxes support
 // ----------------------------------------------------------------------------