关于form中的keydown事件

foutcast 2009-04-04 09:16:18
一个form中放置一个picturebox,按方向建移动picturebox位置.代码如下:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
keyupdown = "up";
timer1.Enabled = true;
break;
case Keys.Down:
keyupdown = "down";
timer1.Enabled = true;
break;
case Keys.Left:
keyleftright = "left";
timer2.Enabled = true;
break;
case Keys.Right:
keyleftright = "right";
timer2.Enabled = true;
break;
}
}


//上下移动的timer
private void timer1_Tick(object sender, EventArgs e)
{
switch (keyupdown)
{
case "up":
pictureBox1.Top = pictureBox1.Top + 6;
break;
case "down":
pictureBox1.Top = pictureBox1.Top - 6;
break;
}
}
//左右移动的timer
private void timer2_Tick(object sender, EventArgs e)
{
switch (keyleftright)
{
case "left":
pictureBox1.Left = pictureBox1.Left + 6;
break;
case "right":
pictureBox1.Left = pictureBox1.Left - 6;
break;
}
}

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
keyupdown = "";
timer1.Enabled = false;
break;
case Keys.Down:
keyupdown = "";
timer1.Enabled = false;
break;
case Keys.Left:
keyleftright = "";
timer2.Enabled = false;
break;
case Keys.Right:
keyleftright = "";
timer2.Enabled = false;
break;
}
}

这个功能能够实现.现在我在form 中又放置了一个button,按键盘就不会出发keydown事件,求解
...全文
779 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
bingbingw 2009-04-07
  • 打赏
  • 举报
回复
顶!
捷哥1999 2009-04-06
  • 打赏
  • 举报
回复
所以再一次证明了6楼的思路是完全正确的,必须重写ProcessDialogKey方法处理。
捷哥1999 2009-04-06
  • 打赏
  • 举报
回复
用Reflecotr反编译Form发现:
protected override bool ProcessDialogKey(Keys keyData)
{
if ((keyData & (Keys.Alt | Keys.Control)) == Keys.None)
{
IButtonControl control;
switch ((keyData & Keys.KeyCode))
{
case Keys.Return:
control = (IButtonControl) base.Properties.GetObject(PropDefaultButton);
if (control != null)
{
if (control is Control)
{
control.PerformClick();
}
return true;
}
break;

case Keys.Escape:
control = (IButtonControl) base.Properties.GetObject(PropCancelButton);
if (control != null)
{
control.PerformClick();
return true;
}
break;
}
}
return base.ProcessDialogKey(keyData);
}

即对于上下左右键,Form是调用其父类的ProcessDialogKey方法,也就是stem.Windows.Forms.ContainerControl类的ProcessDialogKey:
protected override bool ProcessDialogKey(Keys keyData)
{
if ((keyData & (Keys.Alt | Keys.Control)) == Keys.None)
{
Keys keys = keyData & Keys.KeyCode;
switch (keys)
{
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
if (!this.ProcessArrowKey((keys == Keys.Right) || (keys == Keys.Down)))
{
break;
}
return true;

case Keys.Tab:
if (this.ProcessTabKey((keyData & Keys.Shift) == Keys.None))
{
return true;
}
break;
}
}
return base.ProcessDialogKey(keyData);
}

这会导致调用System.Windows.Forms.ContainerControl类的ProcessArrowKey方法:
private bool ProcessArrowKey(bool forward)
{
Control parentInternal = this;
if (this.activeControl != null)
{
parentInternal = this.activeControl.ParentInternal;
}
return parentInternal.SelectNextControl(this.activeControl, forward, false, false, true);
}


在这里,我们才最终看到,上下左右键会导致选择下一个控件SelectNextControl!
wade_li 2009-04-06
  • 打赏
  • 举报
回复
真的精辟!up!!!!!
  • 打赏
  • 举报
回复
不是很确定啊
wbloxyfe 2009-04-05
  • 打赏
  • 举报
回复
学员学习……
Z_L_H 2009-04-04
  • 打赏
  • 举报
回复
foutcast 2009-04-04
  • 打赏
  • 举报
回复
KeyUp放在哪里控件里都可以吗?是否有特殊要求
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复
不放到Button里面也行,你到时候可以放到一个隐藏控件里面去啊,找个不用的控件,将其Visible属性设为false。或者找个标签,把Form的KeyUp事件处理的代码写到标签的KeyUp事件处理函数里面去。因为重新方法ProcessDialogKey时只能处理你按下的键,你松开键的时候Form又不会处理,所以我们就借用一个其他控件来处理KeyUp。
foutcast 2009-04-04
  • 打赏
  • 举报
回复
为什么keyup事件只能用button里的,我这个button是做测试用了,完整的程序的时候上面可能会放很多的控件上去,我又要用那个控件的keyup事件呢,为什么keypreview值设置成true了还是不行呢

[Quote=引用 13 楼 mathieuxiao 的回复:]
刚才KeyUp的时候还有一点点问题,现在重新改进了,测试过,完全OK,lz你再试试吧,应该没有问题的

C# code
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

string keyupdown = "";
string keyleftright = "";

