VB6などでは、StatusBarのパネルのスタイルを変更することにより、文字列表示以外に、現在の日付、時間や、Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockキーの状態を簡単に表示することができます。ここでは、これと同じことを.NET Frameworkで行う方法を紹介します。
目的を達成するためには、以下の問題を解決する必要がありそうです。
この内、ステータスバーに文字列を表示する方法は「ステータスバーに文字列を表示する」で説明しています。現在の日時を取得する方法は「現在の日時を取得する」で、日時を文字列に変換する方法は「日時(DateTimeオブジェクト)を文字列に変換する」で説明しています。Caps Lockなどのキーの状態を知る方法は「Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockキーの状態を取得する」で説明しています。
難しいのが、現在の日時やキー状態の情報をどのタイミングでステータスバーに表示すればよいのかという点です。適当なタイミングで発生してくれるイベントがあればよいのですが、そう都合良くは行きません。
このような時は、タイマーを使ってステータスバーの情報を更新する必要があるかを定期的にチェックします。例えばCaps Lockの状態を表示する場合は、タイマーでCaps Lockの状態を定期的(数百ミリ秒間隔位が適当でしょう)に調べ、状態が変わった時にステータスバーの表示を更新します。
以上の説明で目的は果たせましたが、念の為に具体的なコードを示します。
下の例では、「Form1」という名前のフォームにステータスバー(StatusStrip)を設置して、現在の日時とCaps Lockの状態を表示しています。このコードはForm1クラス内に記述されているものとします。
この例では、StatusStripなどの必要なコントロールをすべて動的に(コードで)作成していますが、もちろんこれらのコントロールをVisual Studioのフォームデザイナで作成して利用する方法でも構いません。
また、この例ではStatusStripコントロールを使用しているため、.NET Framework 2.0以降にしか対応していません。.NET Framework 1.1の場合は、お手数ですが、上記の説明(「ステータスバーに文字列を表示する」と「Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockキーの状態を取得する」)を参考にして書き換えてください。
'ステータスバーとなる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
//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コントロールに追加するだけで済みますので、非常に楽になります。
現在の日時をStatusStripに表示するためのToolStripItemを自作する例を以下に示します。使い方は、後述します。
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
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などと一緒に表示されますので、簡単に使用することができます。
よく分からないという場合は、自作のToolStripItemを使用する方法について「ToolStrip(ツールバー、メニュー、ステータスバー)に任意のコントロールを配置する」や「自作したToolStripItemをVisual Studioのデザイナで表示する」でも説明していますので、これらを参考にしてください。
また、日時をどのような形式(フォーマット)で表示するかを、ToolStripStatusDateTimeクラスのFormatプロパティで設定できるようにしています。フォーマットについて詳しくは、「日時(DateTimeオブジェクト)を文字列に変換する」をご覧ください。
次は、Caps Lock、Num Lock、Insert、Scroll Lock、Kana Lockの状態を表示するToolStripItemの例を示します。使い方は、先ほどのToolStripStatusDateTimeクラスとほぼ同じです。
デフォルトではCaps Lockの状態が表示されますが、別のキーの状態を表示する場合は、KeyStyleプロパティの値を変更してください。
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
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; } }
.NET Framework 1.1以前では、ステータスバーにStatusBarコントロールしか使えません。しかしこの場合でも、StatusBarPanelを自作することができます。
以下に、StatusBarコントロールに現在の時間を表示するStatusBarPanelの例を示します。使い方は、後述します。
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
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イベントハンドラや、コンストラクタの最後などに記述してください。
'StatusBarのパネルを表示する StatusBar1.ShowPanels = True 'DateTimePanelの作成 Dim dtp As New DateTimePanel() 'StatusBar1に追加する StatusBar1.Panels.Add(dtp)
//StatusBarのパネルを表示する StatusBar1.ShowPanels = true; //DateTimePanelの作成 DateTimePanel dtp = new DateTimePanel(); //StatusBar1に追加する StatusBar1.Panels.Add(dtp);
次に、現在のキー状態をStatusBarに表示するStatusBarPanelを自作する例を示します。使い方は、先ほどのDateTimePanelとほぼ同じです。
デフォルトではCaps Lockの状態が表示されますが、別のキーの状態を表示する場合は、KeyStyleプロパティの値を変更してください。
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
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; } }
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。