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

ステータスバーに現在の日時やCaps Lockなどの状態を表示する

VB6などでは、StatusBarのパネルのスタイルを変更することにより、文字列表示以外に、現在の日付、時間や、Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockキーの状態を簡単に表示することができます。ここでは、これと同じことを.NET Frameworkで行う方法を紹介します。

目的を達成するためには、以下の問題を解決する必要がありそうです。

  1. ステータスバーに文字列を表示するには?
  2. 現在の日時を文字列で取得するには?
  3. 現在のCaps Lock等のキーの状態を知るには?
  4. 現在の日時やCaps Lockキーの状態をどのタイミングでステータスバーに表示すればよいのか?

この内、ステータスバーに文字列を表示する方法は「ステータスバーに文字列を表示する」で説明しています。現在の日時を取得する方法は「現在の日時を取得する」で、日時を文字列に変換する方法は「日時(DateTimeオブジェクト)を文字列に変換する」で説明しています。Caps Lockなどのキーの状態を知る方法は「Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockキーの状態を取得する」で説明しています。

難しいのが、現在の日時やキー状態の情報をどのタイミングでステータスバーに表示すればよいのかという点です。適当なタイミングで発生してくれるイベントがあればよいのですが、そう都合良くは行きません。

このような時は、タイマーを使ってステータスバーの情報を更新する必要があるかを定期的にチェックします。例えばCaps Lockの状態を表示する場合は、タイマーでCaps Lockの状態を定期的(数百ミリ秒間隔位が適当でしょう)に調べ、状態が変わった時にステータスバーの表示を更新します。

StatusStripを使用した具体例

以上の説明で目的は果たせましたが、念の為に具体的なコードを示します。

下の例では、「Form1」という名前のフォームにステータスバー(StatusStrip)を設置して、現在の日時とCaps Lockの状態を表示しています。このコードはForm1クラス内に記述されているものとします。

現在の日時とCaps Lockの状態が表示されたステータスバー

この例では、StatusStripなどの必要なコントロールをすべて動的に(コードで)作成していますが、もちろんこれらのコントロールをVisual Studioのフォームデザイナで作成して利用する方法でも構いません。

また、この例ではStatusStripコントロールを使用しているため、.NET Framework 2.0以降にしか対応していません。.NET Framework 1.1の場合は、お手数ですが、上記の説明(「ステータスバーに文字列を表示する」と「Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockキーの状態を取得する」)を参考にして書き換えてください。

VB.NET
コードを隠すコードを選択
'ステータスバーとなるStatusStrip
Private statusStripBar As StatusStrip
'現在の日時を表示するToolStripStatusLabel
Private toolStripStatusDateTime As ToolStripStatusLabel
'Caps Lockの状態を表示するToolStripStatusLabel
Private toolStripStatusCapsLock As ToolStripStatusLabel
'ステータスバーを更新するためのタイマー
Private timerUpdateStatusStrip As Timer
'現在のCaps Lockの状態
Private currentCapsLocked As Boolean = False

'Form1のLoadイベントハンドラ
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'StatusStripを作成する
    statusStripBar = New StatusStrip()
    'toolStripStatusDateTimeとtoolStripStatusCapsLockを追加する
    toolStripStatusDateTime = New ToolStripStatusLabel()
    toolStripStatusCapsLock = New ToolStripStatusLabel()
    statusStripBar.Items.AddRange(New ToolStripItem() { _
                                  toolStripStatusDateTime, _
                                  toolStripStatusCapsLock})
    'StatusStripをフォームに配置する
    Me.Controls.Add(statusStripBar)

    'タイマーを作成する
    timerUpdateStatusStrip = New Timer()
    timerUpdateStatusStrip.Interval = 100
    timerUpdateStatusStrip.Enabled = True
    AddHandler timerUpdateStatusStrip.Tick, _
        AddressOf timerUpdateStatusStrip_Tick
End Sub

'Form1のFormClosedイベントハンドラ
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs)
    If timerUpdateStatusStrip IsNot Nothing Then
        timerUpdateStatusStrip.Dispose()
    End If
End Sub

'タイマーのTickイベントハンドラ
Private Sub timerUpdateStatusStrip_Tick(sender As Object, e As EventArgs)
    '現在の日時を更新する
    UpdateDateTimeStatusBar()
    '現在のCaps Lockの状態を更新する
    UpdateCapsLockStatusBar()
