none
MouseUP on Listview not behaving as expected. RRS feed

  • Question

  • Not sure if this is a bug or desired behavior. If it is desired not sure the reason. Real easy to duplicate, create a windows from project. Add a Listview, Treeview, and textbox. Then a mouse down and up events with a debug.print (“”) in each. Put a break point on each of the debug.prints to see when the event is fired.
    Here is what I am seeing, on the Listview and Treeview controls, the mouse up event fires immediately after the mouse down, even if the mouse key is still held down. To see it, just run the form, put the mouse over the Listview or Treeview, press and hold the mouse button. When the break point stops, while hold the mouse down press the f5 and the mouse up fires. Then try the same thing on the textbox and form it behaves as expect. The mouse up does not fire until the button is released. Also if you press down on the textbox or form, then release on the Listview or Treeview, it’s mouse up fires as expected. All thoughts are appreciated.

    FYI, just for the curios, what I am trying to do is create a image picker, that the use can then sort the order of images picked. I have two listviews, one is the source and the other is the ones selected. Once images are drag and dropped from the source on the destination listview, I wanted to allow the user to drag the image to control the order in the listview.  I thought I could use flags to hold the x,y source item on the mouse down and x,y item on the mouse up, then rearrange the listview accordingly. That’s when I discovered the behavior, then I created a virgin form and saw the same results. I could not find anything Googling. 

    I tried it on frame works 2,3,3.5, and 4. I got the same results on all of them. The one thing that was weird, is on version 2 frame work, when the break point hit the .net environment did not get focus. Once you gave it focus and pressed f5, then the mouse up event fired like the others.
    Here is the code you can past into the form and save some typing.

    Public Class Form1
    
        Private Sub Form1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
            Debug.Print("")
        End Sub
    
        Private Sub Form1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
            Debug.Print("")
        End Sub
    
        Private Sub ListView1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseDown
            Debug.Print("")
        End Sub
    
        Private Sub ListView1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseUp
            Debug.Print("")
        End Sub
    
        Private Sub TextBox1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
            Debug.Print("")
        End Sub
    
        Private Sub TextBox1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp
            Debug.Print("")
        End Sub
    
        Private Sub TreeView1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TreeView1.MouseDown
            Debug.Print("")
        End Sub
    
        Private Sub TreeView1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TreeView1.MouseUp
            Debug.Print("")
        End Sub
    End Class


    • Edited by paenright Monday, February 3, 2014 1:35 PM Change the title to be more specific.
    Monday, February 3, 2014 1:33 PM

