我有一个禁用控件。我仍然希望按键和按键事件被触发,因为我想知道某个键。
当我测试它时,似乎没有任何控件的事件被触发。关于如何解决这个问题的任何想法?
答案 0 :(得分:0)
缺乏互动是禁用控制的基本理念,它正在按预期工作。
您可以使用Form的KeyPreview属性,然后从Form事件启动已禁用控件的事件处理程序。
通常,有n + 1种方法可以实现您所寻求的目标。所以我只介绍其中的一部分。
1 - 操纵焦点。虽然易于实现,但它也很不稳定,因为用户也可以操纵焦点。
private void button_KeyDown(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Add(helpBox);
((Control)sender).Focus(); // Set focus back to control so its KeyUp will be called
}
private void button_KeyUp(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Remove(helpBox);
}
2 - 多次调用同一事件处理程序。对的,这是可能的。有点复杂,可能依赖于helpBox控件类和/或它的事件。可能的问题可能包括多次启动的事件处理程序,但是即使出现这种情况,所提供的代码也可以安全使用。
private void button_KeyDown(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Add(helpBox);
helpBox.KeyUp += button_KeyUp; //This will add KeyUp of our hosting button to hosted control, which means that said KeyUp handler can be raised by both helpBox and button
}
private void button_KeyUp(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Remove(helpBox);
helpBox.KeyUp -= button1_KeyUp; // to avoid unnecessary calls event handler can be easily "subtracted" from helpBox
}
3 - 使用KeyPreview设置为true,通过Form本身进行主控制,在名为的控件上显示带有“help_”作为helpBox的控件。
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
foreach (Control c in this.Controls)
{
string hName = "help_" + c.Name;
Control[] help = this.Controls.Find(hName, true);
if (help.Length>0)
{
c.Controls.Add(help[0]);
}
}
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
foreach (Control c in this.Controls)
{
string hName = "help_" + c.Name;
Control[] help = c.Controls.Find(hName, true);
if (help.Length > 0)
{
c.Controls.Remove(help[0]);
}
}
}
}
注意:控制屏幕位置取决于其父位置(相对于父级的左上角),换句话说,通过更改控件的父级(在Controls.Add期间发生),控件将更改其位置。 / p>
4 - 自己画吧!操纵控件并不总是最佳解决方案,相反,您可能只想在控件上绘制一些东西。
private void Form1_KeyDown(object sender,KeyEventArgs e) { button1.Tag = true; button1.Update(); }
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
button1.Tag = false;
button1.Update();
}
// there is no reason to re-draw it constantly, Paint event will be fired when needed
private void button1_Paint(object sender, PaintEventArgs e)
{
// remember that all Tag's start as null
if (((Control)sender).Tag != null && (bool)((Control)sender).Tag == true)
{
// and when needed just paint on control drawing area (also known as Canvas)
e.Graphics.FillRectangle(Brushes.Red, 0, 0, 100, 100);
e.Graphics.DrawString("Foo!", ((Control)sender).Font, Brushes.Beige, new PointF(5, 5));
}
}
注意:每个Control都有Tag属性,因为它是对象类型,您可以在其中存储任何您想要的内容。这使它成为通用定制属性。如果你想知道这个属性的含义:它没有意义,它是用户定义的。