End Sub

'現在の日時を更新する
Private Sub UpdateDateTimeStatusBar()
    '現在の日時を取得する
    Dim nowTime As DateTime = DateTime.Now
    '日時を文字列に変換する
    Dim newText As String = nowTime.ToString()
    '表示する文字列が前と違う場合は、更新する
    If Not toolStripStatusDateTime.Text.Equals(newText, _
            StringComparison.Ordinal) Then
        toolStripStatusDateTime.Text = newText
    End If
End Sub

'現在のCaps Lockの状態を更新する
Private Sub UpdateCapsLockStatusBar()
    '現在のCaps Lockの状態を取得する
    Dim newLocked As Boolean = Control.IsKeyLocked(Keys.CapsLock)
    'Caps Lockの状態が前と違う場合は、表示を更新する
    If Me.currentCapsLocked <> newLocked Then
        toolStripStatusCapsLock.Text = GetCapsLockStatusString(newLocked)
        Me.currentCapsLocked = newLocked
    End If
End Sub

'Caps Lockの状態を表す文字列を返す
Private Function GetCapsLockStatusString(isLocked As Boolean) As String
    Return If(isLocked, "CAPS", "")
End Function
C#
コードを隠すコードを選択
//using System;
//using System.Windows.Forms;

//ステータスバーとなるStatusStrip
StatusStrip statusStripBar;
//現在の日時を表示するToolStripStatusLabel
ToolStripStatusLabel toolStripStatusDateTime;
//Caps Lockの状態を表示するToolStripStatusLabel
ToolStripStatusLabel toolStripStatusCapsLock;
//ステータスバーを更新するためのタイマー
Timer timerUpdateStatusStrip;
//現在のCaps Lockの状態
bool currentCapsLocked = false;

//Form1のLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //StatusStripを作成する
    statusStripBar = new StatusStrip();
    //toolStripStatusDateTimeとtoolStripStatusCapsLockを追加する
    toolStripStatusDateTime = new ToolStripStatusLabel();
    toolStripStatusCapsLock = new ToolStripStatusLabel();
    statusStripBar.Items.AddRange(new ToolStripItem[]
    {
        toolStripStatusDateTime,
        toolStripStatusCapsLock
    });
    //StatusStripをフォームに配置する
    this.Controls.Add(statusStripBar);

    //タイマーを作成する
    timerUpdateStatusStrip = new Timer();
    timerUpdateStatusStrip.Interval = 100;
    timerUpdateStatusStrip.Enabled = true;
    timerUpdateStatusStrip.Tick += timerUpdateStatusStrip_Tick;
}

//Form1のFormClosedイベントハンドラ
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    if (timerUpdateStatusStrip != null)
    {
        timerUpdateStatusStrip.Dispose();
    }
}

//タイマーのTickイベントハンドラ
private void timerUpdateStatusStrip_Tick(object sender, EventArgs e)
{
    //現在の日時を更新する
    UpdateDateTimeStatusBar();
    //現在のCaps Lockの状態を更新する
    UpdateCapsLockStatusBar();
}

//現在の日時を更新する
private void UpdateDateTimeStatusBar()
{
    //現在の日時を取得する
    DateTime nowTime = DateTime.Now;
    //日時を文字列に変換する
    string newText = nowTime.ToString();
    //表示する文字列が前と違う場合は、更新する
    if (!toolStripStatusDateTime.Text.Equals(newText,
        StringComparison.Ordinal))
    {
        toolStripStatusDateTime.Text = newText;
    }
}

//現在のCaps Lockの状態を更新する
private void UpdateCapsLockStatusBar()
{
    //現在のCaps Lockの状態を取得する
    bool newLocked = Control.IsKeyLocked(Keys.CapsLock);
    //Caps Lockの状態が前と違う場合は、表示を更新する
    if (this.currentCapsLocked != newLocked)
    {
        toolStripStatusCapsLock.Text = GetCapsLockStatusString(newLocked);
        this.currentCapsLocked = newLocked;
    }
}

//Caps Lockの状態を表す文字列を返す
private string GetCapsLockStatusString(bool isLocked)
{
    return isLocked ? "CAPS" : "";
}

