役所風にEnterキーで次のテキストボックスへ移動

先日、子供の出生届に行ってきたわけですが、まだまだ古いパソコンを使っていましたお役所さん。出生届もインターネット越しでもいいんじゃない?と思ったり、思わなかったりしたのですが、ひょいと、パソコンの画面を見ると懐かしのDOS画面でありました。

役所関係や事務関係では、まだまだ強いですよね、この手のインターフェース。

そんな訳で「タブキーで次のフォーカスに移ればいいじゃん」と思っても「エンターキー(Enter Key)で次のフォーカスに移りたい」訳で、そこには、Silverlight とか、WPF とか、WEB やら jQuery やらの話は出てきません。ひたすら、今の業務にそろえたい訳です。

という訳で、UXってのが「ユーザー体験」ならば、かつてのDOS画面風を再現させたっていいじゃないと思いついたのがこの画面。

<001>

20100901_08.jpg

って、バックを「黒」にして、文字を「緑」にしただけなんですが、もうちょっと工夫が必要ですよね。

  • 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

カテゴリー: 開発 パーマリンク

役所風にEnterキーで次のテキストボックスへ移動 への2件のフィードバック

  1. ふたみ のコメント:

    未確定文字列は反転色、なんて演出も欲しいですね(^^)

  2. t.masuda のコメント:

    「演出」ってw

    そうですね。コマンドプロンプトで漢字変換すると、青地に白文字。
    一太郎の場合は、水色に白文字だった覚えが。

コメントは停止中です。