我想在点击按钮后按下特定键后执行某些操作。像这样:我点击按钮,然后按结束键,然后执行一些操作。
我试过这个简单的代码,但它没有用。
private void buttonStart_Click(object sender, EventArgs e)
{
KeyDown += OnKeyDown;
}
private void OnKeyDown(object sender, KeyEventArgs keyEventArgs)
{
if (keyEventArgs.KeyCode == Keys.Return)
label2.Text = "siala";
}
}
答案 0 :(得分:1)
您没有指定是使用Winforms还是WPF,
以下是WPF的示例,但也应与Winforms非常相似:
bool canClick = true;
public MainWindow()
{
InitializeComponent();
TheBox.PreviewMouseDown += TheGrid_PreviewMouseDown;
}
async void TheGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (canClick)
{
canClick = false;
TheBox.PreviewKeyDown += TheGrid_PreviewKeyDown;
await Task.Delay(5000);
TheBox.PreviewKeyDown -= TheGrid_PreviewKeyDown;
canClick = true;
}
}
void TheGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
Console.WriteLine("Button {0}", e.Key);
}
这里的想法是你在PreviewKeyDown
时注册一个事件处理程序
单击鼠标,然后在5秒后删除该处理程序。
这样,用户必须在点击鼠标后5秒内输入密钥 布尔值用于确保每次都不会多次注册事件处理程序。
您还应该查看可能提供清洁的reactive extensions 解决这个问题的方法。
答案 1 :(得分:1)
我会考虑使用Microsoft的Reactive Framework(Rx)(NuGet“Rx-Main”,“Rx-WinForms”,“Rx-WPF”),您可以在一个LINQ查询中非常干净地描述您想要的内容
Rx允许您创建可以查询的事件流。
首先制作两个数据流 - 按钮点击和按键。
var clicks = Observable.FromEventPattern(
h => this.button1.Click += h,
h => this.button1.Click -= h);
var keydowns = Observable.Merge(
Observable.FromEventPattern<KeyEventHandler, KeyEventArgs>(
h => this.button1.KeyDown += h,
h => this.button1.KeyDown -= h),
Observable.FromEventPattern<KeyEventHandler, KeyEventArgs>(
h => this.KeyDown += h,
h => this.KeyDown -= h));
这是迄今为止最难以理解的代码。好的一点是,你真的不需要太努力 - 他们甚至只是用Rx完成处理程序。
现在,您可以执行以下非常好的查询:
var query =
from c in clicks
from kd in keydowns
.Take(1)
.TakeUntil(clicks)
where kd.EventArgs.KeyCode == Keys.Return
select kd;
这表示“当我点击一下时,除非我第二次点击,否则只需按下一个键,但如果恰好是'返回',则只关闭一个键。”
您必须做的唯一最后一步是订阅正在生成的值。
var subscription = query.Subscribe(kd => this.label1.Text = "siala");
你甚至可以更进一步做到这一点:
var query =
from c in clicks
from kd in keydowns
.Take(1)
.TakeUntil(clicks)
.TakeUntil(Observable.Timer(TimeSpan.FromSeconds(3.0)))
where kd.EventArgs.KeyCode == Keys.Return
select kd;
现在说“当我点击一下时,只需要按下一个键,除非我得到第二次点击或者如果已经过了3秒,但是如果它恰好是'返回',则只取下一个键。”
如果您希望订阅停止,只需致电subscription.Dispose();
Rx非常强大。
答案 2 :(得分:-1)
我认为按钮在单击后保持焦点,因此事件不会传播到表单。您可以使用以下代码检查事件被触发的位置
您使用的是WPF还是Winforms?
private void button1_Click(object sender, EventArgs e)
{
this.KeyDown += Form1_KeyDown;
this.button1.KeyDown += button1_KeyDown;
}
void button1_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("[BUTTON] PRE-KEY-CHECK"); e.Handled = false;
if (e.KeyCode == Keys.F1)
{
MessageBox.Show("[BUTTON] POST-KEY-CHECK");
}
}
void Form1_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("[WINDOW] PRE-KEY-CHECK"); e.Handled = false;
if(e.KeyCode == Keys.F1)
{
MessageBox.Show("[WINDOW] POST-KEY-CHECK");
}
}
编辑:可以找到问题的解决方案Keyboard event propagation in winforms
基本上你必须设置this.KeyPreview=true;
编辑2:仅允许注册一次事件
Boolean isEventhandlerRegistered = false;
private void button1_Click(object sender, EventArgs e)
{
if (!this.isEventhandlerRegistered)
{
this.PreviewKeyDown += Form1_PreviewKeyDown;
this.isEventhandlerRegistered = true;
}
}
void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
MessageBox.Show("[WINDOW] POST-KEY-CHECK");
}
}