在WPF中,如何在不使用任何事件的情况下判断左键是否按下?

13

我有一个应用程序,希望能够移动滑块。但是,该程序每30秒会自动更新滑块的位置。当我试图用鼠标改变滑块位置时,程序仍在更新滑块位置,因此我无法手动移动它。

我想让应用程序在用户正在改变滑块位置时不更新滑块。如何判断鼠标左键是否按下,而不使用左键按下事件?我只想访问鼠标,并检查左键的状态,如何在没有鼠标事件的情况下访问它?


1
为什么你不想使用事件呢?你可以在那里设置一个标志,然后在更新之前查询该标志。 - Daniel Hilgarth
我尝试使用MouseLeftButtonDown和MouseLeftButtonUp事件,但它们从未被触发。经过进一步的研究,我发现Slider控件会吞噬这些事件并且不会触发它们。因此,在一些实验和搜索后,我发现可以使用PreviewMouseLeftButtonDown和Up方法代替。它们达到了我需要的效果。我已将代码作为回答发布在此帖子中。感谢您指引我正确的方向。我给了您一个点赞。 - Curtis
6个回答

44
bool mouseIsDown = System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed;

1
正是我所需要的。简单易懂,无需监听任何事件。 - christoph
很遗憾,System.Windows.Input.Mouse类只能在UI线程中使用 :( - BlackOverlord

4

有些罕见情况下,System.Windows.Input.Mouse.LeftButton 无法正常工作。例如在调整大小期间。

那么你可以使用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;

3

好的,我明白了。WPF中的Slider控件不会触发MouseDown、LeftMouseDown或LeftMouseUp事件。这是因为当用户操作滑块时,它们在内部使用这些事件来调整值。但是,WPF中的Slider控件确实会触发PreviewLeftMouseDown和PreviewLeftMouseUp事件。此外,当您单击左键时,Slider控件会自动捕获鼠标,并一直保持到您释放左键。

我通过以下3个事件解决了我的问题:

   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);
        }
    }

1
@JasonMassey 是的,他必须等待2天才能接受自己的答案。 - Nick Freeman
1
只是一点小提醒,我从来不喜欢使用TimeSpan构造函数。我讨厌不得不数有多少个参数才知道它的含义。TimeSpan.FromMilliseconds((int)e.NewValue) 更明显一些。 - Nick Freeman

1

据我了解,您希望保持MVVM模式以完成此任务。

因此,我首先会设计我在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();
    }
}

然后您可以使用 Blend Interactivity 库在 XAML 中处理 UI 方面的内容。

以下是一个示例。我不知道事件名称是否正确。您也可以使用鼠标抬起和完成编辑来完成相同的操作。

<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseDown">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, 
                            Path=EditingSliderCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

1

在您的情况下,您可以考虑使用鼠标类

如果我没记错的话,它不会在鼠标移出应用程序的用户界面时跟踪按钮的状态,因此为了确保您始终拥有正确的信息,您可能需要捕获鼠标。

请注意,您需要自行检查此内容。


1

被接受的答案对我没有用,但这个有效:

if ((System.Windows.Forms.Control.MouseButtons & System.Windows.Forms.MouseButtons.Left) == System.Windows.Forms.MouseButtons.Left)
{
    System.Diagnostics.Debug.WriteLine("Left mouse down");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接