DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

現在アクティブな(選択されている、フォーカスのある)コントロールを取得する、指定したコントロールをアクティブにする

ここでは、現在アクティブな(選択されている、フォーカスのある)コントロールを取得する方法と、指定したコントロールをアクティブにする(選択する、フォーカスを移動させる)方法について説明します。

現在アクティブなコントロールを取得する

現在アクティブなコントロールを取得するには、ContainerControl.ActiveControlプロパティを使用します。

フォームクラス内で、現在アクティブなコントロールを取得する例を示します。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

'現在アクティブなコントロールを取得する
Dim c As Control = f.ActiveControl

If Not (c Is Nothing) Then
    Console.WriteLine("現在アクティブなコントロールは、{0}です。", c.Name)
Else
    Console.WriteLine("現在アクティブなコントロールはありません。")
End If
C#
コードを隠すコードを選択
//using System.Windows.Forms;

//現在アクティブなコントロールを取得する
Control c = f.ActiveControl;

if (c != null)
{
    Console.WriteLine("現在アクティブなコントロールは、{0}です。", c.Name);
}
else
{
    Console.WriteLine("現在アクティブなコントロールはありません。");
}

MSDNの「ContainerControl.ActiveControlプロパティ」によると、「あるフォームから別のフォームの ActiveControl プロパティを呼び出すと、未定義の値が返されます。 この場合、このデータを受け渡すための独自のコミュニケーション機構をフォーム間に定義する必要があります。」とのことです。私が試した限りでは、別フォームのActiveControlプロパティも有効な値を返すように見えましたが、注意が必要です。

SplitContainerコントロール上のアクティブコントロールを取得できない問題

フォームにSplitContainerコントロールが配置されており、SplitContainer上にあるコントロールがアクティブな時、フォームのActiveControlプロパティはそのコントロールを返さずに、SplitContainerコントロールを返します。この時、正しいアクティブコントロールを取得するには、SplitContainerのActiveControlプロパティを使用します。

SplitContainerコントロール上にアクティブコントロールがあっても、SplitContainerではなく、そのコントロールを返すメソッドの例を示します。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

