I have Windows Forms application and I need to capture the mouse movements outside my window. My simplified code in my window class is:
private void ButtonOnClick(object sender, EventArgs e)
{
Capture = true;
MouseMove += OnMouseMove;
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
Console.Out.Write("!");
}
As you see, when user presses a button, my program should start tracking mouse (even if it is outside of window - this is a key featue!) But I get really strange behavior. If I move mouse inside the window, everything is great, ! are written to console. But when I move mouse outside of the window, only OnMouseMove is called only once (and the point is really outside). Then if I move mouse anywhere outside of the window it is not called anymore. If I return mouse back to window, everything is perfect. Move away - 1 message, move in the window - OK.
Can anybody help?
You would need a global mouse hook for that. I recommend that you first read something about hooks, eg. on MSDN. An example implementation in C# can be found at the CodeProject.
Hope that helps a bit.
Related
As of now, I can only listen to touch events within my app window via:
this.TouchDown += new EventHandler<TouchEventArgs>(TouchableThing_TouchDown);
this.TouchMove += new EventHandler<TouchEventArgs>(TouchableThing_TouchMove);
private void TouchableThing_TouchDown(object sender, TouchEventArgs e){}
private void TouchableThing_TouchMove(object sender, TouchEventArgs e){}
But I realized I needed to capture touch events outside the window too. Is there a known event where I could listen to such that it covers not only my own window, but the whole screen instead?
To get input events outside of the window, you need to delve into p/invoke territory. Specifically, you need to set up what's called a hook. Even more specifically, you need to add a WH_MOUSE hook, which lets you monitor system-wide mouse events (touch input is an evolution of mouse input so they are both handled together by Windows).
This question give valuable information and an example on interpreting touch input using a hook:
how to distinguish touch vs mouse event from SetWindowsHookEx in c#
I would like to use a second mouse in my C# WPF application independently from my primary mouse.
So the primary mouse controls the cursor and the mouse buttons triggers the usual click, drag, mouse wheel, etc. events
From the second mouse I would like to receive the mouse move and click events but this one should not move the mouse cursor and should not be handled by the application itself e.g. fire a button command.
In the end I will send the mouse move X/Y delta and mouse click to another device to handle them.
So something like this
private void Window_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
var delta = oldPosition - e.MouseDevice.GetPosition(this);
DoSomething(delta);
e.Handled = true;
}
I found some links to Microsoft Multipoint SDK but this seems to be inactive since 2013 and I couldn't find any good examples.
On the other hand I found some applications using Raw Input to identify the keyboard / mouse device but I couldn't figure out how to listen to the events from the second mouse without influencing the mouse cursor and application.
Does anybody has a good idea or staring point?
Ok I tried a lot of different solution but I didn't get happy with one of them.
In the end I found this nice solution
Interception
that fits my needs. You need to install a software component and this one seems to hack in the system somewhere in between the mouse + keyboard and the OS kernel. From now on you can listen to the mouse/keyboard events from your software and modify them.
My UserControl is a kind of a container that has a set of controls inside. One of the UI behaviours I designed is that the move over nested control makes it selected for some keyboard triggered actions.
The other way of setting up the nested control that is targeted to receive keyboard input is with arrow keys that change focus to certain control within my UserControl.
The problem is that in most cases my UserControl has scrollbars and switching between its elements with arrow keys causes contents to move. Because of that movement it seems that mousemove event is launched also when the mouse arrow stands still, but its over my usercontrol. In the end, the wrong nested control is being selected.
I tried to set a boolean flag to temporary lock the actions of mousemove event while the arrow keys handling function is launched, but it seems to not to work at all.
Does anybody have an idea how to prevent that unwanted triggering of mousemove event and avoid the problems it causes?
I did some debugging/experiments and it appears that though mouse stays still over controll the MouseMove is actually called frequently and not only when control move is caused by some UI behaviour (scrolling of parent controll called using keyboard).
It also seems like it is called twice every single second (but probably only when application is launched form VS during debug session?), the calls are separated by few hundred parts of seconds and for now i couldnt determine what causes those.
Solution (maybe not only, and not the best) is to store last position of cursor and compare it inside event to check if mouse was really moved from last MouseMove call. I achieved it using System.Windows.Forms.Cursor.Position because position from MouseEventArgs will be diffrent depending on circumstances but still will be inconclusive to determine if mouse cursor was moved.
Point lastCursorPosition = new Point();
private void panelPictures_MouseMove(object sender, MouseEventArgs e)
{
if (System.Windows.Forms.Cursor.Position != lastCursorPosition)
{
Console.WriteLine("mouse moved");
lastCursorPosition = System.Windows.Forms.Cursor.Position;
}
else
{
Console.WriteLine("mouse in place");
}
}
I have an application in WPF C# where other than the purpose of what it's done, I customized the close and minimize buttons. The problem is that when I minimize, all is good, I cycle around all other apps, but, when I want to go back to the application, I click in the window in the taskbar, and the window pops up... But when it pops up, the window pursues the mouse pointer throughout the screen...
The code i've implemented the the simplest it can be...
private void Minimize_LeftMouseDown(object sender, MouseButtonEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
Can you point me some directions?
Thanks
It's possible that you've somehow captured the mouse at that point, and the minimize state is preventing WPF's normal release from occurring. If your control is named "Minimize", try adding:
private void Minimize_LeftMouseDown(object sender, MouseButtonEventArgs e)
{
// Make sure we're not capturing the mouse anymore
Mouse.Capture(null);
this.WindowState = WindowState.Minimized;
}
Use the LeftMouseUp event instead of LeftMouseDown. You want to minimize the window when the mouse is released, not when it is pressed down.
I want to show a tooltip when hovering over a button and as long as the mouse is over the button the tooltip should follow the mouse. What is the correct way to achieve that?
When I add a MouseMove event that calls tooltip.Show(...) with the updated mouse position it flickers extremely, and also redraws the tooltip when the mouse rests. And if it is an OwnerDraw tooltip I can see the default system tooltip style "fighting" with the self-drawn tooltip.
Indeed, with .Net 2.0 the ToolTip object has been altered. Before 2.0, there were some inconsistency problems when the ToolTip text was changed while the ToolTip was active, or with some other situations.
Since 2.0, the Tooltip is hidden each time something happens what could affect the currently active Tooltip.
While this solved some problems, it now causes some events being fired right after e.g. a SetToolTip(), even if this function has been called from within this very event, resulting in an endless loop of ToolTip draw/hide until the mouse moves away from the ToolTip area.
My own workaround is to check whether the ToolTip is already the same and omitting the Set ToolTip() if so. (simply omitting the next event by a static flag as suggested above can cause problems as there is no guarantee that there will be a new event right after, e.g. if the mouse has just touched the ToolTip area and moved away already).
Also, using OnMouseHover just to display a Tooltip disables the internal timer functionality of the ToolTip component as well as causing many many unnecessary events and therefore wastes processor time. The Popup Event of the ToolTip component serves well as point of action.
In this special case, however, OnMouse Hover is necessary to track the mouse movement.
Anyways, altering the ToolTip position causes a complete redraw of the Tooltip and therefore flicker. This can be reduced for a motionless mouse by checking whether the mouse position has changed between two events.
Unfortunately, the ToolTip component has no way to change the position of the ToolTip adn is shown always relative to the current mouse position. So the only way to have it follow the mouse is to close and redraw it.
it MAY help to set the UseFading and/or UseAnimation properties to false so the flicker can be further reduced.
OK, this may be complete overkill, and probably not the best solution, but I think a fun little hack nonthless.
Basically, I'm drawing a ListView at the location of the mouse. Some code:
ListView v = new ListView();
public Form1()
{
InitializeComponent();
v.Items.Add("Foo");
v.Height = 30;
v.Width = 50;
this.button1.Controls.Add(v);
v.MouseMove += new MouseEventHandler(v_MouseMove);
v.BackColor = SystemColors.Info;
this.button1.MouseMove += new MouseEventHandler(button1_MouseMove);
}
void v_MouseMove(object sender, MouseEventArgs e)
{
v.Location = new Point(v.Location.X + e.Location.X, v.Location.Y + e.Location.Y);
}
void button1_MouseMove(object sender, MouseEventArgs e)
{
v.Location = e.Location;
}
I've noticed that when manually showing a tooltip with OnMouseHover, OnMouseMove gets called one more time after the tooltip is shown. As a hack, I've ignored the next OnMouseMove call immediately following the tooltip being shown (using a flag). Perhaps a similar phenomenon is occurring?