現在の日時をStatusStripに表示するToolStripItemを作成する

これ以降は、おまけのおまけです。興味のある方のみ参考にしてください。

上記の例はフォームクラスに色々なコードを書かなければならず、面倒ですし、きれいでもありません。

StatusStripコントロールに何か表示する時、ToolStripItemを自作すると、これをStatusStripコントロールに追加するだけで済みますので、非常に楽になります。

現在の日時をStatusStripに表示するためのToolStripItemを自作する例を以下に示します。使い方は、後述します。

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

''' <summary>
''' 現在の時刻を表示するToolStripItemです。
''' </summary>
<ToolStripItemDesignerAvailability( _
    ToolStripItemDesignerAvailability.StatusStrip)> _
Public Class ToolStripStatusDateTime
    Inherits ToolStripStatusLabel
    ''' <summary>
    ''' タイマー
    ''' </summary>
    Private _timer As Timer

    Private _format As String
    ''' <summary>
    ''' 表示する日時のフォーマット
    ''' </summary>
    <System.Configuration.DefaultSettingValue("")> _
    Public Property Format() As String
        Get
            Return _format
        End Get
        Set(value As String)
            _format = value
        End Set
    End Property

    'Textを外部から設定できないようにする
    <System.ComponentModel.Browsable(False)> _
    Public Overrides Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
        End Set
    End Property

    Public Sub New()
        '初期化
        Format = ""
        MyBase.Text = GetFormattedDateTimeText()
        'タイマーを作成
        _timer = New Timer()
        _timer.Interval = 100
        'Tickイベントハンドラの追加
        AddHandler _timer.Tick, New EventHandler(AddressOf _timer_Tick)
        _timer.Enabled = True
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposing AndAlso _timer IsNot Nothing Then
            _timer.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private Sub _timer_Tick(sender As Object, e As EventArgs)
        'Textを更新する
        UpdateText()
    End Sub

    '必要ならば、Textを更新する
    Private Sub UpdateText()
        '現在の日時を表す文字列を取得する
        Dim newText As String = Me.GetFormattedDateTimeText()
        '表示する文字列が更新された時、Textを変更する
        If Not MyBase.Text.Equals(newText, StringComparison.Ordinal) Then
            MyBase.Text = newText
        End If
    End Sub

    '現在の日時を文字列に変換する
    Private Function GetFormattedDateTimeText() As String
        Return DateTime.Now.ToString(Format)
    End Function
End Class
C#
コードを隠すコードを選択
using System;
using System.Windows.Forms;
using System.Windows.Forms.Design;

/// <summary>
/// 現在の時刻を表示するToolStripItemです。
/// </summary>
[ToolStripItemDesignerAvailability(
    ToolStripItemDesignerAvailability.StatusStrip)]
public class ToolStripStatusDateTime : ToolStripStatusLabel
{
    /// <summary>
    /// タイマー
    /// </summary>
    private Timer _timer;

    private string _format;
    /// <summary>
    /// 表示する日時のフォーマット
    /// </summary>
    [System.Configuration.DefaultSettingValue("")]
    public string Format
    {
        set { _format = value; }
        get { return _format; }
    }

    //Textを外部から設定できないようにする
    [System.ComponentModel.Browsable(false)]
    public override string Text
    {
        get { return base.Text; }
        set { }
    }

    public ToolStripStatusDateTime()
    {
        //初期化
        Format = "";
        base.Text = GetFormattedDateTimeText();
        //タイマーを作成
        _timer = new Timer();
        _timer.Interval = 100;
        //Tickイベントハンドラの追加
        _timer.Tick += new EventHandler(_timer_Tick);
        _timer.Enabled = true;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _timer != null)
        {
            _timer.Dispose();
        }
        base.Dispose(disposing);
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        //Textを更新する
        UpdateText();
    }

    //必要ならば、Textを更新する
    private void UpdateText()
    {
        //現在の日時を表す文字列を取得する
        string newText = this.GetFormattedDateTimeText();
        //表示する文字列が更新された時、Textを変更する
        if (!base.Text.Equals(newText, StringComparison.Ordinal))
        {
            base.Text = newText;
        }
    }

    //現在の日時を文字列に変換する
    private string GetFormattedDateTimeText()
    {
        return DateTime.Now.ToString(Format);
    }
}

このToolStripStatusDateTimeクラスは、Visual StudioのフォームデザイナでStatusStripにToolStripItemを追加する時に、StatusLabelなどと一緒に表示されますので、簡単に使用することができます。

ToolStripStatusDateTime

よく分からないという場合は、自作のToolStripItemを使用する方法について「ToolStrip(ツールバー、メニュー、ステータスバー)に任意のコントロールを配置する」や「自作したToolStripItemをVisual Studioのデザイナで表示する」でも説明していますので、これらを参考にしてください。

また、日時をどのような形式(フォーマット)で表示するかを、ToolStripStatusDateTimeクラスのFormatプロパティで設定できるようにしています。フォーマットについて詳しくは、「日時(DateTimeオブジェクト)を文字列に変換する」をご覧ください。

現在のキー状態をStatusStripに表示するToolStripItemを作成する

次は、Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockの状態を表示するToolStripItemの例を示します。使い方は、先ほどのToolStripStatusDateTimeクラスとほぼ同じです。

デフォルトではCaps Lockの状態が表示されますが、別のキーの状態を表示する場合は、KeyStyleプロパティの値を変更してください。

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

''' <summary>
''' 現在のキーロック状態を表示するToolStripItemです。
''' </summary>
<ToolStripItemDesignerAvailability( _
    ToolStripItemDesignerAvailability.StatusStrip)> _
