使方法等待右键单击以转到下一步(C# 窗体)
本文关键字:下一步 窗体 等待 方法 右键 单击 | 更新日期: 2023-09-27 18:34:06
好吧,我正在编写一个机器人,它将在屏幕上使用某些坐标,然后模拟15次点击(每次点击都有不同的坐标(。我已经让它与我在代码上手动输入的坐标一起使用,但现在我需要一种方法来记录这些坐标。我想做的是:用户按下一个按钮,然后程序显示一个消息框,上面写着"右键单击主菜单",用户右键单击它,这些坐标将被记录在一个数组上,然后程序将显示第二个消息框,要求右键单击下一个按钮,如此......我的问题是我不知道如何使该方法等待用户右键单击以继续。
我通过创建一个事件来测试我的程序,该事件会在每次我右键单击并在消息框中显示坐标时触发,使用 UserActivityHook 类包含事件 OnMouseActivity:
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);
}
}
}
我尝试做这样的事情:
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[][]);
...
}
我仍然是一个新手,这是我在StackOverflow中的第一个问题(我通常会在这里浏览找到答案,不需要问自己(,所以我很乐意接受任何批评。
这是使用 C# 5.0 的异步模型最容易实现的。 我们将首先创建一个方法,该方法将生成一个在满足条件时完成的Task
。 它将通过创建一个TaskCompletionSource
,向事件添加一个处理程序,并在处理程序中将任务标记为已完成来实现此目的。 加入一些样板代码以确保处理程序在完成后被删除,从完成源返回Task
,我们设置:
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();
}
有无数种方法可以完成这项工作,您都不应该远程执行。原因是,假设您设法使用 WaitForRightClick
停止执行线程,您将阻止 UI 线程!
通过这样做,您可以阻止用户单击所需的元素(以及从不阻止 UI 线程的许多其他原因(。
你可以用线程或使用异步方法,正如 Servy 所建议的那样。这会阻止方法(或异步执行该方法(,而不会阻止 UI 线程本身。
虽然更复杂,但您也可以将一堆表示"ClickTarget"的对象排队。然后,您将侦听右键单击事件并记录与当前ClickTarget
关联的坐标,取消排队以获取下一条指令,依此类推。
完整的代码对于StackOverflow来说太长了,但给你一些想法:
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);
}