Why do I lose mouse events over a picturebox ?

richardinwpb

Member
Joined
May 19, 2021
Messages
10
Programming Experience
10+
This is regarding a WinForms application written in c# using .Net 4.7.2.

I have a form that has a Top/Down splitter panel. The lower split panel contains Left/Right splitter panel. The Right split panel contains two panels, only one of which is visible at any given time: one contains a flowpanel containing image thumbnails and the other (which I will call the "imagepanel") contains a picturebox with Docking set to full. Right-clicking on a thumbnail hides the flowpanel and displays the imagepanel with the selected thumbnail shown in full in the picturebox. Right-clicking on the PictureBox hides the imagepanel and displays the flowpanel.

When I right-click on a thumbnail for the very first time after running my application, the MouseMove event for the picturebox fires as expected. I have a test label elsewhere that displays the coordinates of the cursor that demonstrates that the MouseMove event is firing. When I right-click on the Picturebox to go back to the flow panel and click on another thumbnail (or the same thumbnail), the MouseMove event never fires again unless I physically left-click on the picturebox.

I have tried setting Focus to the picturebox with PictureBox1.Focus();

I have tried selecting the picturebox with PictureBox1.Select();

I have tried simulating a left mouse-click. I know the simulated mouse click works because when I simulate the left mouse click over a button, it fires the Click event for the button. When I simulate the mouse click over the picturebox, it has no effect.

When I write this.ActiveControl.Name to the console in a variety of places, I always get the name of the Top/Down splitter panel, including the Click event of the PictureBox.

Why am I losing MouseMove events over the picturebox without having to click on it again ? I don't want my users to have to add this extra step.

I have tried creating just a simple application with minimal code to attempt to reproduce the issue, but, of course, I couldn't reproduce the issue.
 
If a minimal application to try to reproduce the problem isn't reproducing the problem, then there's obviously something in the original app that is causing the issue. Try running Spy++ to see where the actual Windows messages are getting sent to in particular situations. If I have to guess the Z-order of the windows maybe messed up in the failure case.
 
If a minimal application to try to reproduce the problem isn't reproducing the problem, then there's obviously something in the original app that is causing the issue. Try running Spy++ to see where the actual Windows messages are getting sent to in particular situations. If I have to guess the Z-order of the windows maybe messed up in the failure case.
Thank you for your response. I will try running Spy++ as you suggest.
 
I tried running Spy++. Not sure exactly what I was looking for, but I didn't see anything that I thought would be helpful. Most of the threads had blank messages.
 
Why are you using MouseMove event to detect mouse click? Shouldn't you use MouseClick event?
 
Alas, the art of using Spy++ is slowly getting lost even amongst Windows developers... Things to check:
1) If your app is 64-bit, use the 64-bit version of Spy++ (spyxx_amd64.exe) instead of the 32-bit version (spyxx.exe).

2) Unless you know which specific window and window message you want to watch, it's usually better to watch the the messages sent to the topmost window, and all so watch child window messages. For example, here I'm watching Notepad.exe and all the messages sent to it and it's child windows:
Screenshot_1.png


3) To not get too flooded with all the messages going by, cherry-pick the specific message, or class of messages that you are interested in. For example here, I'm only interest in the mouse messages:
Screenshot_2.png


4) Note that the second column of the captured messages is the window handle of window that is being sent the message:
Screenshot_3.png


5) You can use that handle to figure out what window that is in the app window hierarchy:
Screenshot_4.png
 
I don't think the OP is trying to use the mouse move to detect a click. It looks like he is using the mouse move to track the current cursor position. Anyway all the clicks he is talking about seems to be his attempts to workaround the problem by forcing whatever window to get placed correctly in the window ordering so that it will get the mouse move messages again after it was hidden away for a short period.
 
I compiled ways of determining the control from a variety of sources. All of these return the PictureBox as the control with the focus, regardless of when I call the ShowFocus() method below. So apparently it is not a "Focus" problem.