''' <summary>
''' アクティブコントロールを取得する
''' </summary>
''' <param name="parentControl">
''' アクティブコントロールを探す元のコンテナコントロール
''' </param>
''' <returns>アクティブコントロール</returns>
''' <example>
''' 自分自身のフォームのアクティブコントロールを取得する例
''' <code>
''' Dim c As Control = GetRealActiveControl(Me)
''' </code>
''' </example>
Public Shared Function GetRealActiveControl( _
        parentControl As ContainerControl) As Control
    'ActiveControlプロパティを取得
    Dim ac As Control = parentControl.ActiveControl
    'ActiveControlがNULLの時は、コンテナコントロールを返す
    If ac Is Nothing Then
        Return parentControl
    End If
    'ActiveControlがコンテナコントロールの場合は、さらにActiveControlを取得
    If TypeOf ac Is ContainerControl Then
        Return GetRealActiveControl(DirectCast(ac, ContainerControl))
    End If
    Return ac
End Function
C#
コードを隠すコードを選択
//using System.Windows.Forms;

/// <summary>
/// アクティブコントロールを取得する
/// </summary>
/// <param name="parentControl">
/// アクティブコントロールを探す元のコンテナコントロール
/// </param>
/// <returns>アクティブコントロール</returns>
/// <example>
/// 自分自身のフォームのアクティブコントロールを取得する例
/// <code>
/// Control c = GetRealActiveControl(this);
/// </code>
/// </example>
public static Control GetRealActiveControl(ContainerControl parentControl)
{
    //ActiveControlプロパティを取得
    Control ac = parentControl.ActiveControl;
    //ActiveControlがNULLの時は、コンテナコントロールを返す
    if (ac == null)
    {
        return parentControl;
    }
    //ActiveControlがコンテナコントロールの場合は、さらにActiveControlを取得
    if (ac is ContainerControl)
    {
        return GetRealActiveControl((ContainerControl)ac);
    }
    return ac;
}

このような方法以外に、後述する、フォーム上のすべてのコントロールのFocusedプロパティを調べるという方法でも可能です。

あるコントロールがアクティブであるか調べる

あるコントロールがアクティブであるかは、Control.Focusedプロパティで調べることができます。

VB.NET
コードを隠すコードを選択
If TextBox1.Focused Then
    Console.WriteLine("TextBox1にフォーカスがあります。")
Else
    Console.WriteLine("TextBox1にフォーカスがありません。")
End If
C#
コードを隠すコードを選択
if (TextBox1.Focused)
    Console.WriteLine("TextBox1にフォーカスがあります。");
else
    Console.WriteLine("TextBox1にフォーカスがありません。");

そのコントロールか、そのコントロール内にある子コントロールにフォーカスがあるかどうかは、Control.ContainsFocusプロパティで調べることができます。

以下に示すメソッドは、指定したコントロール内にあるすべてのコントロールを調べ、FocusedプロパティがTrueのコントロールを返しています。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

''' <summary>
''' 指定されたコントロール内にあるコントロールで、
''' FocusedプロパティがTrueのコントロールを返す
''' </summary>
''' <param name="parentControl">基になるコントロール</param>
''' <returns>FocusedプロパティがTrueのコントロール</returns>
Public Shared Function GetForcusedControl( _
        parentControl As Control) As Control
    'コントロール内のコントロールを列挙する
    Dim c As Control
    For Each c In parentControl.Controls
        'FocusedがTrueの時、そのコントロールを返す
        If c.Focused Then
            Return c
        End If
        '子コントロールにフォーカスがある時
        If c.ContainsFocus Then
            'さらにコントロール内のコントロールを調べる
            Dim fc As Control = GetForcusedControl(c)
            If Not (fc Is Nothing) Then
                Return fc
            End If
        End If
    Next
    '見つからなかった場合は、NULLを返す
    Return Nothing
End Function
C#
コードを隠すコードを選択
//using System.Windows.Forms;

/// <summary>
/// 指定されたコントロール内にあるコントロールで、
/// FocusedプロパティがTrueのコントロールを返す
/// </summary>
/// <param name="parentControl">基になるコントロール</param>
/// <returns>FocusedプロパティがTrueのコントロール</returns>
public static Control GetForcusedControl(Control parentControl)
{
    //コントロール内のコントロールを列挙する
    foreach (Control c in parentControl.Controls)
    {
        //FocusedがTrueの時、そのコントロールを返す
        if (c.Focused)
        {
            return c;
        }
        //子コントロールにフォーカスがある時
        if (c.ContainsFocus)
        {
            //さらにコントロール内のコントロールを調べる
            Control fc = GetForcusedControl(c);
            if (fc != null)
            {
                return fc;
            }
        }
    }
    //見つからなかった場合は、NULLを返す
    return null;
}

指定したコントロールをアクティブにする

指定したコントロールをアクティブにするための方法はいくつかあります。

最も基本的な方法は、Control.Selectメソッドを呼び出す方法です。例えば、TextBox1をアクティブにするには、次のようにします。

VB.NET
コードを隠すコードを選択
'TextBox1をアクティブにする
TextBox1.Select()
C#
コードを隠すコードを選択
//TextBox1をアクティブにする
TextBox1.Select();
補足:コントロールには、アクティブにすることのできないコントロールもあります。アクティブにできないコントロールは、Panel、GroupBox、PictureBox、ProgressBar、、Splitter、Label、リンクが存在しないLinkLabelなどです。また、コントロール(または、親コントロール)のEnabledかVisibleプロパティがFalseになっている時もアクティブになりません。あるコントロールをアクティブにできるかを調べるには、Control.CanSelectプロパティを使用します。

また、アクティブにしたいコントロールをContainerControl.ActiveControlプロパティに設定するという方法もあります。

例えば、フォームにあるTextBox1をフォームクラスからアクティブにするには、次のようにします。

VB.NET
コードを隠すコードを選択
'TextBox1をアクティブにする
Me.ActiveControl = TextBox1
C#
コードを隠すコードを選択
//TextBox1をアクティブにする
this.ActiveControl = TextBox1;

Control.Focusメソッドを使用してもほぼ同じことができます。しかし、MSDNによると、「Focus は、主にカスタム コントロールの作成者が使用するための下位メソッドです」とのことです。

VB.NET
コードを隠すコードを選択
'TextBox1をアクティブにする
TextBox1.Focus()
C#
コードを隠すコードを選択
//TextBox1をアクティブにする
TextBox1.Focus();
補足:上記の方法でSplitContainerコントロールをアクティブにしようとした時、ActiveControlとFocusではSplitContainerコントロールの分割線が選択された状態になりますが、Selectは分割線が選択状態にならず、SplitContainerコントロール内のコントロールがアクティブになります。

次のタブオーダーのコントロールをアクティブにする

次のタブオーダーのコントロールをアクティブにする方法は、「次のタブオーダーのコントロールをアクティブに(選択、フォーカスを移動)する」で説明しています。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。