Answers

  • If you hold the mouse down, and then trigger a breakpoint in the debugger that breaks execution and gives focus to the debugger, then all bets are off as for what mouse messages your applications will get.  This is because by necessity, you need to pass focus to the deugger, but that creates a weird situation where it's not really clear what messages should be passed to your application.

    When the breakpoint is hit your application is suspended immediately, and there should be no problem with that first mouse click.  The problem comes when you hit F5 and you try to get the system back into the exact same state you were in before resuming.  It's a sticky situation because the system needs to pass focus back to the suspended application, but it cannot do so because it's suspended. So you have to resume the application before it can receive any messages but that actually means that it will get some messages about the loss of focus that will interfere with your mouse message passing -- regardless of whether you managed to keep your physical mouse button pressed the whole time.

    If you need to debug this kind of thing, consider using a remote debugger so that mouse interactions with the debugger to not affect mouse interactions with your application.

    For a less intrusive test, to reassure you that things are working as expected, do this:

    1. instead of those Debug.Print statements, remove them, and simply set a breakpoint on each sub
    2. then right click each breakpoint and choose "When Hit..." and check the Print a message, and make sure the Continue execution option is checked too (it should be checked by default.)  This will print a pre-canned message indicating, at the very least, which method the breakpoint is in. (Very handy!)
    3. Then show the Output window (that's where your debug messages will appear)  You'll be watching this window during the test to see what messages are fired.
    4. Start debugging your app.  (F5.)
    5. rearrange your windows so that you can see both your application and the debug output window of your debugger at the same time.  
    6. and finally, give focus to your application. (Switch to your app.)  You don't want to switch focus to the debugger at any point from here on.
    7. Now you can click around with your mouse.  You can mouse down and mouse up in your app wherever you want and you should be able to see the correct debug messages being printed with no surprises.

    So again, what you were seeing by setting hard breakpoints that stop execution of your app is a side effect of having passed focus to the debugger window with the mouse held down, and then having resumed your application by pressing F5 (again, all with the mouse held down).

    If you try my suggested technique, you'll find that the messages in the application are working as expected provided you don't switch focus to your debugger.

    A very similar and much more intrusive problem occurs when you try to debug drag and drop messages your way.  Things can even lock up on you.

    Again, the one sure-fire way to avoid this kind of UI-sensitive situation when debugging is to use two computers, and do remote debugging.  Then the mouse clicks and focus of your debugger on one machine won't interfere with the mouse clicks and focus of your application on the other machine.

    • Marked as answer by paenright Monday, February 3, 2014 3:15 PM
    Monday, February 3, 2014 2:59 PM

All replies

  • Hi, I think you can use ListView.ItemDrag and TreeView.ItemDrag event if you want drag from ListView and TreeView.
    Monday, February 3, 2014 2:10 PM
  • Hi, I think you can use ListView.ItemDrag and TreeView.ItemDrag event if you want drag from ListView and TreeView.
    Thanks, drag and drop works as expected. Just to be clear, I understand if you are in a dodrag the events are different, in this case there are no drag events.  This is off subject, but in a dragdrop event, if you try and use the get item with the mouse x,y it does not give back the correct item. I assume it is because the control is in some “lock” state. The same x,y in the mouse down does give the correct item, hence why I stated looking at mouse up. Again, notice in the test, there are no “dodrag” commands.
    Sorry for my confusion.
    Monday, February 3, 2014 2:31 PM
  • If you hold the mouse down, and then trigger a breakpoint in the debugger that breaks execution and gives focus to the debugger, then all bets are off as for what mouse messages your applications will get.  This is because by necessity, you need to pass focus to the deugger, but that creates a weird situation where it's not really clear what messages should be passed to your application.

    When the breakpoint is hit your application is suspended immediately, and there should be no problem with that first mouse click.  The problem comes when you hit F5 and you try to get the system back into the exact same state you were in before resuming.  It's a sticky situation because the system needs to pass focus back to the suspended application, but it cannot do so because it's suspended. So you have to resume the application before it can receive any messages but that actually means that it will get some messages about the loss of focus that will interfere with your mouse message passing -- regardless of whether you managed to keep your physical mouse button pressed the whole time.

    If you need to debug this kind of thing, consider using a remote debugger so that mouse interactions with the debugger to not affect mouse interactions with your application.

    For a less intrusive test, to reassure you that things are working as expected, do this:

    1. instead of those Debug.Print statements, remove them, and simply set a breakpoint on each sub
    2. then right click each breakpoint and choose "When Hit..." and check the Print a message, and make sure the Continue execution option is checked too (it should be checked by default.)  This will print a pre-canned message indicating, at the very least, which method the breakpoint is in. (Very handy!)
    3. Then show the Output window (that's where your debug messages will appear)  You'll be watching this window during the test to see what messages are fired.
    4. Start debugging your app.  (F5.)
    5. rearrange your windows so that you can see both your application and the debug output window of your debugger at the same time.  
    6. and finally, give focus to your application. (Switch to your app.)  You don't want to switch focus to the debugger at any point from here on.
    7. Now you can click around with your mouse.  You can mouse down and mouse up in your app wherever you want and you should be able to see the correct debug messages being printed with no surprises.

    So again, what you were seeing by setting hard breakpoints that stop execution of your app is a side effect of having passed focus to the debugger window with the mouse held down, and then having resumed your application by pressing F5 (again, all with the mouse held down).

    If you try my suggested technique, you'll find that the messages in the application are working as expected provided you don't switch focus to your debugger.

    A very similar and much more intrusive problem occurs when you try to debug drag and drop messages your way.  Things can even lock up on you.

    Again, the one sure-fire way to avoid this kind of UI-sensitive situation when debugging is to use two computers, and do remote debugging.  Then the mouse clicks and focus of your debugger on one machine won't interfere with the mouse clicks and focus of your application on the other machine.

    • Marked as answer by paenright Monday, February 3, 2014 3:15 PM
    Monday, February 3, 2014 2:59 PM
  • Thanks, drag and drop works as expected. Just to be clear, I understand if you are in a dodrag the events are different, in this case there are no drag events.  This is off subject, but in a dragdrop event, if you try and use the get item with the mouse x,y it does not give back the correct item. I assume it is because the control is in some “lock” state. The same x,y in the mouse down does give the correct item, hence why I stated looking at mouse up. Again, notice in the test, there are no “dodrag” commands.

    Sorry for my confusion.

    Hi, if you want get the item with mouse x,y from dragdrop event, for example, from the dragover event, you need to convert the screen coordinate to control coordinate first, for example:

        Private Sub ListView1_DragOver(ByVal sender As Object, ByVal e As DragEventArgs) Handles ListView1.DragOver
            Dim point = ListView1.PointToClient(New Point(e.X, e.Y))
            Dim item = ListView1.GetItemAt(point.X, point.Y)
    
        End Sub


    I have tried this and it can give the correct item. Hope it can help you


    • Edited by lapheal Monday, February 3, 2014 3:10 PM change to VB code
    Monday, February 3, 2014 3:07 PM
  • If you try my suggested technique, you'll find that the messages in the application are working as expected provided you don't switch focus to your debugger.

    First, that is cool, cant believe I have missed that all these years. You are correct, I did get the expect results. But what’s weird, I got the correct results with the text box and from, that is what made me think my test was valid. 
    Now I will use the same technique and see if the while in a “dodrag” command, will the reported x,y give me the correct over item.

    Monday, February 3, 2014 3:15 PM
  •  But what’s weird, I got the correct results with the text box and from, that is what made me think my test was valid. 
    I think it's because each of those controls responds a little differently to regaining focus.
    Monday, February 3, 2014 3:55 PM