最近在用VS平台做一个【WinForm提示建议小工具】,其中用到keydown\keypress事件,有些感受。
当你按下一个键盘,在keydown、keyup事件的参数keycode是不分字母大小写,只是表示按下某个键了,例如A、a是在一个键上。如果你想捕捉某个动作时 用这个事件比较合适,但是并不包含像keyascii的东西。这个东西在keypress事件的参数里e.KeyChar,而在keypress事件里是不捕捉control、shift、alt等控制键。因此,这个时候如果想把按键发送到另外一个位置,使用
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
//当按向回车
if (e.KeyCode == Keys.Enter)
{
dataGridView1_DoubleClick(sender, e);
}
//当按向左右箭头
// else if (e.KeyCode==Keys.Left|| e.KeyCode==Keys.Right)
// {
// _listenerControl.Focus();
// }
//当按向下箭头
else if (e.KeyCode == Keys.Down)
{
if (dataGridView1.CurrentRow != null && dataGridView1.CurrentRow.Index == dataGridView1.Rows.Count - 1 && dataGridView1.CurrentRow.Index != 0)
{
e.SuppressKeyPress = true;
dataGridView1.CurrentCell = dataGridView1.Rows[0].Cells[0];
}
}
//当按向上箭头
else if (e.KeyCode == Keys.Up)
{
if (dataGridView1.CurrentRow != null && dataGridView1.CurrentRow.Index == 0 && dataGridView1.CurrentRow.Index != dataGridView1.Rows.Count - 1)
{
e.SuppressKeyPress = true;
dataGridView1.CurrentCell = dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[0];
}
}
//否则输入框获取焦点,并将按下的字符传递
else
{
_listenerControl.Focus();
}
}
private void dataGridView1_KeyPress(object sender, KeyPressEventArgs e)
{
SendKeys.Send(e.KeyChar.ToString(CultureInfo.InvariantCulture));
}
--2013-11-29
还有就是做这个小工具会遇到一些问题,SQLServer的压力测试,因为在TextChanged就会从数据库检索数据,按照这种方式每当键入一个字符就会从sqlserver检索,尽管可以建立复合索引,但这种压力的检索速度还是觉得太大了。我也做了测试,看上去服务器的sqlserver没有明显的压力。
但是,如果指示纯粹的测试,可以按住某个键不放,这速度太快了!向服务器申请数据的速度也太快了,因此,考虑应该以时间段为单位,而不应该以TextChanged为单位,比如300ms向服务器申请一次数据,如果TextChanged那么就申请,如果Text没有change就不必申请数据了。
考虑到这种方式,就可以在提示的小工具上放个timer,这个timer没必要使用现成的,用forms下的timer消息驱动即可,因为这时对时间的要求不必太严格,大概时间即可。当text发生改变就告诉timer,300ms或等不到300ms就申请数据,设置timer时间间隔即可。这样在这300ms内发生变化的text就不会频繁申请数据。以下是代码片段:
private Control _listenerControl;
public Control ListenerControl
{
set
{
if (!Visible)
{
//确定弹出位置
Owner = value.FindForm();
Show(Owner);
if (Owner != null)
Location = new Point(value.Location.X + Owner.Location.X + 8,
value.Location.Y + Owner.Location.Y + 53);
//自动刷新事件
value.TextChanged += (sender, args) =>
{
_isTextChanged = true;
};
value.KeyDown += (sender, args) =>
{
//当按向下箭头
if (args.KeyCode == Keys.Down)
{
args.SuppressKeyPress = true;
dataGridView1.Focus();
if (dataGridView1.CurrentRow!=null && dataGridView1.CurrentRow.Index < dataGridView1.Rows.Count-1)
{
dataGridView1.CurrentCell = dataGridView1.Rows[dataGridView1.CurrentRow.Index + 1].Cells[0];
}
else if (dataGridView1.CurrentRow != null && dataGridView1.CurrentRow.Index == dataGridView1.Rows.Count - 1 && dataGridView1.CurrentRow.Index != 0)
{
dataGridView1.CurrentCell = dataGridView1.Rows[0].Cells[0];
}
}
//当按向上箭头
else if (args.KeyCode == Keys.Up)
{
args.SuppressKeyPress = true;
dataGridView1.Focus();
if (dataGridView1.CurrentRow != null && dataGridView1.CurrentRow.Index != 0)
{
dataGridView1.CurrentCell = dataGridView1.Rows[dataGridView1.CurrentRow.Index - 1].Cells[0];
}
else if (dataGridView1.CurrentRow != null && dataGridView1.CurrentRow.Index == 0 && dataGridView1.CurrentRow.Index != dataGridView1.Rows.Count - 1)
{
dataGridView1.CurrentCell = dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[0];
}
}
//当按回车
else if (args.KeyCode == Keys.Enter && dataGridView1.Rows.Count > 0)
{
dataGridView1_DoubleClick(sender, args);
}
};
value.Leave += (sender, args) => Close();
//首次刷新
FilterValue = value.Text;
Refresh();
value.Focus();
_listenerControl = value;
}
}
get { return _listenerControl; }
}
private void timer1_Tick(object sender, EventArgs e)
{
Location = new Point(_listenerControl.Location.X + Owner.Location.X + 8,
_listenerControl.Location.Y + Owner.Location.Y + 53);
if (_isTextChanged)
{
_isTextChanged = false;
timer1.Enabled = false;
FilterValue = _listenerControl.Text;
Refresh();
timer1.Enabled = true;
}
}