2012-11-05 5 views
3

컨트롤이있는 Windows Forms 응용 프로그램이 있습니다. 컨트롤은 캔버스가있는 차트 패널로 구성되어 있습니다. 내가 뭘하고 싶은 건 프로그래밍 방식으로 마우스를 드래그하여 캔버스의 오른쪽 가장자리와 캔버스에 그려진 마지막 항목 사이에 특정 거리를 두는 것입니다. 나는 두 가지 접근법을 시도했다. 두 가지 모두 패널이 원하는만큼 드래그된다는 의미에서 작동하지만 원하는 동작의 정밀도를 얻을 수없는 것처럼 보입니다. 필자는 마우스 시뮬레이터를 코딩하여 두 가지 접근 방식을 시도했습니다.프로그래밍 방식으로 마우스 끌기 시뮬레이션

접근 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 : 나는 마우스 클릭을 시뮬레이션하기위한 SendInput을 사용하고

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

. 여기

private static int CalculateAbsoluteCoordinateX(int x) 
{ 
     return ((x * 65536) + GetSystemMetrics(SystemMetric.SM_CXSCREEN) - 1)/
      GetSystemMetrics(SystemMetric.SM_CXSCREEN); 
} 

그래서 여기

는 정밀도 문제입니다 ...

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

... 샘플 마우스 왼쪽 버튼을 아래 코드는 다음과 같이 나는 마우스에 대한 표준화 된 절대 좌표를 계산합니다. 접근법 1 (마우스 이동)을 사용하면 마지막으로 칠한 항목과 캔바스의 오른쪽 가장자리 사이의 측정 거리가 positionShift에서 설정 한 것과 다르며 커서 위치 차이가 positionShift와 동일하지 않습니다. 처음에는 그것이 포인터 탄도 문제로 인해 접근법 2를 시도했기 때문에 생각했습니다. 접근법 2는 포인터 위치 지정에서 정밀함을 제공하지만 패널이 이동한다는 점에서 여전히 어려움을 겪고 있지만 마지막 막대 그리기와 오른쪽 가장자리 사이의 거리는 canvas는 positionShift 양과 같지 않습니다. 항상 꺼져있는 것 같습니다. 나는 오랫동안이 일을 해왔으며 나의 지혜 끝에있다. 나는 여기서 무슨 일이 일어나고 있는지 확신하지 못한다. 시뮬레이션 된 마우스 끌기로 캔버스 드래그의 정밀도를 향상시키는 방법은 무엇입니까?

+0

이 점이 무엇입니까? 캔버스를 직접 그릴 수 있습니다. –

+0

이것은 기존 응용 프로그램에 추가되므로 마지막 요소가 그려지는 위치를 제어 할 수 없습니다. 패널을 끌기 위해 정확하게 그려야합니다. – PBrenek

답변

0

당신이 할 수있는 일은 이것입니다. 우선 SendInput API가 AbsoluteValue 플래그를 허용하므로 문제가 될 수 있지만 그럴 가능성이없는 값을 계산할 필요가 없다고 생각합니다.

왜 이렇게 마우스 드래그를 사용하는지 궁금합니다. 모든 드로잉에서 캔버스의 위치를 ​​특정 양만큼 재배치하기 만하면됩니다. 이 경우 캔버스 자체에 명시 적으로 설정하지 않는 것이 좋습니다. 또한 순수 WinForms 또는 WPF를 사용하고 있는지 여부도 분명하지 않습니다. 명확하지 않은 캔버스 캔버스는 WPF 가능 윈도우에서만 사용할 수 있습니다.

WPF 수정, 캔버스를 포함하는 개체에 따라 상황에 맞는 여백을 설정하기 때문에 작업중인 데이터를 알 수 없으므로 이에 대해 많이 언급하지 않습니다. 그러나 이것은 비교적 단순한 생각입니다. 그렇게하면 효과가 있는지, 최소한 가까운 곳에서 픽셀을 완벽하게 정렬해야합니다.

WinForms, 위의 "Canvas"객체에 대해 위의 작업을 수행하거나 객체의 절대 좌표를 사용하여 주위로 이동하십시오.

대략 작업 한 샘플을 제공 할 수 있다면 어쩌면 우리는 당신이 의미하는 바를 더 잘 이해할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 접근법 1, MouseMove에서 ABSOLUTE 플래그를 사용합니다.접근법 1이 접근법 2보다 덜 정확하다는 것을 알았습니다. 저는 이것을 포인터 탄도 문제로 돌렸습니다. 다른 항목에 대해서. WPF가 아닌 Winforms입니다. 나는 두 접근법에서 이미 이동을위한 절대 좌표를 사용한다. 여백은 재설정 할 수는 있지만 필요한 여백 영역으로 그려지지 않으므로 작동하지 않습니다. 캔버스의 위치를 ​​바꾸려는 당신의 제안에 흥미가 있습니다. WinForms에서 어떻게 할 수 있을지 제안 할 수 있습니까? 고맙습니다. – PBrenek

관련 문제