2012-11-05 50 views
3

我有一個帶有控件的Windows窗體應用程序。該控件包含一個帶有畫布的圖表面板,我可以在該面板上繪畫。我想要做的是以編程方式鼠標拖動面板,以便在畫布的右邊緣和畫布上最後一個項目之間有特定的距離。我嘗試了兩種方法。這兩個工作的意義在於,面板是按需拖動的,但我似乎無法獲得我想要的運動精度。我編寫了一個鼠標模擬器,並嘗試了兩種方法。以編程方式模擬鼠標拖動

方法1:

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確實給了我在指針定位精度,但我仍然有困難,面板移動,但最後一個欄和右邊緣之間的距離畫布不等於positionShift的數量,因爲它應該。它似乎總是關閉。我一直在研究這個很長一段時間,並在我的智慧結束。我不確定這裏發生了什麼事。如何通過模擬鼠標拖動提高畫布拖動的精度?

+0

這是什麼意思?只需直接在畫布上繪製即可。 –

+0

這是對現有應用程序的添加,所以我無法控制最後一個元素的繪製位置。我正在試圖拖動一個面板,而不是在它上面繪製。 – PBrenek

回答

0

嗯,你可以做的是,首先我相信SendInput API允許AbsoluteValue標誌,所以不需要計算這些值,這可能是問題,但很可能不是。

雖然我很好奇你爲什麼使用鼠標拖動操作。似乎所有你想要做的是重新定位畫布上的每一個畫一定量。如果是這種情況,爲什麼不直接在畫布本身上設置它。也不清楚你是否使用純WinForms或WPF。不清楚的一點是我相當確定的Canvas只能用於啓用WPF的窗口。

話雖這麼說 WPF修復, 根據包含畫布對象只設置了保證金適當的局面,因爲我不知道你在工作與我不能說太多有關數據。但是這是一個相對簡單的想法,所以讓我知道如果這是有效的,它應該給你,至少也是一個像素完美對齊。

WinForms, 只需對上述的「Canvas」對象進行操作,或者使用對象的絕對座標來移動它。

如果您可以提供您正在進行的工作的樣本,大概看起來可能我們可以更好地瞭解您的意思。

+0

謝謝你的回覆。在方法1中,MouseMove,我使用ABSOLUTE標誌。我發現方法1比方法2更不精確。我將其歸因於指針彈道問題。關於其他項目。這是Winforms而不是WPF。我已經在這兩種方法中使用了絕對座標。保證金不起作用,因爲雖然我可以重置它,但它可以防止進入我需要做的邊緣區域。我對你重新定位畫布的建議很感興趣。你能建議我怎麼能在WinForms中做到這一點?謝謝。 – PBrenek