【问题标题】:C# WPF Capture Keyboard and MouseC# WPF 捕获键盘和鼠标
【发布时间】:2014-04-05 00:25:19
【问题描述】:

所以我有一个 WPF 窗口来捕获图像上的鼠标事件。我通过以下代码执行此操作:

<Image Name="imgPrimaryImage" Width="512" Height="512" RenderOptions.BitmapScalingMode="NearestNeighbor" Margin="5"
       Source="{Binding Path=ImageMgr.ImageSource}"
                 MouseLeftButtonDown="OnMouseLeftButtonDown" 
                 MouseMove="OnMouseMove"
                 MouseLeftButtonUp="OnMouseLeftButtonUp"/>

应用程序功能:当用户左右移动鼠标时,只要按下鼠标左键,它就会改变图像的大小。

问题:是否可以在捕捉鼠标移动事件的同时捕捉键盘事件。

最终结果:我希望能够根据按下的 CTRL 和 SHIFT 来改变鼠标速度。我有更改鼠标速度所需的代码,我只是想知道如何获得它,以便如果用户在左键单击并拖动图像时按住 CTRL 键,它会改变速度。

如果有人对此有任何见解(即文章、文献或建议),那就太好了。谢谢,如果需要任何其他信息,请告诉我。

【问题讨论】:

标签: c# wpf mouseevent keyboard-events


【解决方案1】:

总结 cmets 如果你想检查键盘按键的状态,你可以使用 Keyboard 提供 IsKeyDown 方法的类

var isShift = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
var isCtrl = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
var isAlt = Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt);

或使用其Modifiers 属性

var isShift = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift);
var isCtrl = Keyboard.Modifiers.HasFlag(ModifierKeys.Control);
var isAlt = Keyboard.Modifiers.HasFlag(ModifierKeys.Alt);

【讨论】:

    【解决方案2】:

    根据在按键事件中按下的按键设置boolean 标志。

    OnMouseMove 中记录鼠标位置,如果为空。否则计算行进的距离,并根据您已经设置的加速或减速标志对其进行放大或衰减。

    要抑制或放大,一旦你从最后一点的 X 和 Y 变化,乘以 2,或除以 2...(你可以选择自己的数字),现在将新的 YX 变化添加到当前鼠标 XY 坐标并设置鼠标位置。

    这是MouseMove 的样子,以及一些需要的私有变量。在我的示例中,您必须包含 Forms 作为参考。我没有在我的 Include 语句中包含 Forms,因为它破坏了 WPF 应用程序中的 IntelliSense。您仍然需要使用 KeyDown 事件维护这些 _speedUp_slowDown 变量

    private bool entering = true;
    private Point _previousPoint;
    private bool _speedUp;
    private bool _slowDown;
    private double _speedMod = 2;
    private double _slowMod = .5;
    
    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        Point curr = new Point(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
    
        if (entering)
        {
            _previousPoint = curr;
            entering = false;
        }
        if (_previousPoint == curr)
            return; // The mouse hasn't really moved
    
        Vector delta = curr - _previousPoint;
        if (_slowDown && !_speedUp)
            delta *= _slowMod;
        else if (_speedUp && !_slowDown)
            delta *= _speedMod;
        else
        {
            _previousPoint = curr;
            return; //no modifiers... lets not do anything
        }
        Point newPoint = _previousPoint + delta;
        _previousPoint = newPoint;
        //Set the point
        System.Windows.Forms.Cursor.Position = new System.Drawing.Point((int)newPoint.X, (int)newPoint.Y);
    }
    

    编辑:我把按键事件放在我的窗口定义中,它工作得很好。尽管正如该线程的 cmets 中所指出的,使用Keyboard.IsKeyDown 要简单得多。我还编辑了上面的代码,以免引起奇怪的跳跃问题

    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        _slowDown = true;
        if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
            _slowDown = true;
        else if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
            _speedUp = true;
    }
    
    private void Window_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
            _slowDown = false;
        else if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
            _speedUp = false;
    }
    
    private void Window_MouseLeave(object sender, MouseEventArgs e)
    {
        entering = true;
    }
    

    【讨论】:

    • 感谢您的回复。正如我所说,我有计算鼠标速度并进行这些更改的代码,这里未知的是在鼠标移动事件中捕获按键的能力。我尝试按照您的建议在按键上设置标志值来实现,我遇到的问题是,只要左键单击它似乎忽略任何键盘输入。有什么建议吗?
    • @Jimmy 在实际测试中,我发现是 MouseEvents 没有触发。我得到 KeyEvents 就好了。
    • 作为上面链接的 dkozl,我需要在鼠标事件本身内部进行键绑定检查。所以它看起来像这样: private void OnMouseMove(object sender, MouseEventArgs e) { if(Keyboard.IsKeyDown(Key.LeftCtrl)) { //Change Speed } }
    • @Jimmy 确实比一直监控按键要简单得多。希望申请顺利!
    猜你喜欢
    • 1970-01-01
    • 2011-06-29
    • 2010-11-09
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    相关资源
    最近更新 更多