C# 以编程方式模拟鼠标拖动
我有一个带有控件的Windows窗体应用程序。该控件由一个图表面板和一个画布组成,我在画布上绘制。我想做的是通过编程鼠标拖动面板,这样画布的右边缘和画布上最后一个绘制的项目之间就有一个特定的距离。我尝试了两种方法。这两项工作的意义上说,小组是拖动所需的,但我似乎无法获得我的运动精度的愿望。我编写了一个鼠标模拟器,并尝试了两种方法 方法1:C# 以编程方式模拟鼠标拖动,c#,winforms,mouse,C#,Winforms,Mouse,我有一个带有控件的Windows窗体应用程序。该控件由一个图表面板和一个画布组成,我在画布上绘制。我想做的是通过编程鼠标拖动面板,这样画布的右边缘和画布上最后一个绘制的项目之间就有一个特定的距离。我尝试了两种方法。这两项工作的意义上说,小组是拖动所需的,但我似乎无法获得我的运动精度的愿望。我编写了一个鼠标模拟器,并尝试了两种方法 方法1: if(this.ChartControl.ChartPanel.CanFocus) { // ... Focus the chart pane
if(this.ChartControl.ChartPanel.CanFocus)
{
// ... Focus the chart panel to be adjusted.
this.ChartControl.ChartPanel.Focus();
// ... Move cursor to lastBarScreenCoordinates on the chart panel to be adjusted.
Cursor.Position = new Point(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
MouseSimulator.SetMouseDragThresholds();
// ... Move chart panel to required position.
MouseSimulator.LeftMouseButtonDown(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
MouseSimulator.MouseMove(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
MouseSimulator.LeftMouseButtonUp(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
MouseSimulator.ResetMouseDragThresholds(_cx_default, _cy_default);
// ... Redraw the chart panel.
this.ChartControl.ChartPanel.Refresh();
// ... Reset cursor to its starting position.
Cursor.Position = new Point(startingCursorX, startingCursorY);
}
方法2:
if(this.ChartControl.ChartPanel.CanFocus)
{
// ... Focus the chart panel to be adjusted.
this.ChartControl.ChartPanel.Focus();
// ... Move cursor to lastBarScreenCoordinates on the chart panel to be adjusted.
Cursor.Position = new Point(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
MouseSimulator.SetMouseDragThresholds();
// ... Move chart panel to required position.
MouseSimulator.LeftMouseButtonDown(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
Cursor.Position = new Point(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
WindowsCommunication.SendMessage(this.ChartControl.Handle, 0x200, IntPtr.Zero,IntPtr.Zero);
MouseSimulator.LeftMouseButtonUp(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
MouseSimulator.ResetMouseDragThresholds(_cx_default, _cy_default);
// ... Redraw the chart panel.
this.ChartControl.ChartPanel.Refresh();
// ... Reset cursor to its starting position.
Cursor.Position = new Point(startingCursorX, startingCursorY);
}
我使用SendInput模拟鼠标点击。下面是示例鼠标左键按下代码
public static void LeftMouseButtonDown(int x, int y)
{
INPUT mouseInput = new INPUT();
mouseInput.type = SendInputEventType.InputMouse;
mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x);
mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y);
mouseInput.mkhi.mi.mouseData = 0;
mouseInput.mkhi.mi.time = 0;
mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
}
我计算鼠标的标准化绝对坐标如下
private static int CalculateAbsoluteCoordinateX(int x)
{
return ((x * 65536) + GetSystemMetrics(SystemMetric.SM_CXSCREEN) - 1) /
GetSystemMetrics(SystemMetric.SM_CXSCREEN);
}
这里是精度问题。如果使用方法1(鼠标移动),绘制的最后一个项目与画布右边缘之间的测量距离与我在positionShift中设置的不同,并且光标位置差不等于positionShift。我最初认为这是由于指针弹道问题,所以我尝试使用方法2。方法2确实给了我指针定位的精度,但我仍然有困难,因为面板移动,但最后一个绘制的条与画布右边缘之间的距离不等于它应该的位置偏移量。它似乎总是关闭。我已经在这方面工作了很长时间,现在我已经不知所措了。我不知道这里发生了什么事。如何通过模拟鼠标拖动来提高画布拖动的精度?您可以做的是,首先,我相信SendInput API允许使用AbsoluteValue标志,因此无需计算可能存在问题但很可能不存在的值 虽然我很好奇为什么你要用鼠标拖动操作来实现这个。看起来您所要做的就是在每次绘制时按指定的数量重新定位画布。如果是这种情况,为什么不直接在画布上显式设置它呢。此外,还不清楚您使用的是纯WinForms还是WPF。不清楚的一点是画布,我相当肯定它只适用于支持WPF的windows 话虽如此 WPF修复, 根据包含画布的对象,只需根据情况适当设置其边距,因为我不知道您正在处理的数据,对此我不能说太多。但这是一个相对简单的想法,所以让我知道,如果这是可行的,它应该给你,至少也接近,一个像素完美的对齐 WinForms, 只需对您所说的“Canvas”对象执行上述操作,或者使用对象的绝对坐标来移动它
如果你能提供一个你正在研究的样本,大概看起来像,也许我们能更好地理解你的意思 这有什么意义?直接在画布上绘制。这是现有应用程序的附加组件,因此我无法控制最后一个元素的绘制位置。我正试图拖动一个面板,而不是在上面画。谢谢你的回复。在方法1 MouseMove中,我使用绝对标志。我发现方法1比方法2更不精确。我把这归因于弹道导弹问题。关于其他项目。这是Winforms,不是WPF。我已经在两种方法中使用了绝对坐标。边距将不起作用,因为虽然我可以重置它,但它会阻止绘制到我需要执行的边距区域。我对你关于重新定位画布的建议很感兴趣。您能建议我如何在WinForms中实现这一点吗?非常感谢。