0

这是我的带有事件处理程序的课程:

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();
    }
}

在我的 Form1 中,我有以下代码:(已编辑)

KeyEvent ke = new KeyEvent();

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

当我运行表单并按下键盘上的键然后单击按钮时,它会弹出空的 MessageBox。我想要的是每次我按下键盘上的一个键时都会弹出一个 MessageBox 并显示我按下了哪个键。此代码仅用于测试,我不想只是弹出消息框,我需要其他事情的密钥。

注意:处理 Form1 上的事件不是解决方案,我需要在类中处理事件。我制作了一个库。

4

2 回答 2

0

你可以这样做:

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());
        }
    }

如果您启用 KeyPreview,您将收到所有 keyDowns,甚至是放置在表单上的控件。如果将其设置为 false,则只有在 Form 具有焦点时才能获得 KeyDown。

正如您在代码中看到的,您可以将任何类中的任何 KeyDownEventHandler 方法连接到 Form。

正如问题所在:

 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());
        }
    }

可以在代码中的某处这样调用:

FormKeyListener fkl = new FormKeyListener();
Form1 f = new Form1();
f.KeyPreview = true;
fkl.SetFormToListen(f);
于 2013-06-18T16:54:41.480 回答
0

您不可能创建一个能够仅自动侦听其父级生成的事件的类。那将如何运作?如果您KeyEvent使用不是 aForm并且没有引发事件的东西创建了一个新类,会发生什么?

您将需要为您的KeyEvent班级提供您想要监控关键事件的任何内容的参考。我意识到您的意图是创建一些第三方库,因此您希望尽可能保持通用性,以最大限度地重复使用。由于您依赖于KeyDown事件,因此使用Control是最通用的。这是因为它KeyDown是实际定义事件的地方。

让我告诉你我的意思...

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) 修改您在其中创建它的父级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);
}
于 2013-06-18T17:24:36.000 回答