3

我有一个带有控件的 Windows 窗体应用程序。该控件由一个图表面板和一个我在其上绘制的画布组成。我想做的是以编程方式鼠标拖动面板,以便在画布的右边缘和画布上绘制的最后一个项目之间有一个特定的距离。我尝试了两种方法。两者都可以根据需要拖动面板,但我似乎无法获得我想要的运动精度。我编写了一个鼠标模拟器并尝试了两种方法。

方法一:

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

方法二:

 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 确实给了我指针定位的精确度,但我仍然在面板移动但最后绘制的条与右边缘之间的距离方面遇到困难。画布不等于应有的 positionShift 量。它似乎总是关闭。我已经为此工作了很长时间,并且不知所措。我不确定这里发生了什么。如何通过模拟鼠标拖动提高画布拖动的精度?

4

1 回答 1

0

那么你可以做的是,首先我相信 SendInput API 允许一个 AbsoluteValue 标志,所以不需要计算那些可能是问题但很可能不是问题的值。

尽管我很好奇您为什么要为此使用鼠标拖动操作。似乎您想要做的就是在每次绘制时重新定位画布某个指定的数量。如果是这种情况,为什么不直接在画布本身上明确设置它。此外,不清楚您使用的是纯 WinForms 还是 WPF。我相当肯定 Canvas 的不清楚之处仅适用于启用 WPF 的窗口。

话虽如此 WPF 修复,根据包含画布的对象,只需根据情况适当地设置其边距,因为我不知道您正在使用的数据,我对此不能说太多。但这是一个相对简单的想法,所以让我知道它是否有效,它应该给你,至少也接近,像素完美对齐。

WinForms,只需对您所说的“Canvas”对象执行上述操作,或使用对象的绝对坐标来移动它。

如果你能提供一个你正在处理的大致看起来的样本,也许我们可以更好地理解你的意思。

于 2012-11-06T10:14:34.000 回答