最近在用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;
}
}