使用C# WPF捕获键盘和鼠标

3

我有一个捕获图像上鼠标事件的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并在图像上左键拖动时改变鼠标速度。

如果有人对此有任何见解(例如文章、文献或建议),那将非常棒。谢谢,如果需要任何其他信息,请告诉我。


也许这会有所帮助:https://dev59.com/x2025IYBdhLWcg3w3J5H - dkozl
@dkozl,你解决了问题,能否把解决方案发布为答案?谢谢。 - Jimmy
2个回答

5

总结一下,如果您想检查键盘按键的状态,可以使用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);
}

编辑:我将按键事件放在了窗口定义中,现在它可以正常工作了。虽然在这个线程的评论中指出,使用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
@ Jimmy 经过实际测试,我发现鼠标事件没有触发。我可以正常地获取键盘事件。 - BenVlodgi
如同dkozl在上面所连接的,我需要在鼠标事件内进行按键绑定检查。因此它看起来会像这样:private void OnMouseMove(object sender, MouseEventArgs e) { if(Keyboard.IsKeyDown(Key.LeftCtrl)) { // 更改速度 } } - Jimmy
@Jimmy 确实,这比一直监视按键要简单得多。我希望应用程序能够成功! - BenVlodgi

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