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

查看:502
本文介绍了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),然后执行自定义操作. /p>

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")]

公共静态外部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天全站免登陆