这是我的类与事件处理程序:
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();
}
}
在我的表单1中,我有这个代码:(编辑)
KeyEvent ke = new KeyEvent();
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(ke.key);
}
当我运行表单并按键盘上的键,然后单击按钮,它弹出空消息框。我想要的是,每次我按键盘上的一个键,一个消息框弹出,告诉我我按了哪个键。这段代码只是为了测试,我不想只是弹出消息框,我需要其他事情的关键。
注意:要处理Form1上的事件不是解决方案,我需要处理类中的事件。
您不可能创建一个能够自动侦听其父类生成的事件的类。这怎么可能呢?如果您使用非Form
且不引发事件的东西创建新的KeyEvent
类,会发生什么?
你需要给你的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);
}
你可以这样做:
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,您将接收到所有的keydown,甚至是放置在窗体上的控件。如果你把它设为false,你只会在窗体有焦点时得到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);