Public Class ToolStripStatusKeyState
    Inherits ToolStripStatusLabel
    ''' <summary>
    ''' ToolStripStatusKeyStateに表示できるキーの種類を表します。
    ''' </summary>
    Public Enum KeyStatePanelStyle
        CapsLock = Keys.CapsLock
        Insert = Keys.Insert
        NumLock = Keys.NumLock
        ScrollLock = Keys.Scroll
        KanaLock = Keys.KanaMode
    End Enum

    ''' <summary>
    ''' タイマー
    ''' </summary>
    Private _timer As Timer

    Private _keyStatePanelStyle As KeyStatePanelStyle
    ''' <summary>
    ''' 状態を表示するキーの種類を取得、設定します。
    ''' </summary>
    <System.Configuration.DefaultSettingValue("CapsLock")> _
    Public Property KeyStyle() As KeyStatePanelStyle
        'Textを更新する
        Get
            Return _keyStatePanelStyle
        End Get
        Set(value As KeyStatePanelStyle)
            _keyStatePanelStyle = value
            UpdateText(True)
        End Set
    End Property

    'Textを外部から設定できないようにする
    <System.ComponentModel.Browsable(False)> _
    Public Overrides Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
        End Set
    End Property

    '現在のキーの状態
    Private currentLocked As Boolean

    Public Sub New()
        '状態を表示するキーの種類を設定
        KeyStyle = KeyStatePanelStyle.CapsLock
        'タイマーを作成
        _timer = New Timer()
        _timer.Interval = 100
        'Tickイベントハンドラの追加
        AddHandler _timer.Tick, New EventHandler(AddressOf _timer_Tick)
        _timer.Enabled = True
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposing AndAlso _timer IsNot Nothing Then
            _timer.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private Sub _timer_Tick(sender As Object, e As EventArgs)
        'Textを更新する
        UpdateText(False)
    End Sub

    '必要ならば、Textを更新する
    Private Sub UpdateText(forced As Boolean)
        '現在のキーの状態を取得する
        Dim newLocked As Boolean = CheckIsLocked()
        If forced OrElse currentLocked <> newLocked Then
            'Textを更新する
            MyBase.Text = GetKeyStateText(newLocked)
            currentLocked = newLocked
        End If
    End Sub

    'キー状態を取得する
    Private Function CheckIsLocked() As Boolean
        If KeyStyle = KeyStatePanelStyle.KanaLock Then
            'Kana Lockの状態はControl.IsKeyLockedで取得できない
            Return IsKeyStateLocked(CType(KeyStyle, Keys))
        Else
            Return Control.IsKeyLocked(CType(KeyStyle, Keys))
        End If
    End Function

    'キー状態に応じた、Textに表示する文字列を返す
    Private Function GetKeyStateText(isLocked As Boolean) As String
        If isLocked Then
            Select Case KeyStyle
                Case KeyStatePanelStyle.CapsLock
                    Return "CAPS"
                Case KeyStatePanelStyle.Insert
                    Return "INS"
                Case KeyStatePanelStyle.NumLock
                    Return "NUM"
                Case KeyStatePanelStyle.ScrollLock
                    Return "SCRL"
                Case KeyStatePanelStyle.KanaLock
                    Return "カナ"
                Case Else
                    Return ""
            End Select
        Else
            Return ""
        End If
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Private Shared Function GetKeyState(nVirtKey As Integer) As Short
    End Function

    ''' <summary>
    ''' トグルキーの状態がオンであるかを調べます。
    ''' </summary>
    ''' <param name="keyVal">調べるキー。</param>
    ''' <returns>キーの状態がオンであれば、True。</returns>
    Public Shared Function IsKeyStateLocked(keyVal As Keys) As Boolean
        Return (GetKeyState(CInt(keyVal)) And 1) = 1
    End Function
