先日、子供の出生届に行ってきたわけですが、まだまだ古いパソコンを使っていましたお役所さん。出生届もインターネット越しでもいいんじゃない?と思ったり、思わなかったりしたのですが、ひょいと、パソコンの画面を見ると懐かしのDOS画面でありました。
役所関係や事務関係では、まだまだ強いですよね、この手のインターフェース。
そんな訳で「タブキーで次のフォーカスに移ればいいじゃん」と思っても「エンターキー(Enter Key)で次のフォーカスに移りたい」訳で、そこには、Silverlight とか、WPF とか、WEB やら jQuery やらの話は出てきません。ひたすら、今の業務にそろえたい訳です。
という訳で、UXってのが「ユーザー体験」ならば、かつてのDOS画面風を再現させたっていいじゃないと思いついたのがこの画面。
<001>
って、バックを「黒」にして、文字を「緑」にしただけなんですが、もうちょっと工夫が必要ですよね。
- MS ゴシックのフォントでは字がつぶれるので、もっと適切な固定ピッチフォントで。
- アルファベット&数字が、きれい過ぎる感じがするので、そのあたりも。
とか。
で、真っ先に実装したいのが Enter キーによるフォーカス移動です。
Enter キーのフォーカス移動は、落とし穴が多くって、少なくとも、
・複数行のテキストボックスが入ると破綻する。
・漢字の確定の Enter キーと、アルファベットの入力途中の Enter キーを区別する。
・1行のテキストボックスだと、Enter キーでビープ音が鳴る仕様。
があります。
複数行のテキストボックスの場合は、かつての画面ってこのパターンはなかったんですよ、考えてみれば。DOSで業務画面を作る場合は、テキストのスクロールとかもなくて、大抵の場合、複数行の入力なんてのもありません。
となれば、ちょっと、業務画面チックに Enter キーを変えていくのも良いかと。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | { 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 そのものを渡してしまうか。
ひとずつ登録する場合は
1 2 3 4 5 6 7 8 9 10 | 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); |
フォームにあるコントロールを一括で登録する場合は
1 2 3 | ekm = new EnterKeyManager(); ekm.ProcessTabKeyEvent += new EnterKeyManager.EnterKeyEventHandler(ekm_SampleEvent); ekm.SetForm( this ); |
イベントで、ProcessTabKeyEvent を登録しているのは、フォーカス移動のメソッド ProcessTabKey を呼び出すためなんですね。ProcessTabKey メソッドが protected になっているので、こんな風にしています。
リフレクションを使えば EnterKeyManager クラスに抑え込むことができるかもしれませんが、まあ、ひとまず。
1 2 3 4 5 6 7 | // 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
そうですね。コマンドプロンプトで漢字変換すると、青地に白文字。
一太郎の場合は、水色に白文字だった覚えが。