Windowsアプリケーションで[Enter]キーによるフォーカス移動を行うには?.NET TIPS

» 2004年11月19日 05時00分 公開
[一色政彦デジタルアドバンテージ]
.NET TIPS
Insider.NET


「.NET TIPS」のインデックス

連載目次

 Windowsアプリケーションでは、[Tab]キーだけでなく[Enter]キーによるコントロール間のフォーカス移動処理を要求されることがよくある。一般ユーザーにとっては、普段あまり使わない[Tab]キーよりも[Enter]キーの方が押しやすく、利便性が向上するからである。

 本稿では、このような[Enter]キーでフォーカス移動する処理の実装方法を紹介する。

[Enter]キーによるコントロール間のフォーカス移動

 といってもその実装は難しくはない。フォーム上の各コントロールについてKeyDownイベント・ハンドラを追加し、そのイベント・ハンドラ内で[Enter]キーが押されたときの処理として、次のいずれかのメソッドを呼び出せばよい。これらのメソッドはいずれも、別のコントロールにフォーカスを移動させるためのものだ。

 この2つのメソッドでは、ProcessTabKeyメソッドの方が呼び出しが単純で簡単だが、オプションとして指定できる機能(Bool値のパラメータにより指定)は、前方向に移動するか(True)/後方向に移動するか(False)、しかない。それに比べてSelectNextControlメソッドの方はかなり細かくフォーカス移動処理を制御できる。例えば、TabStopプロパティがFalseに設定されているコントロールへの移動や、入れ子になったコントロールには移動させないといった制御が可能だ(詳しくは、MSDNライブラリの「SelectNextControlメソッド」を参照してほしい)。

 フォーカス移動の方向については、通常ならば[Enter]キーを押すと前方向にフォーカスが進む。これに加えて、[Enter]キーが押されると同時に[Shift]キーが押されている場合(つまり[Shift]+[Enter]キーの場合)に逆方向(後方向)へフォーカス移動させたいなら、次のコードのように条件判定したうえでフォーカス移動の方向を決定すればよい。

// C#
bool forward = e.Modifiers != Keys.Shift;


' VB.NET
Dim forward As Boolean = e.Modifiers <> Keys.Shift


 上記コードの「e」はKeyDownイベント・ハンドラのパラメータで渡されるKeyEventArgsオブジェクト(System.Windows.Forms名前空間)である。KeyEventArgsオブジェクトのModifiersプロパティでは、同時に押し下げられている修飾子キー([Ctrl]キー、[Shift]キー、[Alt]キー)を取得できる。つまり上記のコードでは、Keys列挙体(System.Windows.Forms名前空間)の値「Shift」を使って、[Shift]キーが押されていないかを確認している。[Shift]キーが押されていなければ前方向へのフォーカス移動フラグ「forward」がTrueとなり、押されていればFalseとなる。この値をProcessTabKeyメソッドやSelectNextControlメソッドのパラメータに指定すれば、前方向へフォーカス移動するか、後方向に移動するかを、[Shift]キーの押し下げ状況に合わせて変更できる。

[Enter]キーの一括処理

 コントロールごとにKeyDownイベント・ハンドラを追加して上記の処理を実装すれば、[Enter]キー押し下げるとコントロール間をフォーカス移動するようになる。しかし、それではコントロールを追加・削除するたびに同様の処理を実装しなければならない。そこで「TIPS:コントロールに対するキー入力をフォームで処理するには?」で紹介した方法を使って、フォームのKeyDownイベント・ハンドラで[Enter]キーの一括処理を行うようにしよう。これにより、コントロールの追加・削除で発生する作業が不要となる。

 以下のコードは、実際にフォームのKeyDownイベント・ハンドラで、[Enter]キー押し下げるとコントロール間のフォーカス移動を行う処理を実装したものだ。なお、「TIPS:コントロールに対するキー入力をフォームで処理するには?」で解説しているように、事前にフォームのKeyPreviewプロパティをTrueに設定しておく必要がある。

private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
  if (e.KeyCode == Keys.Enter)
  {
    bool forward = e.Modifiers != Keys.Shift;
    //this.ProcessTabKey(forward);
    this.SelectNextControl(this.ActiveControl, forward, true, true, true);
    e.Handled = true;
  }
}