End Class
C#
コードを隠すコードを選択
using System;
using System.Windows.Forms;
using System.Windows.Forms.Design;

/// <summary>
/// 現在のキーロック状態を表示するToolStripItemです。
/// </summary>
[ToolStripItemDesignerAvailability(
    ToolStripItemDesignerAvailability.StatusStrip)]
public class ToolStripStatusKeyState : ToolStripStatusLabel
{
    /// <summary>
    /// ToolStripStatusKeyStateに表示できるキーの種類を表します。
    /// </summary>
    public enum KeyStatePanelStyle
    {
        CapsLock = Keys.CapsLock,
        Insert = Keys.Insert,
        NumLock = Keys.NumLock,
        ScrollLock = Keys.Scroll,
        KanaLock = Keys.KanaMode
    }

    /// <summary>
    /// タイマー
    /// </summary>
    private Timer _timer;

    private KeyStatePanelStyle _keyStatePanelStyle;
    /// <summary>
    /// 状態を表示するキーの種類を取得、設定します。
    /// </summary>
    [System.Configuration.DefaultSettingValue("CapsLock")]
    public KeyStatePanelStyle KeyStyle
    {
        set
        {
            _keyStatePanelStyle = value;
            //Textを更新する
            UpdateText(true);
        }
        get { return _keyStatePanelStyle; }
    }

    //Textを外部から設定できないようにする
    [System.ComponentModel.Browsable(false)]
    public override string Text
    {
        get { return base.Text; }
        set { }
    }

    //現在のキーの状態
    private bool currentLocked;

    public ToolStripStatusKeyState()
    {
        //状態を表示するキーの種類を設定
        KeyStyle = KeyStatePanelStyle.CapsLock;
        //タイマーを作成
        _timer = new Timer();
        _timer.Interval = 100;
        //Tickイベントハンドラの追加
        _timer.Tick += new EventHandler(_timer_Tick);
        _timer.Enabled = true;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _timer != null)
        {
            _timer.Dispose();
        }
        base.Dispose(disposing);
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        //Textを更新する
        UpdateText(false);
    }

    //必要ならば、Textを更新する
    private void UpdateText(bool forced)
    {
        //現在のキーの状態を取得する
        bool newLocked = CheckIsLocked();
        if (forced || currentLocked != newLocked)
        {
            //Textを更新する
            base.Text = GetKeyStateText(newLocked);
            currentLocked = newLocked;
        }
    }

    //キー状態を取得する
    private bool CheckIsLocked()
    {
        if (KeyStyle == KeyStatePanelStyle.KanaLock)
        {
            //Kana Lockの状態はControl.IsKeyLockedで取得できない
            return IsKeyStateLocked((Keys)KeyStyle);
        }
        else
        {
            return Control.IsKeyLocked((Keys)KeyStyle);
        }
    }

    //キー状態に応じた、Textに表示する文字列を返す
    private string GetKeyStateText(bool isLocked)
    {
        if (isLocked)
        {
            switch (KeyStyle)
            {
                case KeyStatePanelStyle.CapsLock:
                    return "CAPS";
                case KeyStatePanelStyle.Insert:
                    return "INS";
                case KeyStatePanelStyle.NumLock:
                    return "NUM";
                case KeyStatePanelStyle.ScrollLock:
                    return "SCRL";
                case KeyStatePanelStyle.KanaLock:
                    return "カナ";
                default:
                    return "";
            }
        }
        else
        {
            return "";
        }
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern short GetKeyState(int nVirtKey);

    /// <summary>
    /// トグルキーの状態がオンであるかを調べます。
    /// </summary>
    /// <param name="keyVal">調べるキー。</param>
    /// <returns>キーの状態がオンであれば、True。</returns>
    public static bool IsKeyStateLocked(Keys keyVal)
    {
        return (GetKeyState((int)keyVal) & 1) == 1;
    }
}

