首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >单击按钮后,C#检测检测按键按下

单击按钮后,C#检测检测按键按下
EN

Stack Overflow用户
提问于 2015-06-19 09:46:47
回答 3查看 2.1K关注 0票数 1

我想在点击按钮后按下特定的键后执行一些操作。像这样:我点击按钮,然后按下End键,然后执行一些操作。

我试着用这个简单的代码,但它不能工作。

代码语言:javascript
运行
复制
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";
    }
}
EN

回答 3

Stack Overflow用户

发布于 2015-06-19 10:18:06

您没有指定是使用Winforms还是WPF,

以下是WPF的一个示例,但也应该与Winforms非常相似:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2015-06-19 11:32:00

我会考虑使用微软的Reactive Framework (Rx)来实现这一点(NuGet "Rx-Main","Rx-WinForms","Rx-WPF")你可以非常清晰地描述你想要在一个单一的LINQ查询中得到什么。

Rx允许您创建可查询的事件流。

首先,创建两个数据流--按钮点击和按键按下。

代码语言:javascript
运行
复制
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完成的处理程序。

下面是您现在可以执行的非常好的查询:

代码语言:javascript
运行
复制
var query =
    from c in clicks
    from kd in keydowns
        .Take(1)
        .TakeUntil(clicks)
    where kd.EventArgs.KeyCode == Keys.Return
    select kd;

这就是说“当我点击的时候,只取下一个键,除非我得到第二次点击,但只有当它碰巧是‘return’时才取下那个键。”

您要做的最后一步就是订阅所生成的值。

代码语言:javascript
运行
复制
var subscription = query.Subscribe(kd => this.label1.Text = "siala");

你甚至可以更进一步,这样做:

代码语言:javascript
运行
复制
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非常强大。

票数 1
EN

Stack Overflow用户

发布于 2015-06-19 10:09:53

我假设按钮在单击后保持焦点不变,因此事件不会传播到窗体。您可以使用下面的代码来检查事件的触发位置

您使用的是WPF还是Winforms?

代码语言:javascript
运行
复制
    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:允许事件只注册一次

代码语言:javascript
运行
复制
    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");
        }
    }
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30928629

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档