private void timer1_Tick(object sender, EventArgs e)
{
switch (keyup…
[/Quote]
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复
注意我处理KeyUp事件的时候是依靠你的Button控件,处理KeyDown事件是依靠重写ProcessDialogKey()方法
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复
刚才KeyUp的时候还有一点点问题,现在重新改进了,测试过,完全OK,lz你再试试吧,应该没有问题的

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

string keyupdown = "";
string keyleftright = "";

private void timer1_Tick(object sender, EventArgs e)
{
switch (keyupdown)
{
case "down":
pictureBox1.Top = pictureBox1.Top + 6;
break;
case "up":
pictureBox1.Top = pictureBox1.Top - 6;
break;
}

}

private void timer2_Tick(object sender, EventArgs e)
{
switch (keyleftright)
{
case "right":
pictureBox1.Left = pictureBox1.Left + 6;
break;
case "left":
pictureBox1.Left = pictureBox1.Left - 6;
break;
}

}

protected override bool ProcessDialogKey(Keys keyData)
{
switch (keyData)
{
case Keys.Up:
keyupdown = "up";
timer1.Enabled = true;
break;
case Keys.Down:
keyupdown = "down";
timer1.Enabled = true;
break;
case Keys.Left:
keyleftright = "left";
timer2.Enabled = true;
break;
case Keys.Right:
keyleftright = "right";
timer2.Enabled = true;
break;
}
return base.ProcessDialogKey(keyData);
}

private void button1_KeyUp(object sender, KeyEventArgs e)
{
keyupdown = "";
timer1.Enabled = false;
keyleftright = "";
timer2.Enabled = false;
}
}
捷哥1999 2009-04-04
  • 打赏
  • 举报
回复
6楼的正解,应该是这样的,只要Form上存在一个具有TabIndex属性的控件,那么默认的情况下,上下左右键,都会导致按键被用于控件之间的导航,这一点,你只要添加一个textbox控件,然后按下上下左右任意一个按键,发现当前获得焦点的控件由Button1变成Textbox1,就可以证明。所以让Form1变得无法接收到按键事件了,我试着修改Form1的KeyPreview属性,竟然也不能解决问题,而重写ProcessDialogKey方法被证明是有效的。
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复
不会吧,在我这里可以上下移动啊
foutcast 2009-04-04
  • 打赏
  • 举报
回复
我已经将这个属性设置成true了,没有效果
[Quote=引用 8 楼 mathieuxiao 的回复:]
为了确保无误,lz最好还将窗体的KeyPreview属性设为True
[/Quote]
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复
某些键,如 Tab、Return、Esc 和箭头键,由控件自动处理。所以你在Form上点击方向键被Form自动处理了,为了加上我们自己的处理代码,就需要重写Form的处理方法,我们先处理,我们处理完了再让他处理
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复
为了确保无误,lz最好还将窗体的KeyPreview属性设为True
foutcast 2009-04-04
  • 打赏
  • 举报
回复
能不能请解释一下
[Quote=引用 6 楼 mathieuxiao 的回复:]
C# code
string keyupdown = "";
string keyleftright = "";
//private void Form1_KeyDown(object sender, KeyEventArgs e)
//{
// switch (e.KeyCode)
// {
// case Keys.Up:
// keyupdown = "up";
// timer1.Enabled = true;
// break;
// case Keys.Down:
// …
[/Quote]
mathieuxiao 2009-04-04
  • 打赏
  • 举报
回复

string keyupdown = "";
string keyleftright = "";
//private void Form1_KeyDown(object sender, KeyEventArgs e)
//{
// switch (e.KeyCode)
// {
// case Keys.Up:
// keyupdown = "up";
// timer1.Enabled = true;
// break;
// case Keys.Down:
// keyupdown = "down";
// timer1.Enabled = true;
// break;
// case Keys.Left:
// keyleftright = "left";
// timer2.Enabled = true;
// break;
// case Keys.Right:
// keyleftright = "right";
// timer2.Enabled = true;
// break;
// }
//}

private void timer1_Tick(object sender, EventArgs e)
{
switch (keyupdown)
{
case "down":
pictureBox1.Top = pictureBox1.Top + 6;
break;
case "up":
pictureBox1.Top = pictureBox1.Top - 6;
break;
}

}

private void timer2_Tick(object sender, EventArgs e)
{
switch (keyleftright)
{
case "right":
pictureBox1.Left = pictureBox1.Left + 6;
break;
case "left":
pictureBox1.Left = pictureBox1.Left - 6;
break;
}

}

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
keyupdown = "";
timer1.Enabled = false;
break;
case Keys.Down:
keyupdown = "";
timer1.Enabled = false;
break;
case Keys.Left:
keyleftright = "";
timer2.Enabled = false;
break;
case Keys.Right:
keyleftright = "";
timer2.Enabled = false;
break;
}

}

protected override bool ProcessDialogKey(Keys keyData)
{
switch (keyData)
{
case Keys.Up:
keyupdown = "up";
timer1.Enabled = true;
break;
case Keys.Down:
keyupdown = "down";
timer1.Enabled = true;
break;
case Keys.Left:
keyleftright = "left";
timer2.Enabled = true;
break;
case Keys.Right:
keyleftright = "right";
timer2.Enabled = true;
break;
//default:
// keyupdown = "";
// timer1.Enabled = false;
// keyleftright = "";
// timer2.Enabled = false;
// break;

}
return base.ProcessDialogKey(keyData);
}
kkun_3yue3 2009-04-04
  • 打赏
  • 举报
回复
这个方法有点曲线救国的味道,不过用起来还算不错
在界面上新增一个ContextMenu控件
然后参照http://www.cnblogs.com/kkun/archive/2009/03/10/1407480.html
最后将ContextMenu控件给FORM的CONTEXTMENU属性,将设置VISIABLE为FALSE,效果到达,。。。。
加载更多回复(4)

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