現在の日時をStatusBarに表示するパネルを作成する

.NET Framework 1.1以前では、ステータスバーにStatusBarコントロールしか使えません。しかしこの場合でも、StatusBarPanelを自作することができます。

以下に、StatusBarコントロールに現在の時間を表示するStatusBarPanelの例を示します。使い方は、後述します。

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

''' <summary>
''' 現在の時刻を表示するStatusBarPanelです。
''' </summary>
Public Class DateTimePanel
    Inherits StatusBarPanel
    ''' <summary>
    ''' タイマー
    ''' </summary>
    Private _timer As Timer

    Private _format As String
    ''' <summary>
    ''' 表示する日時のフォーマット
    ''' </summary>
    Public Property Format() As String
        Get
            Return _format
        End Get
        Set(value As String)
            _format = value
        End Set
    End Property

    'Textを外部から設定できないようにする
    Public Shadows Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
        End Set
    End Property

    Public Sub New()
        '幅を内容に合わせる
        Me.AutoSize = StatusBarPanelAutoSize.Contents
        '初期化
        Format = ""
        'タイマーを作成
        _timer = New Timer()
        _timer.Interval = 100
        'Tickイベントハンドラの追加
        AddHandler _timer.Tick, New EventHandler(AddressOf _timer_Tick)
        _timer.Enabled = True
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposing AndAlso Not (_timer Is Nothing) Then
            _timer.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private Sub _timer_Tick(sender As Object, e As EventArgs)
        'Textを更新する
        UpdateText()
    End Sub

    '必要ならば、Textを更新する
    Private Sub UpdateText()
        '現在の日時を表す文字列を取得する
        Dim newText As String = Me.GetFormattedDateTimeText()
        '表示する文字列が更新された時、Textを変更する
        If Not MyBase.Text.Equals(newText) Then
            MyBase.Text = newText
        End If
    End Sub

    '現在の日時を文字列に変換する
    Private Function GetFormattedDateTimeText() As String
        Return DateTime.Now.ToString(Format)
    End Function
End Class
C#
コードを隠すコードを選択
using System;
using System.Windows.Forms;

/// <summary>
/// 現在の時刻を表示するStatusBarPanelです。
/// </summary>
public class DateTimePanel : StatusBarPanel
{
    /// <summary>
    /// タイマー
    /// </summary>
    private Timer _timer;

    private string _format;
    /// <summary>
    /// 表示する日時のフォーマット
    /// </summary>
    public string Format
    {
        set { _format = value; }
        get { return _format; }
    }

    //Textを外部から設定できないようにする
    public new string Text
    {
        get { return base.Text; }
        set { }
    }

    public DateTimePanel()
    {
        //幅を内容に合わせる
        this.AutoSize = StatusBarPanelAutoSize.Contents;
        //初期化
        Format = "";
        //タイマーを作成
        _timer = new Timer();
        _timer.Interval = 100;
        //Tickイベントハンドラの追加
        _timer.Tick += new EventHandler(_timer_Tick);
        _timer.Enabled = true;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _timer != null)
        {
            _timer.Dispose();
        }
        base.Dispose(disposing);
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        //Textを更新する
        UpdateText();
    }

    //必要ならば、Textを更新する
    private void UpdateText()
    {
        //現在の日時を表す文字列を取得する
        string newText = this.GetFormattedDateTimeText();
        //表示する文字列が更新された時、Textを変更する
        if (!base.Text.Equals(newText))
        {
            base.Text = newText;
        }
    }

    //現在の日時を文字列に変換する
    private string GetFormattedDateTimeText()
    {
        return DateTime.Now.ToString(Format);
    }
}

このDateTimePanelを使用する具体例を示します。ここでは、StatusBarコントロールはすでにフォームに配置されており、名前は「StatusBar1」であるとします。このコードは、フォームのLoadイベントハンドラや、コンストラクタの最後などに記述してください。

VB.NET
コードを隠すコードを選択
'StatusBarのパネルを表示する
StatusBar1.ShowPanels = True

'DateTimePanelの作成
Dim dtp As New DateTimePanel()
'StatusBar1に追加する
StatusBar1.Panels.Add(dtp)
C#
コードを隠すコードを選択
//StatusBarのパネルを表示する
StatusBar1.ShowPanels = true;

//DateTimePanelの作成
DateTimePanel dtp = new DateTimePanel();
//StatusBar1に追加する
StatusBar1.Panels.Add(dtp);

現在のキー状態をStatusBarに表示するパネルを作成する

次に、現在のキー状態をStatusBarに表示するStatusBarPanelを自作する例を示します。使い方は、先ほどのDateTimePanelとほぼ同じです。

デフォルトではCaps Lockの状態が表示されますが、別のキーの状態を表示する場合は、KeyStyleプロパティの値を変更してください。

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

''' <summary>
''' 現在のキーロック状態を表示するStatusBarPanelです。
''' </summary>
Public Class KeyStatePanel
    Inherits StatusBarPanel

    ''' <summary>
    ''' ToolStripStatusKeyStateに表示できるキーの種類を表します。
    ''' </summary>
    Public Enum KeyStatePanelStyle
        CapsLock = Keys.CapsLock
        Insert = Keys.Insert
        NumLock = Keys.NumLock
        ScrollLock = Keys.Scroll
        KanaLock = Keys.KanaMode
    End Enum

    ''' <summary>
    ''' タイマー
    ''' </summary>
    Private _timer As Timer

    Private _keyStatePanelStyle As KeyStatePanelStyle
    ''' <summary>
    ''' 状態を表示するキーの種類を取得、設定します。
    ''' </summary>
    Public Property KeyStyle() As KeyStatePanelStyle
        'Textを更新する
        Get
            Return _keyStatePanelStyle
        End Get
        Set(value As KeyStatePanelStyle)
            _keyStatePanelStyle = value
            UpdateText(True)
        End Set
    End Property

    'Textを外部から設定できないようにする
    Public Shadows Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
        End Set
    End Property

    '現在のキーの状態
    Private currentLocked As Boolean

    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <param name="styl">状態を表示するキーの種類</param>
    Public Sub New(styl As KeyStatePanelStyle)
        '状態を表示するキーの種類を設定
        KeyStyle = styl
        'タイマーを作成
        _timer = New Timer()
        _timer.Interval = 100
        'Tickイベントハンドラの追加
        AddHandler _timer.Tick, New EventHandler(AddressOf _timer_Tick)
        _timer.Enabled = True
    End Sub

    Public Sub New()
        Me.New(KeyStatePanelStyle.CapsLock)
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposing AndAlso Not (_timer Is Nothing) Then
            _timer.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private Sub _timer_Tick(sender As Object, e As EventArgs)
        'Textを更新する
        UpdateText(False)
    End Sub

    '必要ならば、Textを更新する
    Private Sub UpdateText(forced As Boolean)
        '現在のキーの状態を取得する
        Dim newLocked As Boolean = CheckIsLocked()
        If forced OrElse currentLocked <> newLocked Then
            'Textを更新する
            MyBase.Text = GetKeyStateText(newLocked)
            currentLocked = newLocked
        End If
    End Sub

    'キー状態を取得する
    Private Function CheckIsLocked() As Boolean
        Return IsKeyStateLocked(CType(KeyStyle, Keys))
    End Function

    'キー状態に応じた、Textに表示する文字列を返す
    Private Function GetKeyStateText(isLocked As Boolean) As String
        If isLocked Then
            Select Case KeyStyle
                Case KeyStatePanelStyle.CapsLock
                    Return "CAPS"
                Case KeyStatePanelStyle.Insert
                    Return "INS"
                Case KeyStatePanelStyle.NumLock
                    Return "NUM"
                Case KeyStatePanelStyle.ScrollLock
                    Return "SCRL"
                Case KeyStatePanelStyle.KanaLock
                    Return "カナ"
                Case Else
                    Return ""
            End Select
        Else
            Return ""
        End If
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Private Shared Function GetKeyState(nVirtKey As Integer) As Short
    End Function

    ''' <summary>
    ''' トグルキーの状態がオンであるかを調べます。
    ''' </summary>
    ''' <param name="keyVal">調べるキー。</param>
    ''' <returns>キーの状態がオンであれば、True。</returns>
    Public Shared Function IsKeyStateLocked(keyVal As Keys) As Boolean
        Return (GetKeyState(CInt(keyVal)) And 1) = 1
    End Function
