所有的文本框,不管單行多行都Ctrl-A全選就好了吧?是啊,很方便。Windows的軟件基本都是這樣。可為什么我們自己制作的WinForm就默認不是這樣呢?誰知道呢,可能是WinForm飽受詬病,要改變一下,不想再封裝太多默認功能吧。反正程序員自己加這點功能也不難。
好了,以上是YY。接下來正式開始。
一開始,我在自己的WinForm的某個文本框內按Ctrl-A,它沒有全選,而且發出“噔”一聲,提醒我按了一個無效的按鍵。於是很簡單的,加了以下代碼,實現了“這一個”文本框的Ctrl-A實現全選功能。
private void TextBox_KeyPress(object sender, KeyPressEventArgs e) { TextBox textBox = sender as TextBox; if (textBox == null) return; if (e.KeyChar == (char)1) // Ctrl-A 相當於輸入了AscII=1的控制字符 { textBox.SelectAll(); e.Handled = true; // 不再發出“噔”的聲音 } }
並由屬性編輯器或自己在代碼中實現了事件的注冊: textBox.KeyPress += TextBox_KeyPress;
這樣就完事了,真是“這點事”。等等,如果我有30個TextBox不是要寫30行注冊代碼?能不能寫個什么一次搞定,整個WinForm內的所有TextBox都支持Ctrl-A,最好連動態加載的TextBox也支持。於是我在Form的ControlAdded事件中判斷如果新添加的Control是TextBox則注冊KeyPress事件處理方法。
private void Control_ControlAdded(object sender, ControlEventArgs e) { TextBox textBox = e.Control as TextBox; if (textBox != null) { textBox.KeyPress += TextBox_KeyPress; } } public Form1() { this.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.Control_ControlAdded); InitializeComponent(); }
代碼運行后,發現部分TextBox有效果,部分沒效果。經過調試,發現,直接跟在WinForm(Form1)的有效果,在用戶控件(UserControl)中的TextBox則無效果。對照一下代碼,是啊,我還應該處理UserControl的ControlAdded事件,哦不,是所有Control的ControlAdded事件。而且控件還會包含控件,所有子子孫孫控件都注冊這個事件,這樣任何新添加的控件都會被判斷是否為TextBox,於是Control_ControlAdded變成這個樣子:
private void Control_ControlAdded(object sender, ControlEventArgs e) { //使“未來”生效 e.Control.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.Control_ControlAdded); //使“子孫”生效 foreach (Control c in e.Control.Controls) { Control_ControlAdded(sender, new ControlEventArgs(c)); } //使“過去”生效 TextBox textBox = e.Control as TextBox; if (textBox != null) { textBox.KeyPress += TextBox_KeyPress; } }
經測試,通過。一勞永逸地解決了這個問題,從此不再為這個問題而費神。
2016-04-27補充:在最終版本的Control_ControlAdded方法加上3行注釋,從時空的角度來描述原理,讓各位看明白它的覆蓋范圍。由於同時處理了過去和未來,所以 this.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.Control_ControlAdded); 這一句不一定要放在 InitializeComponent(); 之前。放哪都行,執行后就整個Form(this)的TextBox有效。