WinForm提示建議小工具【keydown\keyup\keypress】

--2013-11-17

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


 





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章