3

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.

2

2 Answers 2

5

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

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;
}
4
  • thank you for the response. As I said I have the code to calculate the mouse speed and make those changes the unknown here was the ability to catpure the key press while in a mouse move event. I attempted to implement as you suggested with setting a flag value on key press, the issue I am having is that so long as the left click is down it seems to ignore any keyboard input. Any suggestions?
    – Jimmy
    Commented Mar 3, 2014 at 20:02
  • @Jimmy Upon actual testing, I see that it is the MouseEvents that are not firing. I'm getting the KeyEvents just fine.
    – BenVlodgi
    Commented Mar 3, 2014 at 20:17
  • as dkozl linked above I needed to do a key binding check inside the mouse event itself. So it would look something like this: private void OnMouseMove(object sender, MouseEventArgs e) { if(Keyboard.IsKeyDown(Key.LeftCtrl)) { //Change Speed } }
    – Jimmy
    Commented Mar 3, 2014 at 20:30
  • @Jimmy indeed, that is much simpler than monitoring for key presses all the time. I hope the application turns out well!
    – BenVlodgi
    Commented Mar 3, 2014 at 20:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.