End Class
C#
コードを隠すコードを選択
using System;
using System.Windows.Forms;

/// <summary>
/// 現在のキーロック状態を表示するStatusBarPanelです。
/// </summary>
public class KeyStatePanel : StatusBarPanel
{
    /// <summary>
    /// ToolStripStatusKeyStateに表示できるキーの種類を表します。
    /// </summary>
    public enum KeyStatePanelStyle
    {
        CapsLock = Keys.CapsLock,
        Insert = Keys.Insert,
        NumLock = Keys.NumLock,
        ScrollLock = Keys.Scroll,
        KanaLock = Keys.KanaMode
    }

    /// <summary>
    /// タイマー
    /// </summary>
    private Timer _timer;

    private KeyStatePanelStyle _keyStatePanelStyle;
    /// <summary>
    /// 状態を表示するキーの種類を取得、設定します。
    /// </summary>
    public KeyStatePanelStyle KeyStyle
    {
        set
        {
            _keyStatePanelStyle = value;
            //Textを更新する
            UpdateText(true);
        }
        get { return _keyStatePanelStyle; }
    }

    //Textを外部から設定できないようにする
    public new string Text
    {
        get { return base.Text; }
        set { }
    }

    //現在のキーの状態
    private bool currentLocked;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="styl">状態を表示するキーの種類</param>
    public KeyStatePanel(KeyStatePanelStyle styl)
    {
        //状態を表示するキーの種類を設定
        KeyStyle = styl;
        //タイマーを作成
        _timer = new Timer();
        _timer.Interval = 100;
        //Tickイベントハンドラの追加
        _timer.Tick += new EventHandler(_timer_Tick);
        _timer.Enabled = true;
    }

