2014-12-11 3 views
1

으로 마우스 오른쪽 버튼을 클릭 할 때까지 기다리십시오. 특정 좌표를 화면에 사용하고 15 클릭 (다른 좌표로 클릭 할 때마다)을 시뮬레이트합니다. 이미 코드에서 수동으로 입력 한 좌표로 작업을 만들었지 만 지금은 좌표를 기록 할 방법이 필요합니다. 내가 원했던 것은 사용자가 버튼을 누른 후 프로그램이 "메인 메뉴에서 마우스 오른쪽 버튼을 클릭하십시오"라는 메시지 상자를 보여주고, 사용자가 마우스 오른쪽 버튼을 클릭하면 해당 좌표가 배열에 기록되고 프로그램에 두 번째 messagebox는 다음 버튼을 마우스 오른쪽 버튼으로 클릭하는 것을 묻습니다. 내 문제는 사용자가 마우스 오른쪽 버튼을 클릭하여 계속 진행할 때까지 기다리는 방법을 알지 못한다는 것입니다.다음 단계 (C# 양식)

UserActivityHook actHook; 
    void MainFormLoad(object sender, System.EventArgs e) 
    { 
     actHook = new UserActivityHook(); 
     // crate an instance with global hooks 
     // hang on events 
     actHook.OnMouseActivity+=new MouseEventHandler(MouseMoved);   
    } 

    public void MouseMoved(object sender, MouseEventArgs e) 
    {    
     if (e.Clicks > 0) 
     { 
      if (e.Button.Equals(MouseButtons.Right)) 
      { 
       MessageBox.Show("X:" + e.X + " Y:" + e.Y); 
      } 
     } 
    } 

내가 일을하려고했습니다

나는 이벤트 OnMouseActivity를 포함와 UserActivityHook 클래스를 사용하여, 내가 마우스 오른쪽 버튼을 클릭하고 메시지 박스의 좌표를 보여 매번 발생하게 이벤트를 만들어 내 프로그램을 테스트 뭔가 같은 :

private void button1_Click(object sender, EventArgs e) 
    { 
     RecordMacro(cords, 1);   
    } 

    public void RecordMacro(int coordinates[][], int slotnumber){ 

     MessageBox.show("Right click main menu"); 
     //saves coordinates on [0][0] and [0][1] 
     WaitForRightClickAndSaveCords(coordinates[][]); 

     MessageBox.show("Right click resupply button"); 
     //saves coordinates on [1][0] and [1][1] 
     WaitForRightClickAndSaveCords(coordinates[][]); 
     ... 
    } 

나는 아직 안돼서이에 유래 내 첫 번째 질문입니다 (나는 보통 여기 찾아 답을 찾아 자신을 요청할 필요가 없습니다) 그래서 나는 기꺼이 어떤을 받아 들일 수 있습니다 비평가.

답변

2

이것은 C# 5.0의 비동기 모델을 사용하여 구현하는 것이 가장 쉽습니다. 조건이 충족 될 때 완료 될 Task을 생성하는 메소드를 작성하는 것으로 시작하겠습니다. TaskCompletionSource을 만들고 이벤트에 처리기를 추가하고 처리기에서 완료된 것으로 작업을 표시하여이 작업을 수행합니다.

public static Task<Point> WhenRightClicked(this UserActivityHook hook) 
{ 
    var tcs = new TaskCompletionSource<Point>(); 
    MouseEventHandler handler = null; 
    handler = (s, e) => 
    { 
     if (e.Clicks > 0 && e.Button == MouseButtons.Right) 
     { 
      tcs.TrySetResult(new Point(e.X, e.Y)); 
      hook.OnMouseActivity -= handler; 
     } 
    }; 
    hook.OnMouseActivity += handler; 
    return tcs.Task; 
} 

지금 당신이 쓸 수 있습니다 :

public async void RecordMacro(int[][] coordinates, int slotnumber) 
{ 
    MessageBox.Show("Right click main menu"); 
    Point mainMenuPosition = await actHook.WhenRightClicked(); 
    MessageBox.Show("Right click resupply button"); 
    Point resupplyButtonPosition = await actHook.WhenRightClicked(); 
} 
+0

'+ 1' RecordMacro의 (잠재적) 길이는 어떤 종류의 나에게 제안하지만 나는이 방법을 좋아한다 대기열에 저장되므로 작업이 하드 코딩되지 않습니다. – BradleyDotNET

+0

@BradleyDotNET 나는이 메소드를 호출하는 방법을 보여 주려했다. 요점은 일단 당신이 그것을 사용하면 메서드가 * 매우 * 쉬워진다는 것입니다. 그가 전화를하고 싶다면 그는 그렇게 할 수 있습니다. – Servy

+0

당신은 생명의 은인입니다. 브래들리 (Bradley)가 말했듯이 명확한 대답을 주셔서 감사합니다. "좌표를 저장하는 비 정교한 수동 방식"으로 의도를 보여 주려고했는데 루프를 사용할 생각이었습니다. –

0

가 있습니다 핸들러가 완료되면, 완료 소스에서 Task를 돌려 제거되고, 우리가 설정하고 있는지 확인하기 위해 몇 가지 상용구 코드에 던져 이 작업을 수행하는 방법은 무수히 많으며 원격으로 수행 할 수있는 방법은 없습니다. 그 이유는, 당신이 WaitForRightClick이라는 쓰레드의 실행을 멈출 수 있다고 가정한다면, 당신은 UI 쓰레드를 차단할 것입니다. 이렇게함으로써

, 당신은 (결코 블록 UI 스레드에 다른 많은 이유들) 당신이 원하는 요소를 클릭 할 수있는에서 사용자를 방지 할 수 있습니다.

Servy가 제안한 것처럼 스레드를 사용하거나 비동기 메서드를 사용할 수 있습니다. 이 경우 UI 스레드 자체를 차단하지 않고 메서드을 차단하거나 비동기 적으로 실행합니다.

더 복잡한 반면, "ClickTarget"을 나타내는 많은 개체를 큐에 넣을 수도 있습니다. 그런 다음 마우스 오른쪽 버튼 클릭 이벤트를 수신하고 관련 좌표를 현재 ClickTarget과 함께 기록하고, 다음 명령을 가져 오는 등의 작업을 수행합니다.

전체 코드에 유래 너무 긴 것, 그러나 몇 가지 아이디어를 당신에게 제공하기 위해 :

public class ClickTarget 
{ 
    Point Coordinates {get; set;} 
    String TargetName {get; set;} 
} 

Queue<ClickTarget> clickTargets; 
//Obviously you instantiate/populate this somewhere 

private void onRightClick(...) 
{ 
    ClickTarget target = clickTargets.Dequeue(); 
    target.Coordinates = clickLocation; 

    MessageBox.Show("Please click on " + clickTargets.Peek().TargetName); 
} 
+0

아, 큐 사용에 대해서는 생각하지 않았습니다. 몇 년 전부터 그래픽 환경에서 멀티 링크 노드 목록을 보여 주려고했던 때부터 사용하지 않았습니다. 조언 해 주셔서 감사합니다. –