In WPF, how do you tell if the left mouse button is currently down without using any events?
Asked Answered
E

6

14

I have an app where I want to be able to move a slider. However, the slider is automatically updated by the program every 30 seconds. When I try to change the slider position with my mouse, the program is still updating the slider position, so I cannot move it manually with the mouse.

Somehow, I want the app to NOT update the slider if the user is in the process of changing its position. How can I tell if the left mouse button is down without using the left button down event? I just want to be able to access the mouse, and check the button state of the left mouse button. How do I access it without being inside of a mouse event?

Ebb answered 18/4, 2013 at 14:12 Comment(2)
Why don't you want to use the event? You could simply set a flag there and query that flag before updating.Manchukuo
I tried MouseLeftButtonDown and MouseLeftButtonUp events, and they never got fired. With further research, I discovered that the Slider Control gobbles these events up and never fires them. So, after some experimenting and searching, I discovered that I can just use the PreviewMouseLeftButtonDown and Up methods instead. They accomplish what I needed. I've posted the code below as an answer to this post. Thanks for pointing me in the right direction. I gave you a point.Ebb
P
46
bool mouseIsDown = System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed;
Prebend answered 9/2, 2015 at 16:59 Comment(2)
Exactly what I was looking for. Simple, easy and no need on listening to any events.Saez
Unfortunately System.Windows.Input.Mouse class works only from UI thread :(Cr
K
4

There are some rare cases, where System.Windows.Input.Mouse.LeftButton does not work. For example during Resize.

Then you can use GetKeyState:

public enum VirtualKeyCodes : short
{
  LeftButton = 0x01
}

[DllImport("user32.dll")]
private static extern short GetKeyState(VirtualKeyCodes code);

public static bool CheckKey(VirtualKeyCodes code) => (GetKeyState(code) & 0xFF00) == 0xFF00;
Knotweed answered 21/6, 2021 at 6:42 Comment(0)
E
3

Ok,

I figured it out. The Slider control in WPF does NOT fire the MouseDown, LeftMouseDown, or LeftMouseUp events. This is because it uses them internally to adjust the value as the user is manipulating the slider. However, the Slider control in WPF DOES fire the PreviewLeftMouseDown and the PreviewLeftMouseUp events. In addition, when you click the Left Mouse button, the Slider Control automatically captures the mouse and holds on to it until you release the Left Mouse button.

I was able to solve my problem with the following 3 events:

   private void _sliderVideoPosition_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _adjustingVideoPositionSlider = true;
        _mediaElement.Pause();
    }

    private void _sliderVideoPosition_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _adjustingVideoPositionSlider = false;
        _mediaElement.Play();
    }

    private void _sliderVideoPosition_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (_adjustingVideoPositionSlider)
        {
            _mediaElement.Position = TimeSpan.FromMilliseconds((int)e.NewValue);
        }
    }
Ebb answered 18/4, 2013 at 15:11 Comment(2)
@JasonMassey Yeah, he has to wait 2 days to accept his own answer, though.Concordia
Just a side note, I never like using the TimeSpan constructor. I hate having to count how many parameters there are to know what it means. TimeSpan.FromMilliseconds((int)e.NewValue) is a little more obvious.Concordia
I
1

You may consider, in your case, using Mouse Class.

If I'm not mistaken it doesn't track the state of the button when the mouse goes out of the UI of the application, so to be sure that you have always correct information, you may need to capture mouse.

Repeat, you need to check this by yourself.

Idiolect answered 18/4, 2013 at 14:17 Comment(0)
C
1

As I understand it, you want to keep an MVVM pattern to accomplish this task.

So first I would start by designing what I want in my ViewModel

public class ViewModel
{
    public ICommand EditingSliderCommand { get; set; } // actually set the command
    public ICommand DoneEditingCommand { get; set; } // actually set the command
    public bool IsEditing { get; set; }

    ...

    private void AutomaticUpdate
    {
        if (IsEditing)
            return;
        Update();
    }
}

then you could use the Blend Interactivity library to do the UI side in xaml.

The following is an example. I don't know if the event name is correct. You could also do the same with mouse up and done editing.

<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseDown">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, 
                            Path=EditingSliderCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>
Concordia answered 18/4, 2013 at 14:23 Comment(0)
S
1

Accepted answer didn't work for me, but this did:

if ((System.Windows.Forms.Control.MouseButtons & System.Windows.Forms.MouseButtons.Left) == System.Windows.Forms.MouseButtons.Left)
{
    System.Diagnostics.Debug.WriteLine("Left mouse down");
}
Succulent answered 21/4, 2021 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.