从类中按下Form1上的Catch键

时间:2013-06-18 16:40:53

标签: c# events delegates event-handling keypress

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

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上的事件不是解决方案,我需要处理类中的事件。我制作了一个图书馆。

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

您无法创建一个能够自动侦听其父级生成的事件的类。那会怎么样?如果您使用非KeyEvent并且未引发事件的内容创建新的Form课程,会发生什么?

您需要为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);
}