GetMouseMovePointsEx:(mp_in)问题中的Bounds / MOUSEMOVEPOINT

我正在尝试计算光标加速度/速度。

我在C#中阅读了Find鼠标的速度,并决定采用Hans的建议使用GetMouseMovePointsEx ( pinvoke.net , MSDN )。

我制作了一个演示程序来测试它(参见下面的完整代码),但它有一个很大的局限性。

一旦光标离开窗口,它将不会返回点。
实际上,如果执行不限于MainWindow中的点,则函数返回-1(win32Exception 1171,“传递给GetMouseMovePoints的点不在缓冲区中”)。

  • 我怀疑这可能是因为我使用Mouse.GetPosition()来提供mp_in值。
    这可以通过使用GetCursorPos来解决吗?

移动窗口或调整窗口大小会导致myBounds.Contains(currentPosition)为true时为false。

  • 这可能是一个与我如何设定界限有关的愚蠢错误,但对我来说并不是很明显为什么会这样。 它也可能连接到Mouse.GetPosition() 。 不管是什么原因,我的比较都不匹配。 请帮忙?

它看起来像什么

MainWindow.xaml

         

MainWindow.xaml.cs

 using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; using System.Windows.Interop; using System.Runtime.InteropServices; namespace MouseVelocity { public partial class MainWindow : Window { DispatcherTimer GetMousePointsNow; MOUSEMOVEPOINT[] mp_out = new MOUSEMOVEPOINT[64]; MOUSEMOVEPOINT LastMMP; Rect myBounds; double[] XVelocity; public const int GMMP_USE_DISPLAY_POINTS = 1; public const int GMMP_USE_HIGH_RESOLUTION_POINTS = 2; int nNumPointsDesired = 20; uint mode = GMMP_USE_DISPLAY_POINTS; string DataCollectionTime; int nVirtualWidth = GetSystemMetrics(SystemMetric.SM_CXVIRTUALSCREEN); int nVirtualHeight = GetSystemMetrics(SystemMetric.SM_CYVIRTUALSCREEN); int nVirtualLeft = GetSystemMetrics(SystemMetric.SM_XVIRTUALSCREEN); int nVirtualTop = GetSystemMetrics(SystemMetric.SM_YVIRTUALSCREEN); double ScreenWidth = System.Windows.SystemParameters.PrimaryScreenWidth; double ScreenHeight = System.Windows.SystemParameters.PrimaryScreenHeight; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct MOUSEMOVEPOINT { public int x; public int y; public int time; public IntPtr dwExtraInfo; } [DllImport("user32.dll")] static extern int GetSystemMetrics(SystemMetric smIndex); [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] internal static extern int GetMouseMovePointsEx( uint cbSize, [In] ref MOUSEMOVEPOINT pointsIn, [Out] MOUSEMOVEPOINT[] pointsBufferOut, int nBufPoints, uint resolution ); public MainWindow() { InitializeComponent(); GetMousePointsNow = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 20), DispatcherPriority.Background, GetMousePointsNow_Tick, Dispatcher.CurrentDispatcher); GetMousePointsNow.IsEnabled = false; myBounds = new Rect(); } private void pMouseDown(object sender, MouseButtonEventArgs e) { GetMousePointsNow.Start(); } private void pMouseUp(object sender, MouseButtonEventArgs e) { GetMousePointsNow.Stop(); } private void GetMousePointsNow_Tick(object sender, EventArgs e) { double width = System.Windows.SystemParameters.PrimaryScreenWidth; double height = System.Windows.SystemParameters.PrimaryScreenHeight; myBounds.Location = new Point(this.Top, this.Left); myBounds.Size = new Size(this.ActualWidth, this.ActualHeight); Point currentPosition = PointToScreen(Mouse.GetPosition(this)); if (!myBounds.Contains(currentPosition)) { GetMousePointsNow.Stop(); return; } var mp_in = new MOUSEMOVEPOINT(); mp_in.x = ((int)currentPosition.X) & 0x0000FFFF; mp_in.y = ((int)currentPosition.Y) & 0x0000FFFF; int cpt = GetMouseMovePointsEx((uint)(Marshal.SizeOf(mp_in)), ref mp_in, mp_out, nNumPointsDesired, mode); if (cpt == -1) { int win32Error = Marshal.GetLastWin32Error(); throw new System.ComponentModel.Win32Exception(win32Error); } for (int i = 0; i  32767) mp_out[i].x -= 65536; if (mp_out[i].y > 32767) mp_out[i].y -= 65536; break; case GMMP_USE_HIGH_RESOLUTION_POINTS: mp_out[i].x = ((mp_out[i].x * (nVirtualWidth - 1)) - (nVirtualLeft * 65536)) / nVirtualWidth; mp_out[i].y = ((mp_out[i].y * (nVirtualHeight - 1)) - (nVirtualTop * 65536)) / nVirtualHeight; break; } } DisplayMousePoints(); DisplayVelocity(); } private void DisplayMousePoints() { string Result = ""; XVelocity = new double[20]; for (int i = 0; i  0) // Don't include first point in the calculation { Result = Result += "X: " + mp_out[i].x + ", " + "Timestamp: " + mp_out[i].time.ToString() + ", " + "Change: (" + DeltaTime.ToString() + "), " + "Point Velo: " + (XVelocity[i] * 100).ToString("0.000") + Environment.NewLine; } } DataCollectionTime = DateTime.Now.Second.ToString("00") + DateTime.Now.Millisecond.ToString("000"); txtOutput.Text = "Time Collected: " + DataCollectionTime + Environment.NewLine + Result; LastMMP = ThisMMP; } } private void DisplayVelocity() { // Calculate a moving average of velocity values double aggregate = 0; double weight; int item = 1; int count = 1; foreach (var d in XVelocity) { weight = (double)item / (double)count; aggregate += (double)d * weight; count++; } double result = (aggregate / count) * 100; lbl_Velo.Content = result.ToString("0.000"); } public enum SystemMetric { SM_XVIRTUALSCREEN = 76, // 0x4C SM_YVIRTUALSCREEN = 77, // 0x4D SM_CXVIRTUALSCREEN = 78, // 0x4E SM_CYVIRTUALSCREEN = 79, // 0x4F } } }