]> git.saurik.com Git - wxWidgets.git/commitdiff
Don't try to determine the clicked item ourselves in wxMSW wxListBox.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 9 Sep 2012 00:44:26 +0000 (00:44 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 9 Sep 2012 00:44:26 +0000 (00:44 +0000)
This doesn't work when the listbox is scrolled as the result of a click to
make the selected item fully visible and results in the index of the item
being off by 1 in the generated event which is a pretty serious problem.

Fix it by simply retrieving the item from the listbox itself, without doing
any hit testing. This seems to give the correct result in all cases and also
makes the code much simpler as we don't have to use 2 different ways of
finding the item depending on whether it was selected using the keyboard or
the mouse and makes it unnecessary to keep track of how the selection was done
completely, i.e. reverts r64498 which is not needed any more.

Closes #14635.

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

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

index 0d9982bab80879d9d063718270b621458e84694e..b687aac8d7e6e5ebef1aa8f1c4fdb35f83d1df24 100644 (file)
@@ -151,8 +151,6 @@ public:
 
     virtual void OnInternalIdle();
 
-    virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
-
 protected:
     virtual wxSize DoGetBestClientSize() const;
 
@@ -194,10 +192,6 @@ 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 c01c325a5cda0ca9c3174bd44d421eff079ea203..9f9720f39a10d802a212f5c283d2a41f372c6761 100644 (file)
@@ -84,7 +84,6 @@ void wxListBox::Init()
 {
     m_noItems = 0;
     m_updateHorizontalExtent = false;
-    m_selectedByKeyboard = false;
 }
 
 bool wxListBox::Create(wxWindow *parent,
@@ -582,28 +581,23 @@ wxSize wxListBox::DoGetBestClientSize() const
 bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
 {
     wxEventType evtType;
-    int n = wxNOT_FOUND;
     if ( param == LBN_SELCHANGE )
     {
         if ( HasMultipleSelection() )
             return CalcAndSendEvent();
 
         evtType = wxEVT_COMMAND_LISTBOX_SELECTED;
-
-        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 will be determined below from the mouse position
     }
     else if ( param == LBN_DBLCLK )
     {
+        // Clicking under the last item in the listbox generates double click
+        // event for the currently selected item which is rather surprising.
+        // Avoid the surprise by checking that we do have an item under mouse.
+        const DWORD pos = ::GetMessagePos();
+        const wxPoint pt(GET_X_LPARAM(pos), GET_Y_LPARAM(pos));
+        if ( HitTest(ScreenToClient(pt)) == wxNOT_FOUND )
+            return false;
+
         evtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED;
     }
     else
@@ -612,14 +606,7 @@ bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
         return false;
     }
 
-    // Find the item position if it was a mouse-generated selection event or a
-    // double click event (which is always generated using the mouse)
-    if ( n == wxNOT_FOUND )
-    {
-        const DWORD pos = ::GetMessagePos();
-        const wxPoint pt(GET_X_LPARAM(pos), GET_Y_LPARAM(pos));
-        n = HitTest(ScreenToClient(wxPoint(pt)));
-    }
+    const int n = ListBox_GetCurSel(GetHwnd());
 
     // We get events even when mouse is clicked outside of any valid item from
     // Windows, just ignore them.
@@ -636,20 +623,6 @@ bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
     return 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
 // ----------------------------------------------------------------------------