タスクトレイにアイコンを表示する方法について

Cc440880.download(ja-jp,MSDN.10).gif サンプル コードのダウンロード (vbmigtips_NotifyIcon.exe, 98.7 KB)

アプリケーションを起動したとき、フォームを表示せずにアプリケーションを常駐させ、タスクトレイにアイコンを表示させたい場合があります。そこで今回は、タスクトレイにアイコンを表示する (図1) 方法について紹介します。今回、タスクトレイに表示されたアイコンからフォームを開いたりプロジェクトを終了したりする処理も実装します。

 Cc440880.NotifyIcon_fig01(ja-jp,MSDN.10).gif
 図1

Visual Basic 6.0 では、アイコンを表示させるためのフォームと、アイコンのポップアップメニューから表示されるフォームの 2 つを使用します。また、タスクトレイアイコンの作成や、ウィンドウのアクティブ状態を変更するために、Win32API の Shell_NotifyIcon 関数と SetForegroundWindow 関数を使用します。
まず、タスクトレインに表示されたアイコンを右クリックしたときに表示されるポップアップメニューを作成します。[メニュー エディタ]ダイアログを使用してポップアップさせるメニューを作成し、以下のコードを実装します。

Private Sub mnuOpen_Click()
Form2.Show vbModal
End Sub

Private Sub mnuEnd_Click()
Unload Me
End Sub

リスト1

続いて、SetForegroundWindow 関数、Shell_NotifyIcon 関数の定義と、Shell_NotifyIcon 関数で使用する NOTIFYICONDATA 構造体および定数を宣言します。

Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long

Public udtNotifyIconData As NOTIFYICONDATA

Type NOTIFYICONDATA
cbSize As Long
hwnd As Long
uID As Long
uFlags As Long
uCallbackMessage As Long
hIcon As Long
szTip As String * 64
End Type

Public Const NIF_ICON = &H2
Public Const NIF_MESSAGE = &H1
Public Const NIF_TIP = &H4

Public Const NIM_ADD = &H0
Public Const NIM_DELETE = &H2
Public Const NIM_MODIFY = &H1

Public Const WM_MOUSEMOVE = &H200
Public Const WM_LBUTTONDBLCLK = &H203
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const WM_RBUTTONDBLCLK = &H206
Public Const WM_RBUTTONDOWN = &H204
Public Const WM_RBUTTONUP = &H205

リスト2

リスト2 で宣言した SetForegroundWindow 関数と Shell_NotifyIcon 関数の呼び出し方法は以下のとおりです。

Private Sub Form_Load()
Form1.Visible = False
Form1.mnuMain.Visible = False

udtNotifyIconData.cbSize = Len(udtNotifyIconData)
udtNotifyIconData.hwnd = Form1.hwnd
udtNotifyIconData.uID = 1
udtNotifyIconData.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
udtNotifyIconData.uCallbackMessage = WM_MOUSEMOVE
udtNotifyIconData.hIcon = Form1.Icon
udtNotifyIconData.szTip = "タスクトレイのサンプル" & vbNullChar

Call Shell_NotifyIcon(NIM_ADD, udtNotifyIconData)
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Select Case X \ Screen.TwipsPerPixelX
Case WM_RBUTTONDOWN
Call SetForegroundWindow(Me.hwnd)
DoEvents
Me.PopupMenu mnuMain
End Select
End Sub

Private Sub Form_Unload(Cancel As Integer)
Call Shell_NotifyIcon(NIM_DELETE, udtNotifyIconData)
End Sub

リスト3

リスト3 の「Private Sub Form_Load() ... End Sub」では、アイコンの属性を設定し、タスクトレイに表示します。「Call Shell_NotifyIcon(NIM_ADD, udtNotifyIconData)」でタスクトレイにアイコンを表示します。「Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) ... End Sub」では、タスクトレイのアイコンを右クリックしたときに表示されるポップアップアップメニューを指定し、「Private Sub Form_Unload(Cancel As Integer) ... End Sub」ではタスクトレイに表示されているアイコンを削除します。

上記を実装し、プロジェクトを実行すると、図1 のようにタスクトレイにアイコンが表示されます。表示されたアイコンを右クリックするとポップアップメニューが表示されます (図2)。

 Cc440880.NotifyIcon_fig02(ja-jp,MSDN.10).gif
 図2

図2 の[開く]メニューを選択すると、Form2 が表示され、[終了]ボタンを選択するとForm1 (プロジェクト) が終了します。

このように、Visual Basic 6.0 では Win32API を使用します。また、タスクトレイにアイコンを表示するフォームとポップアップメニューによって表示されるフォームを設定します。しかし、Visual Basic .NETでは、標準でWindows コントロールに NotifyIcon コントロールが追加されています。そのため、フォームを 2つに分ける必要はありません。そこで続いては、Visual Basic .NET でタスクトレイにアイコンを表示する方法を紹介します。

