先日、子供の出生届に行ってきたわけですが、まだまだ古いパソコンを使っていましたお役所さん。出生届もインターネット越しでもいいんじゃない?と思ったり、思わなかったりしたのですが、ひょいと、パソコンの画面を見ると懐かしのDOS画面でありました。
役所関係や事務関係では、まだまだ強いですよね、この手のインターフェース。
そんな訳で「タブキーで次のフォーカスに移ればいいじゃん」と思っても「エンターキー(Enter Key)で次のフォーカスに移りたい」訳で、そこには、Silverlight とか、WPF とか、WEB やら jQuery やらの話は出てきません。ひたすら、今の業務にそろえたい訳です。
という訳で、UXってのが「ユーザー体験」ならば、かつてのDOS画面風を再現させたっていいじゃないと思いついたのがこの画面。
<001>
って、バックを「黒」にして、文字を「緑」にしただけなんですが、もうちょっと工夫が必要ですよね。
- MS ゴシックのフォントでは字がつぶれるので、もっと適切な固定ピッチフォントで。
- アルファベット&数字が、きれい過ぎる感じがするので、そのあたりも。
とか。
で、真っ先に実装したいのが Enter キーによるフォーカス移動です。
Enter キーのフォーカス移動は、落とし穴が多くって、少なくとも、
・複数行のテキストボックスが入ると破綻する。
・漢字の確定の Enter キーと、アルファベットの入力途中の Enter キーを区別する。
・1行のテキストボックスだと、Enter キーでビープ音が鳴る仕様。
があります。
複数行のテキストボックスの場合は、かつての画面ってこのパターンはなかったんですよ、考えてみれば。DOSで業務画面を作る場合は、テキストのスクロールとかもなくて、大抵の場合、複数行の入力なんてのもありません。
となれば、ちょっと、業務画面チックに Enter キーを変えていくのも良いかと。
{ public partial class Form1 : Form { public Form1() { InitializeComponent(); #if true // ひとつずつ登録する場合 ekm = new EnterKeyManager(); ekm.ProcessTabKeyEvent += new EnterKeyManager.EnterKeyEventHandler(ekm_SampleEvent); ekm.Add(textBox1); ekm.Add(textBox2); ekm.Add(textBox3); ekm.Add(textBox4); ekm.Add(textBox5); ekm.Add(textBox6); ekm.Add(textBox7); ekm.Add(button1); #else // 全てのコントロールを登録する場合 ekm = new EnterKeyManager(); ekm.ProcessTabKeyEvent += new EnterKeyManager.EnterKeyEventHandler(ekm_SampleEvent); ekm.SetForm(this); #endif } // Enterキーの制御クラス EnterKeyManager ekm; // タブ移動のイベント void ekm_SampleEvent(object sender, bool b) { this.ProcessTabKey(b); } } /// <summary> /// Enterキーで移動させるためのクラス /// </summary> public class EnterKeyManager { private List<Control> m_lst = new List<Control>(); private bool imeEnter = false; /// <summary> /// コンストラクタ /// </summary> public EnterKeyManager() { } // テキストボックスを追加 public void Add(TextBox ctrl) { ctrl.PreviewKeyDown += new PreviewKeyDownEventHandler(ctrl_PreviewKeyDown); ctrl.KeyUp += new KeyEventHandler(ctrl_KeyUp); ctrl.KeyPress += new KeyPressEventHandler(ctrl_KeyPress); m_lst.Add(ctrl); } // テキスト以外を追加 public void Add(Control ctrl) { ctrl.KeyUp += new KeyEventHandler(ctrl_KeyUp); m_lst.Add(ctrl); } // テキストボックスでEnterを押した時、BEEPが鳴るのを防ぐ void ctrl_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)Keys.Enter) { e.Handled = true; } } // タブキー移動のハンドラ public delegate void EnterKeyEventHandler(object sender, bool b); // Declare the event. public event EnterKeyEventHandler ProcessTabKeyEvent; // Enterキーの処理 void ctrl_KeyUp(object sender, KeyEventArgs e) { if (ProcessTabKeyEvent == null) return; if (e.KeyCode == Keys.Enter) { TextBox t = sender as TextBox; if (t == null) { ProcessTabKeyEvent(sender, !e.Shift); } else { if (e.Shift) { ProcessTabKeyEvent(sender, !e.Shift); e.Handled = true; } else { if (imeEnter == true) { ProcessTabKeyEvent(sender, !e.Shift); e.Handled = true; } imeEnter = false; } } } } // 日本語の変換確定のEnterを区別する処理 private void ctrl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { TextBox t = sender as TextBox; if (t != null) { if (e.KeyData == Keys.Enter) { imeEnter = true; } } } // フォームから全てのコントロールを設定する public void SetForm( Form frm ) { foreach (Control c in frm.Controls) { TextBox t = c as TextBox; if (t != null) { this.Add(t); } else { this.Add(c); } } } } }
EnterKeyManager クラスってのを作ってしまいます。
このクラスに、Enter キーで移動したいコントロールを Add メソッドで登録していくか、面倒な場合は Form そのものを渡してしまうか。
ひとずつ登録する場合は
ekm = new EnterKeyManager(); ekm.ProcessTabKeyEvent += new EnterKeyManager.EnterKeyEventHandler(ekm_SampleEvent); ekm.Add(textBox1); ekm.Add(textBox2); ekm.Add(textBox3); ekm.Add(textBox4); ekm.Add(textBox5); ekm.Add(textBox6); ekm.Add(textBox7); ekm.Add(button1);
フォームにあるコントロールを一括で登録する場合は
ekm = new EnterKeyManager(); ekm.ProcessTabKeyEvent += new EnterKeyManager.EnterKeyEventHandler(ekm_SampleEvent); ekm.SetForm(this);
イベントで、ProcessTabKeyEvent を登録しているのは、フォーカス移動のメソッド ProcessTabKey を呼び出すためなんですね。ProcessTabKey メソッドが protected になっているので、こんな風にしています。
リフレクションを使えば EnterKeyManager クラスに抑え込むことができるかもしれませんが、まあ、ひとまず。
// Enterキーの制御クラス EnterKeyManager ekm; // タブ移動のイベント void ekm_SampleEvent(object sender, bool b) { this.ProcessTabKey(b); }
な感じで、イベントを受けたら呼び出してくださいということで。
エンターキーのフォーカス移動では、漢字の変換を確定したときの Enter キーと区別するのが結構面倒なので、晒しておきます。
電話番号入力とか、数字のみとか、フォントを固定ピッチにしてよりDOSらしくとか、ちょっと作ってみようかな、と思案中です。
■参考サイト
Enterキーを押した時に、まるでTabキーを押した時のように、次のコントロールにフォーカスを移す: .NET Tips: C#, VB.NET, Visual Studio
http://dobon.net/vb/dotnet/control/enterliketab.html#section1
全ては時の中に… : 【VB.NET】Enterキーで次のコントロールにフォーカスを移す
http://blog.livedoor.jp/akf0/archives/51318097.html#
@IT:.NET TIPS Windowsアプリケーションで[Enter]キーによるフォーカス移動を行うには? – C# VB.NET Windowsフォーム
http://www.atmarkit.co.jp/fdotnet/dotnettips/231winentermove/winentermove.html
単一行テキストボックスでEnterやEscapeキーを押した時にビープ音が鳴らないようにする: .NET Tips: C#, VB.NET, Visual Studio
http://dobon.net/vb/dotnet/control/tbsuppressbeep.html
未確定文字列は反転色、なんて演出も欲しいですね(^^)
「演出」ってw
そうですね。コマンドプロンプトで漢字変換すると、青地に白文字。
一太郎の場合は、水色に白文字だった覚えが。