先日、子供の出生届に行ってきたわけですが、まだまだ古いパソコンを使っていましたお役所さん。出生届もインターネット越しでもいいんじゃない?と思ったり、思わなかったりしたのですが、ひょいと、パソコンの画面を見ると懐かしの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
そうですね。コマンドプロンプトで漢字変換すると、青地に白文字。
一太郎の場合は、水色に白文字だった覚えが。