今回、タスクトレイにアイコンが常駐しているとき (フォームを開いていないとき) は、フォームを最小化にし、Windows のタスクバーに表示しないようにします。一方、ポップアップの[開く]メニューを選択されたときはフォームを既存のサイズで表示し、タスクバーにも表示させます。そこで、まず、Form1 の WindowState プロパティを「Minimized」 (最小化) に、ShowInTaskbar プロパティを「false」に設定します。
次に、[ツールボックスボックス]から ContextMenu コントロールをドラッグ & ドロップします (コントロールはフォームの下部に配置されます)。そして、ポップアップ表示させるメニューを作成します。作成したメニューの実装コードは以下のとおりです。

Private bColseFlag As Boolean

Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click
Me.WindowState = System.Windows.Forms.FormWindowState.Normal
Me.ShowInTaskbar = True
End Sub

Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
bColseFlag = True
Me.Close()
End Sub

リスト4

上記 (リスト4) の「Me.WindowState = System.Windows.Forms.FormWindowState.Normal」で Form1 を既存のサイズ (Height、Left、Top、Windth プロパティの設定地が反映されます) で表示され、「Me.ShowInTaskbar = True」で Windows のタスクバーに表示します。「Me.Close()」で Form1 を閉じます。

続いて、NotifyIcon コントロールをフォームにドラッグ & ドロップします。そして追加された NotifyIcon コントロールの Icon プロパティにタスクトレイに表示するアイコンを指定し、ContextMenu プロパティに上記で作成したポップアップメニュー (ContextMenu1) を設定します。

これらを実装し、プロジェクトを実行すると、図1 のようにタスクトレイにアイコンが表示され、アイコンを右クリックすると図2 のようにポップアップメニューが表示されます。ただし、ここで注意しなければならないのが、上記の実装だけでは、フォーム (Form1) のタイトルバーから[× (閉じる) ]ボタンを選択すると、アプリケーションが終了してしまうことです。それを避けるため、フォームが閉じている間に発生する Closing イベントでアプリケーションを終了するか否かを判断します。Closing イベントでは、フォームを最小化し、タスクバーの表示を非表示にします。実装コードは以下のとおりです。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
bColseFlag = False
End Sub

Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
If bColseFlag = False Then
Me.WindowState = System.Windows.Forms.FormWindowState.Minimized
Me.ShowInTaskbar = False
e.Cancel = True
End If
End Sub

Private Shared WM_QUERYENDSESSION As Integer = &H11

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_QUERYENDSESSION Then
bColseFlag = True
End If
MyBase.WndProc(m)
End Sub

リスト5

フォームを閉じずに最小化するか否かを判断するため、フラグ (bColseFlag) を立てます。このフラグは、ポップアップメニューの[閉じる]メニューの実装時 (リスト4) にも設定します。フォームを閉じる時は bColseFlag を「True」にし、最小化にする場合は「False」を設定します。上記 (リスト5) の「If bColseFlag = False Then」では、フォームを閉じず最小化するかどうかを判断し、最小化する場合は「Me.WindowState = System.Windows.Forms.FormWindowState.Minimized」で Form1 を最小化します。また「Me.ShowInTaskbar = False」でタスクバーの表示を非表示にします。

ここで、もう一点注意しなければならないことがあります。フォームのタイトルバーの[× (閉じる) ]ボタンからアプリケーションを終了させないために、Closing イベントで、終了のキャンセル処理を行っています。この処理を行うことによる副作用として、シャットダウン処理時にアプリケーションが終了されないため、シャットダウンが途中でストップしてしまう現象が発生します。正しくシャットダウンさせるために、シャットダウン時に送信される WM_QUERYENDSESSION メッセージ時に、bColseFlag を「True」に設定します。.NET Framework には、SystemEvents.SessionEnding イベントという WM_QUERYENDSESSION メッセージに相当するイベントが存在します。ですが、このイベントは、Closing イベントの前に必ず発生することが保障されていないため、必ず、WM_QUERYENDSESSION メッセージで処理する必要があります。

Form、NotifyIcon コントロールの各プロパティの設定、リスト4、リスト5 の実装を行い、プロジェクトを実行すると、図1 のようにタスクトレイにアイコンが表示されます。表示されたアイコンを右クリックすると図2 のようにポップアップメニューが表示されます。[開く]メニューで最小化されていた Form1 が表示され、[終了]メニューでプロジェクトが終了します。また、[開く]メニューによって表示された Form1 の「× (閉じる) 」ボタンを選択すると、Form1 は最小化され、タスクバーの表示が非表示となります。