[Enter]キーでフォーカス移動するサンプル・コード(C#)

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
  If e.KeyCode = Keys.Enter Then
    Dim forward As Boolean =  e.Modifiers <>  Keys.Shift
    'Me.ProcessTabKey(forward);
    Me.SelectNextControl(Me.ActiveControl, forward, True, True, True)
    e.Handled = True
  End If
End Sub

[Enter]キーでフォーカス移動するサンプル・コード(VB.NET)

 上記コードにあるKeyEventArgsオブジェクト「e」のHandledプロパティは、イベントを処理したかどうかを設定するためのものだ。このコード例では、[Enter]キーのイベントを処理済みとして、HandledプロパティにTrueを設定している。これにより、コントロール側のKeyDownイベント・ハンドラは呼び出されなくなる(HandledプロパティはデフォルトでFalseのため、通常は親フォームのKeyDownイベント・ハンドラが呼び出されたあと、子コントロールのKeyDownイベント・ハンドラが呼び出される)。SelectNextControlメソッドのパラメータで指定している、フォームのActiveControlプロパティは、現在アクティブな(フォーム上の)コントロールを取得するためのものである。

[Enter]キーによるフォーカス移動処理のスキップ

 コントロールがデフォルト機能として[Enter]キーを処理する場合、そのコントロールでは[Enter]キーによるフォーカス移動はさせたくないだろう。例えば、複数行の入力が可能なTextBoxコントロールならば[Enter]キーで改行処理が行われるので、[Enter]キーによるフォーカス移動はさせたくない。このような場合、フォーカス移動させたくないコントロールをそのクラスの種類(型)により判別し、フォーカス移動の処理から外すようにすればよいだろう。次にその記述例を示す。

private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
  if (e.KeyCode == Keys.Enter)
  {
    bool bThrough = false;
    if (this.ActiveControl is TextBox)
    {
      if (((TextBox)this.ActiveControl).Multiline == true)
      {
        bThrough = true;
      }
    }

    if (bThrough == false)
    {
      bool forward = e.Modifiers != Keys.Shift;
      //this.ProcessTabKey(forward);
      this.SelectNextControl(this.ActiveControl, forward, true, true, true);
    }
  }
}

一部のコントロールに対して[Enter]キーによるフォーカス移動が行われないようにするサンプル・コード(C#)

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
  If e.KeyCode = Keys.Enter Then
    Dim bThrough As BooleanFalse
    If TypeOf Me.ActiveControl Is TextBox Then
      If (CType(Me.ActiveControl,TextBox)).Multiline = True Then
        bThrough = True
      End If
    End If

    If bThrough = False Then
      Dim forward As Boolean =  e.Modifiers <>  Keys.Shift
      'this.ProcessTabKey(forward);
      Me.SelectNextControl(Me.ActiveControl, forward, True, True, True)
    End If
  End If
End Sub

一部のコントロールに対して[Enter]キーによるフォーカス移動が行われないようにするサンプル・コード(VB.NET)

 コントロールの種類(型)を判別するには、is演算子(C#)/TypeOf…Is式(VB.NET)を使えばよい。上記コードでは、キー処理中のコントロール(=アクティブなコントロール)がTextBoxコントロールであるかを判別し、それがTextBoxコントロールの場合には、そのMultiLineプロパティがTrueかどうか(つまり、TextBoxコントロールが複数行対応であるかどうか)を確認している。MultiLineプロパティがTrueの場合(つまり複数行対応の場合)には[Enter]キーによるフォーカス移動は行われない。

 ちなみに、Buttonコントロールも[Enter]キーによるフォーカス移動が必要でない場合が多いが、Buttonコントロールの場合は(デフォルト設定のままでは)[Enter]キーによるKeyDownイベントが発生しないようである。そのため、Buttonコントロールについては[Enter]キーによるフォーカス移動処理をスキップするためのコードは不要だ。

カテゴリ:Windowsフォーム 処理対象:キーボード
使用ライブラリ:KeyEventArgsオブジェクト(System.Windows.Forms名前空間)
使用ライブラリ:Keys列挙体(System.Windows.Forms名前空間)
関連TIPS:コントロールに対するキー入力をフォームで処理するには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。