    public KeyStatePanel()
        : this(KeyStatePanelStyle.CapsLock)
    {
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _timer != null)
        {
            _timer.Dispose();
        }
        base.Dispose(disposing);
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        //Textを更新する
        UpdateText(false);
    }

    //必要ならば、Textを更新する
    private void UpdateText(bool forced)
    {
        //現在のキーの状態を取得する
        bool newLocked = CheckIsLocked();
        if (forced || currentLocked != newLocked)
        {
            //Textを更新する
            base.Text = GetKeyStateText(newLocked);
            currentLocked = newLocked;
        }
    }

    //キー状態を取得する
    private bool CheckIsLocked()
    {
        return IsKeyStateLocked((Keys)KeyStyle);
    }

    //キー状態に応じた、Textに表示する文字列を返す
    private string GetKeyStateText(bool isLocked)
    {
        if (isLocked)
        {
            switch (KeyStyle)
            {
                case KeyStatePanelStyle.CapsLock:
                    return "CAPS";
                case KeyStatePanelStyle.Insert:
                    return "INS";
                case KeyStatePanelStyle.NumLock:
                    return "NUM";
                case KeyStatePanelStyle.ScrollLock:
                    return "SCRL";
                case KeyStatePanelStyle.KanaLock:
                    return "カナ";
                default:
                    return "";
            }
        }
        else
        {
            return "";
        }
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern int GetKeyState(int nVirtKey);

    /// <summary>
    /// トグルキーの状態がオンであるかを調べます。
    /// </summary>
    /// <param name="keyVal">調べるキー。</param>
    /// <returns>キーの状態がオンであれば、True。</returns>
    public static bool IsKeyStateLocked(Keys keyVal)
    {
        return (GetKeyState((int)keyVal) & 1) == 1;
    }
}
  • 履歴:
  • 2006/11/10 UpdateTextメソッドを修正。
  • 2013/6/13 今までの本文をほぼ全ておまけのおまけに移動して、説明を書き直した。Application.Idleイベントを使わないコードに書き換えた。

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

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。