C#:
private void ShowFocus()
    {
        var _C_ = _get_all_controls(this);

        foreach (Control c in _C_)
        {
            if (c.Focused)
                Console.WriteLine(c.Name + " is focused now (ALL)");
        }

        foreach (Control c in this.Controls)
        {
            if (c.Focused)
                Console.WriteLine(c.Name + " is focused now (FORM)");
        }


        Control fc = GetFocusedControl();

        if (fc != null)
            Console.WriteLine("Focused Control: " + fc.Name);
    }

    private IEnumerable<Control> _get_all_controls(Control c)
    {
        return c.Controls.Cast<Control>().SelectMany(item =>
            _get_all_controls(item)).Concat(c.Controls.Cast<Control>()).Where(control =>
            control.Name != string.Empty);
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
    internal static extern IntPtr GetFocus();

    public static Control GetFocusedControl()
    {
        Control focusedControl = null;
        // To get hold of the focused control:
        IntPtr focusedHandle = GetFocus();
        if (focusedHandle != IntPtr.Zero)
            // Note that if the focused Control is not a .Net control, then this will return null.
            focusedControl = Control.FromHandle(focusedHandle);
        return focusedControl;
    }
 
It's not a matter of who has the focus. It's matter of who has the mouse capture:
Posted to a window when the cursor moves. If the mouse is not captured, the message is posted to the window that contains the cursor. Otherwise, the message is posted to the window that has captured the mouse.
 
This is the Spy++ output immediately after I click the thumbnail (when the mouse events do not work) and after I left-click the picturebox (LBUTTONDOWN).
I cannot see any difference at all. The mouse MOUSEMOVE event is still firing and coordinates are showing (which match the coordinates I am showing
on a label on my application). The handle (004D1F54) is the same before and after.
1621523398484.png
 
At least that shows that it's not a disappearing window on the WM_MOUSEMOVE being sent to another window. I assume that window handle is the window handle for the PictureBox.

The only thing I can think of is for debugging purposes to try to override the WndProc() of that picture box to see if the WM_MOUSEMOVE messages are getting to it on the C# side. But all that will show is whether the message is either making it there, or not making it there. Obviously if it's not making it there, the MouseMove event won't fire, but I don't have an recommendations on how to fix things so that the message does make it there. If the messages are arriving, but the event is not being recieved, I also don't have an recommendations on how to fix things other than double check that the object that has the mouse move event handler has not been accidentally destroyed or unregistered.
 
At least that shows that it's not a disappearing window on the WM_MOUSEMOVE being sent to another window. I assume that window handle is the window handle for the PictureBox.

The only thing I can think of is for debugging purposes to try to override the WndProc() of that picture box to see if the WM_MOUSEMOVE messages are getting to it on the C# side. But all that will show is whether the message is either making it there, or not making it there. Obviously if it's not making it there, the MouseMove event won't fire, but I don't have an recommendations on how to fix things so that the message does make it there. If the messages are arriving, but the event is not being recieved, I also don't have an recommendations on how to fix things other than double check that the object that has the mouse move event handler has not been accidentally destroyed or unregistered.
The mouse move event is being correctly handled as soon as I left-click on the picture box. Even though events are obviously occurring, as shown by Spy++, somehow the picturebox isn't picking it up until after I click on it. This whole thing is very frustrating.
 
Given that WM_MOUSEMOVE messages are posted (not sent) see the 'P' instead of 'S' in Spy++, it affects the way messages processed in the message queue. By any chance are you calling Application.DoEvents() or Form.ShowDialog() at some point? These tend to change the way messages are pumped and processed.
 
Given that WM_MOUSEMOVE messages are posted (not sent) see the 'P' instead of 'S' in Spy++, it affects the way messages processed in the message queue. By any chance are you calling Application.DoEvents() or Form.ShowDialog() at some point? These tend to change the way messages are pumped and processed.
There are no Application.DoEvents() or Form.ShowDialog() calls. Just hiding and unhiding of panels.
 
Back
Top Bottom