【C#】EnterキーでTabキーを押した時と全く同じフォーカス遷移を行う
EnterキーでTabキーを押した時と同じフォーカス遷移を行いたいという要望は、案外多い。
古いシステムからの名残りだったり、そもそも提案した人が古い人だったりで。
果てはWebシステムでもそれを望むこともあるが、今回はWindows Formsアプリケーションの場合の解決方法を記す。
Enterキーでフォーカス遷移する方法は、難しく考えすぎて意外とハマる。
他のサイトで調べた結果、最適解を導き出した。
参考サイト
Enterキーを押した時、まるでTabキーを押したかのように、次のコントロールにフォーカスを移す - .NET Tips (VB.NET,C#...)
色々あって全部試したわけではないが、コンポーネント単位に継承するのは非効率。
コメント欄に[たきる]ってなってるのは俺^^;
Windowsアプリケーションで[Enter]キーによるフォーカス移動を行うには?:.NET TIPS - @IT
C# - フォームで [Enter] キーが押された時にフォーカスを遷移させる
SelectNextControlメソッドを利用すると、『自分のオブジェクト配下に存在するコントロールを遷移する』だけであり、Tabキーと全く同じにはならない。
主なハマる点
基本的には、参考サイトにある方法論でも問題ない。
しかし、SplitContainerを利用した途端、『Tabキーを押した時と全く同じ』とはならない。
例えばこんな状態のフォーム内容の場合。(TextBox内の値が、Tabキー押下時に遷移するタブ順)
解決策
これが最も適切に動作すると思う。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// ダイアログ キーを処理します。 /// </summary> /// <param name="keyData">処理するキーを表す Keys 値の 1 つ。</param> /// <returns>キーがコントロールによって処理された場合は true。それ以外の場合は false。</returns> protected override bool ProcessDialogKey(Keys keyData) { // Enterキー押下によるフォーカス移動 if (((keyData & Keys.KeyCode) == Keys.Return) && ((keyData & (Keys.Alt | Keys.Control)) == Keys.None)) { this.MoveNextControl(); return true; } return base.ProcessDialogKey(keyData); } /// <summary> /// 次のコントロールをアクティブにします。 /// </summary> /// <param name="forward">タブオーダー内を前方に移動する場合はtrue。後方に移動する場合はfalse。</param> public void MoveNextControl(bool forward = true) { if (forward) { SendKeys.Send("{TAB}"); } else { SendKeys.Send("+{TAB}"); } } } }
MultilineプロパティがtrueのTextBoxは、Ctrl+Enterで改行される。
MoveNextControl()メソッドは、SelectNextControl()メソッドの『Tabキー押下版』。
このロジックを実装したフォームを継承してアプリを作ることで、面倒なことが起こらない。
EnterFocusプロパティなどを設けて、trueの時だけ処理するとか、継承元で考慮しておけば楽。
2017/05/26 追記
TextBoxBase.AcceptsTabをtrueにしたコントロール上で行うと、Tab入力になってしまう。
ここは要検討かもしれない。
2018/05/10 追記
TextBoxBase.AcceptsTabをtrueのコントロールの場合、Ctrl+TabまたはCtrl+Shift+Tabでタブ遷移が行われるため、
SendKeys.Send("^{TAB}");、SendKeys.Send("^+{TAB}");で対応できる。
public void MoveNextControl(bool forward = true) { // control は Form.ActiveControlなどを使った、現在フォーカスのあるコントロール var textBox = GetTextBox(control); if (textBox != null && textBox.Multiline && textBox.AcceptsTab) { if (forward) { SendKeys.Send("^{TAB}"); } else { SendKeys.Send("^+{TAB}"); } return; } // その他コントロール if (forward) { SendKeys.Send("{TAB}"); } else { SendKeys.Send("+{TAB}"); } } // 対象コントロールからアクティブなTextBoxオブジェクトを取得 private static TextBox GetTextBox(Control control) { var targetControl = control as TextBox; if (targetControl != null) { return targetControl; } var form = control as Form; if (form == null) { return null; } targetControl = form.ActiveControl as TextBox; if (targetControl != null) { return targetControl; } var splitContainer = form.ActiveControl as SplitContainer; targetControl = splitContainer?.ActiveControl as TextBox; if (targetControl != null) { return targetControl; } return null; }