As I see it, basically what you are asking is how you can detect a case where the mouse is on the edge of the screen and trying to move in the direction of the edge. Naturally, a MouseMove
event will not detect this because the coordinate has not changed.
Using a global low level mouse hook is possibly the only way of getting a mouse move message even if the cursor has not changed position.
This allows to check if the coordinate has changed since the last message or not. If it has not, we might be at the edge of the screen.
public partial class Form1 : Form
{
private const int WH_MOUSE_LL = 14;
private const int WM_MOUSEMOVE = 0x200;
[DllImport("kernel32.dll")]
static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
public static extern int UnhookWindowsHookEx(IntPtr hhook);
[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, uint wParam, IntPtr lParam);
delegate IntPtr HookProc(int nCode, uint wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public int mouseData; // be careful, this must be ints, not uints (was wrong before I changed it...). regards, cmew.
public int flags;
public int time;
public UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
private HookProc hookProc;
private IntPtr hook;
private POINT formerPoint = new POINT() { X = 0, Y = 0 };
public Form1() { InitializeComponent(); }
IntPtr LowLevelMouseProc(int nCode, uint wParam, IntPtr lParam)
{
if (wParam == WM_MOUSEMOVE)
{
MSLLHOOKSTRUCT infoStr = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (infoStr.pt.X == formerPoint.X && infoStr.pt.Y == formerPoint.Y)
{
Console.WriteLine("Mouse moved without coordinates changing");
//use the standard way of finding the direction of travel here.
}
formerPoint = infoStr.pt;
}
return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
}
protected override void OnHandleDestroyed(EventArgs e)
{
UnhookWindowsHookEx(hook);
base.OnHandleDestroyed(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!DesignMode)
{
hookProc = new HookProc(LowLevelMouseProc);
hook = SetWindowsHookEx(WH_MOUSE_LL, hookProc, GetModuleHandle(null), 0);
}
}
}
*Hook code was taken from this blog
The problem with this method is that if the mouse is moving slower than 1 pixel per mouse message, a false positive is generated.
A possible partial solution to this would be to pre-detect the X and Y values of screen edges and test for those as well, but even this will not eliminate 100% of false positives, as it is possible for the mouse to be (for example) on the right edge of the screen and move very slowly left (less than 1 pixel), and this would still be detected as a positive.
Perhaps someone has a better idea how to eliminate these false positives.