简体   繁体   English

从类在Form1上按下捕获键

[英]Catch key pressed on Form1 from the Class

Here is my class with event handler: 这是我的带有事件处理程序的类:

public delegate void MyKeyEventHandler(object sender, KeyEventArgs e);

public class KeyEvent
{
    public event MyKeyEventHandler keyEvent;
    public string key = "";

    protected virtual void KeyPressed(KeyEventArgs e) 
    {
        MyKeyEventHandler handler = keyEvent;
        if (handler != null)
            handler(this, e);
    }

    public KeyEvent()
    {
        keyEvent += new MyKeyEventHandler(keyPressed);
    }

    private void keyPressed(object sender, KeyEventArgs e)
    {
        key = e.KeyCode.ToString();
    }
}

And in my Form1 I have this code: (EDITED) 在我的Form1中,我有以下代码:(已编辑)

KeyEvent ke = new KeyEvent();

private void button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(ke.key);
}

When I run form and press key on keyboard and then click on button it pop up empty MessageBox. 当我运行表单并按键盘上的键,然后单击按钮时,它会弹出一个空的MessageBox。 What I want is everytime I press a key on keyboard a MessageBox to pop up and show me which key I pressed. 我想要的是每当我按下键盘上的一个键时,就会弹出一个MessageBox并显示我按下的键。 This code is just for testing, I don't want just to pop up message box, I need the key for other things. 这段代码仅用于测试,我不想仅弹出消息框,我需要用于其他操作的密钥。

Note: To handle the events on Form1 is not a solution, I need to handle the events in class. 注意:处理Form1上的事件不是解决方案,我需要处理类中的事件。 I making a libray. 我做一个libray。

You can do something like this: 您可以执行以下操作:

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Form1 f = new Form1();
            f.KeyPreview = true;
            f.KeyDown += f_KeyDown;
            Application.Run(f);
        }

        static void f_KeyDown(object sender, KeyEventArgs e)
        {
            MessageBox.Show(e.KeyValue.ToString());
        }
    }

If you enable KeyPreview you will receive all keyDowns even of the controls placed on the Form. 如果启用KeyPreview,您将收到所有keyDown,甚至包括放置在窗体上的控件。 If you set it to false you only get the KeyDown when the Form has focus. 如果将其设置为false,则只有在窗体具有焦点时才能获取KeyDown。

As you can see in the code you can connect any KeyDownEventHandler method in any class to the Form. 如您在代码中看到的,您可以将任何类中的任何KeyDownEventHandler方法连接到Form。

As there where questions left: 那里还有问题:

 public class FormKeyListener
    {
        private Form formToListen = null;
        public void SetFormToListen(Form form)
        {

            if (formToListen != null)
                formToListen.KeyDown -= formToListen_KeyDown; // Unregister from old form if present

            formToListen = form;
            formToListen.KeyDown += formToListen_KeyDown; // Attach to new form
        }

        void formToListen_KeyDown(object sender, KeyEventArgs e)
        {
            MessageBox.Show(e.KeyValue.ToString());
        }
    }

Which can be call this way somewhere in your code: 可以在代码中的某处这样调用:

FormKeyListener fkl = new FormKeyListener();
Form1 f = new Form1();
f.KeyPreview = true;
fkl.SetFormToListen(f);

It will not be possible for you to create a class that is capable of just automatically listening for events generated by its parent. 您将无法创建一个能够自动侦听其父级生成的事件的类。 How would that work? 那将如何工作? What would happen if you created a new KeyEvent class using something that wasn't a Form and didn't raise events? 如果您使用非Form且未引发事件的东西创建了一个新的KeyEvent类,将会发生什么情况?

You are going to need to give your KeyEvent class a reference to whatever thing that you want to monitor key events for. 您将需要为KeyEvent类提供对您要监视其关键事件的任何事物的引用。 I realize that your intention is to create some third-party library, so you'd like to keep things as generic as possible in order to maximize its reuse. 我意识到您的意图是创建一些第三方库,因此您希望使它们尽可能通用,以最大程度地重用它。 Since you are dependent on the KeyDown event, using Control is the most generic you can be. 由于您依赖KeyDown事件,因此使用Control是最通用的方法。 This is because it is where the KeyDown event is actually defined. 这是因为它是实际定义KeyDown事件的地方。

Let me show you what I mean... 让我告诉你我的意思...

1) Modify the constructor of your KeyEvent class to accept an instance of Control 1)修改KeyEvent类的构造函数以接受Control的实例

public class KeyEvent
{
    // You don't need to declare an internal event
    public string key = "";
    private Control _control;

    public KeyEvent(Control control)
    {
        // Here is where we save the reference of Control that was passed to the class.
        // This will enable you to access the instance of the Form or whatever else
        // you want to use, which is helpful for unregistering events during cleanup
        _control = control;

        // Wire up your event handler to this SPECIFIC instance of Control.
        // This will cause your `keyPressed` method to execute whenever
        // the control raises the KeyDown event.  All of the middleman
        // event handling you are doing is unnecessary.
        _control.KeyDown += keyPressed;
    }

    private void keyPressed(object sender, KeyEventArgs e)
    {
        key = e.KeyCode.ToString();
    }

}

2) Modify the parent in which you are creating this KeyEvent to pass itself into the KeyEvent 2)修改要在其中创建此KeyEvent的父级,以将其自身传递给KeyEvent

// Now you pass 'this' into the constructor.  This can be a Form, or any other
// Winforms control that may inherit from Control (which is all of them)
KeyEvent ke = new KeyEvent(this);

private void button1_Click(object sender, EventArgs e)
{
    // At this point, ke.Key will always display the last
    // key pressed in the Form when the button is clicked.
    MessageBox.Show(ke.key);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM