一,需求
在Winform中,默認情況下,按下Tab鍵,光標會按照我們設定的TabIndex值從小到大進行跳轉。
但如果用戶要求按下Tab鍵跳轉到特定的控件,這種要求還是很合理的,比如用戶只想輸入幾個必須填的項目。
我們可以在配置文件中配置這些必須填寫的項目,並設定他們的跳轉順序。這樣程序也更加靈活,利於擴展。
二,探索實現方法
1,在每個輸入控件的keyDown事件里判斷是Tab鍵,做相應的跳轉處理。
最后調查發現按下Tab鍵,並不會觸發控件keyDown事件,Tab鍵默認被系統處理了,悲劇了。
另外,輸入項目太多的時候,這個做法工作量也太大了,不可行。
2,找一個全局點控制,而不分散到每個控件來處理。
方法就是利用Form本身的ProcessCmdKey方法。
看代碼吧,備注已經寫的很明白了
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,在實際應用中應該從配置文件中讀取。