控制WinForm中Tab鍵的跳轉

一,需求

在Winform中,默認狀況下,按下Tab鍵,光標會按照咱們設定的TabIndex值從小到大進行跳轉。ide

但若是用戶要求按下Tab鍵跳轉到特定的控件,這種要求仍是很合理的,好比用戶只想輸入幾個必須填的項目。函數

咱們能夠在配置文件中配置這些必須填寫的項目,並設定他們的跳轉順序。這樣程序也更加靈活,利於擴展。this

二,探索實現方法

1,在每一個輸入控件的keyDown事件裏判斷是Tab鍵,作相應的跳轉處理。

最後調查發現按下Tab鍵,並不會觸發控件keyDown事件,Tab鍵默認被系統處理了,悲劇了。spa

另外,輸入項目太多的時候,這個作法工做量也太大了,不可行。code

2,找一個全局點控制,而不分散到每一個控件來處理。

方法就是利用Form自己的ProcessCmdKey方法。orm

看代碼吧,備註已經寫的很明白了blog

  Dictionary<string, string> tabMap = new Dictionary<string, string>();

        private void InitTabMap()
        {
            // 加入From,To的控件名稱,表示按下Tab鍵從From跳掉To位置
            tabMap.Add("textBox3", "textBox7");
            tabMap.Add("textBox7", "textBox8");
        }

        /// <summary>
        /// 這個重載函數裏能夠預先捕捉到一些按鍵,好比被系統默認捕獲了的Tab鍵
        /// 若是要改寫Tab鍵的默認動做,要返回true,表示你已經處理過這個按鍵了
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            Control ctl = this.ActiveControl;
            if (keyData == Keys.Tab)
            {
                if (ctl != null && tabMap.Keys.Contains(ctl.Name))
                {
                    var toCtrls = this.Controls.Find(tabMap[ctl.Name], true);
                    if (toCtrls.Length > 0)
                    {
                        //檢查父容器是不是隱藏的
                        ActivieParentContainerIfNeeded(toCtrls[0]);
                        toCtrls[0].Focus();
                        //確實得到了焦點,再吞噬這個按鍵動做
                        if (toCtrls[0].Focused)
                        {
                            return true;
                        }
                    }
                }
            }
            bool ret = base.ProcessCmdKey(ref msg, keyData);
            return ret;
        }
        /// <summary>
        /// 有一些控件隱藏在了TabControl的後面,形成Focus不成功。
        /// 由於這些控件的Visible爲False,必須先使他們的父控件TabPage先選中
        /// </summary>
        /// <param name="child"></param>
        private void ActivieParentContainerIfNeeded(Control child)
        {
            if (child.Visible)
            {
                return;
            }
            Control parent = child.Parent;
            while (parent != null)
            {
                if (parent is TabPage)
                {
                    break;
                }
                parent = parent.Parent;
            }

            if (parent is TabPage)
            {
                TabControl tabCtrl = (TabControl)parent.Parent;
                tabCtrl.SelectedTab = (parent as TabPage);
            }
        }

上面的tabMap,在實際應用中應該從配置文件中讀取。事件

相關文章
相關標籤/搜索