首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WinForms -使用ProcessCmdKey VS KeyDown捕获按键组合

问WinForms -使用ProcessCmdKey VS KeyDown捕获按键组合
EN

Stack Overflow用户
提问于 2011-12-10 19:05:25
回答 3查看 8.4K关注 0票数 6

我的目标是实现一个自定义控件+S键处理程序,以连接到winforms应用程序中的自定义保存方法。

根据我的研发,有几种方法可以实现这一点--首先,我尝试了明显的KeyPress事件处理程序。这不够强大,无法捕获我需要的按键(在编辑器级别上没有调用它,这正是我所需要的)。

第二个更好的选项是保护覆盖bool ProcessCmdKey(ref Message msg,Keys keyData)覆盖。这是有效的--它拦截CTRL键单击,但显然我需要编写额外的代码来坚持按下CTRL键的事实,并拦截下一个按键(在我的例子中是S),然后执行自定义操作。

代码语言:javascript
复制
 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == (Keys.S | Keys.Control))
        {
            // This is never called
        }
        else if (keyData == (Keys.Menu | Keys.Alt))
        {
           // this is called each time I hit CTRL
        }
        return true;
    }

ProcessCmdKey似乎是在我点击CTRL键后立即被调用的。

这篇文章建议创建一个KeyTracker类,它将持久化按下的键并执行它需要做的事情:

Capture Key Sequence via ProcessCmdKey

这似乎是一个很好的选择,但在我深入研究实现纪念品跟踪模式之前,是否有人对如何完成这一看似常见的特性有意见呢?

另一种模式使用GetKeyboardState API函数:

Capture multiple key downs in C#

这似乎很有趣,虽然我不确定它能满足我的需求。

代码语言:javascript
复制
[DllImport ("user32.dll")]

公开静态GetKeyboardState( byte[] keystate );

代码语言:javascript
复制
private void Form1_KeyDown( object sender, KeyEventArgs e )
{
  byte[] keys = new byte[255];

  GetKeyboardState (keys);

  if( keys[(int)Keys.Up] == 129 && keys[(int)Keys.Right] == 129 )
  {
      Console.WriteLine ("Up Arrow key and Right Arrow key down.");
  }
}

谢谢你看我的问题。

更新

我在我的DataPanel中添加了三个用于密钥处理的事件。当我在事件中设置断点时,这些事件都没有被VS捕获,所以这就是我认为ProcessCmdKey是我最好的选择的原因。

如果我能让这些活动发挥作用,那也会很好:

代码语言:javascript
复制
        // Ctrl + S: Save Support
        this.ParentForm.KeyPreview = true;
        this.KeyPress             += new KeyPressEventHandler(DataPanel_KeyPress);
        this.KeyDown              += new KeyEventHandler(DataPanel_KeyDown);
        this.PreviewKeyDown       += new PreviewKeyDownEventHandler(DataPanel_PreviewKeyDown);

在按任何键时,这些事件似乎都没有被捕捉到:

代码语言:javascript
复制
void DataPanel_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        if (e.KeyCode == (Keys.S | Keys.Control))
        {
            SessionManager.Trace.AddTrace("You Hit Save!!");
        }
    }

    void DataPanel_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == (Keys.S | Keys.Control))
        {
            SessionManager.Trace.AddTrace("You Hit Save!!");
        }
    }

    void DataPanel_KeyPress(object sender, KeyPressEventArgs e)
    {
        var key = e.KeyChar;
    }

更新

我通过使用一个简单的KeyUp事件和KeyPreview标志解决了这个问题:

代码语言:javascript
复制
 void ShipmentDataPanel_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.S)
        {
            MessageBox.Show("Control + S Key Hit!");
        }
    }

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-10 19:18:37

将表单的KeyPreview属性设置为true。该属性的摘要表示:“获取或设置一个值,该值指示窗体在事件传递到具有焦点的控件之前是否将接收关键事件。”然后使用KeyUp事件。除非是KeyPressed,否则它也会给出诸如控制键之类的特殊密钥的信息。

票数 3
EN

Stack Overflow用户

发布于 2017-12-19 09:32:34

我通过这样做解决了这个问题

代码语言:javascript
复制
if(e.KeyData==(Keys.S | Keys.Control))
票数 2
EN

Stack Overflow用户

发布于 2021-09-04 07:20:36

虽然这是一个很老的问题,但我还是想补充一下我的答案。

OP写道,他不能使用ProcessCmdKey,因为它会在他一命中Control键就会触发,并且也不会等到他按下S键。

我没有这个问题,下面的代码运行良好,只有当我第一次按Ctrl,然后按S时,才会调用Delete()方法

代码语言:javascript
复制
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    bool bHandled = false;
    // switch case is the easy way, a hash or map would be better, but more work to get set up.
    switch (keyData)
    {
        case Keys.F5:
            RefreshList("", "", false); // call my refresh method
            bHandled = true;
            break;
        case Keys.S | Keys.Control: // call my delete method
            Delete(false);
            bHandled = true;
            break;
        default:
            base.ProcessCmdKey(ref msg, keyData);
            break;
    }
    return bHandled;
}

protected virtual void Delete(bool handled)
{
    if (handled == false)
    {
        MessageBox.Show("delete");
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8459067

复制
相关文章

相似问题

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