WinForms - 使用 ProcessCmdKey VS KeyDown 捕获按键组合 [英] WinForms - Capturing the combination of key presses using ProcessCmdKey VS KeyDown

查看:15
本文介绍了WinForms - 使用 ProcessCmdKey VS KeyDown 捕获按键组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是实现自定义 Control + S 按键处理程序,以连接到 winforms 应用程序中的自定义保存方法.

My goal is to implement a custom Control + S key press handler to wire up to a custom save method in a winforms app.

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

There are several ways to accomplish this based on my R&D. First, I tried the obvious KeyPress event handler. This wasn't powerful enough to capture the key presses I need (it wasn't called on the Editor level, which is what I needed).

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

The second option which looks better is the protected override bool ProcessCmdKey(ref Message msg, Keys keyData) override. This works - it intercepts the CTRL key click, but apparently I need to write extra code to persist the fact the CTRL key is pressed and intercept the next key press (which would be S in my case) and then perform the custom action.

 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 键后立即被调用.

ProcessCmdKey seems to be called immediately after I hit the CTRL key.

这篇文章建议创建一个 KeyTracker 类,该类将保持按下的键并执行它需要执行的操作:

This post suggests creating a KeyTracker class that will persist the keys pressed and do what it needs to do:

通过 ProcessCmdKey 捕获键序列

这似乎是一个不错的选择,但在我深入研究实现一个纪念品跟踪模式之前,是否有人对如何完成这个看似常见的功能提出意见?

Which seems like a good option, but before I dig in an implement a memento tracking pattern, does anyone have input on how else to accomplish this seemingly common feature?

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

Another pattern uses the GetKeyboardState API function:

在 C# 中捕获多个按键操作

这似乎很有趣,但我不确定它是否适合我的需求.

This seems interesting, though I'm not sure it will suite my needs.

[DllImport ("user32.dll")]

public static extern int GetKeyboardState(byte[] keystate);

public static extern int GetKeyboardState( byte[] keystate );

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 是我最好的选择的原因.

I've added three events for key handling to my DataPanel. None of these events are being picked up by VS when I set breakpoints in the events, so this is what leads me to believe that ProcessCmdKey is my best option.

如果我能让这些事件发挥作用,那也很好:

If I could get these Events to work, that would be good as well:

        // 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);

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

None of these events seem to be caught when pressing any keys:

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 标志解决了这个问题:

I've solved the problem by using a simple KeyUp event and the KeyPreview flag:

 void ShipmentDataPanel_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.S)
        {
            MessageBox.Show("Control + S Key Hit!");
        }
    }

谢谢.

推荐答案

将表单的 KeyPreview 属性设置为 true.此属性的摘要说:获取或设置一个值,该值指示在将事件传递给具有焦点的控件之前表单是否将接收键事件.".然后使用 KeyUp 事件.除非 KeyPressed 它还提供有关特殊键(如控制键)的信息.

Set the KeyPreview property of our form to true. The summary of this property says: "Gets or sets a value indicating whether the form will receive key events before the event is passed to the control that has focus.". Then use the KeyUp event. Unless KeyPressed it gives also information on special keys like control keys.

这篇关于WinForms - 使用 ProcessCmdKey VS KeyDown 捕获按键组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