Pergunta

So I have a WPF Window that captures mouse events on an image. I am doing this by the following code:

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

Application Functionality: While the user moves the mouse left and right it changes the size of the image so long as they have the left mouse button pressed.

Question: Is is possible to also capture keyboard events while capturing the mouse move event.

End Result: I want to be able to change the mouse speed based on CTRL and SHIFT pressed. I have the code I need to change the mouse speed, I am just wondering how I can get it so that if the user is holding CTRL while they left click and drag on the image it changes the speed.

If anyone has any insight on this (i.e. articles, literature, or advice) that would be excellent. Thank you and if there is any additional information needed please let me know.

Foi útil?

Solução

To sum up comments if you want to check state of keyboard keys you can use Keyboard class which provides IsKeyDown method

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

or use its Modifiers property

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

Outras dicas

Set boolean flags based on what keys are pressed in the key pressed event.

In the OnMouseMove record the mouse position if null. Otherwise calculate the distance traveled, and amplify it or dampen it based on the speed up or slow down flags you've set already.

To dampen or amplify, once you have the X and Y change from the last point, multiply by 2, or divide by 2... (you can choose your own numbers), now add the new YX change to the current mouse XY coordinates and set the mouse position.

Here is what the MouseMove would look like, and some of the private variables needed. In my Example you have to have Forms included as a reference. I did not include Forms in my Include statements, because it mucks up IntelliSense in WPF applications. You will still need to maintain those _speedUp and _slowDown variables with your KeyDown events

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

EDIT: I put the key down events in my window definition, and it works just fine. Although as pointed out in the comments of this thread, using Keyboard.IsKeyDown is much simpler. I also edited the code above to not cause weird jumping issues

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top