前章では、API Shell_NotifyIcon を利用する簡単な「ラッパークラス」を作成しました。クラスのメソッドを呼び出せば、複雑な API コーディングを気にすることなく、簡単にアイコンを表示させることができます。
この章では、クラスを検討し直し、もう少し「オブジェクト化」を進めてみたいと思います。
前章で作った StatusIconManager は、その名の通り、タスクトレイのアイコンを操作するオブジェクトです。
| メソッド | 説明 |
|---|---|
| AddStatusIcon | 引数に指定された属性をもつアイコンをひとつ追加する |
| ModifyStatusIcon | 追加したアイコンの状態を変更する |
| DeleteStatusIcon | 追加したアイコンを削除する |
しかし、アイコンを表示させたいだけなのに、「追加」とか「変更」とか、なんとなくスマートではありません。しかもインターフェイスはメソッドしかなく、API を呼び出すときと同じような手順を踏まなければなりません。
そもそも、オブジェクト化する対象がハッキリしていません。(フォームからコピー&ペーストしただけだから。)これはオブジェクトと呼べるでしょうか?
クラスのメリットを十分に活かすためには、オブジェクト化する対象を「IconManager」から、「Icon」(アイコンそのもの)にします。
つまり、インスタンスのひとつひとつが、タスクトレイのアイコンひとつひとつを意味するように設計するのです。“アイコンの”プロパティやメソッドを考えなければなりません。
そこで、次のようなクラスを考えてみました。
| プロパティ | 説明 | 型 |
|---|---|---|
| Image | アイコン画像のピクチャ | Picture |
| ToolTipText | ツールチップの文字 | String |
| Visible | アイコンの表示状態 | Boolean |
| hWnd | このアイコンを管理するウィンドウのハンドル(値の取得専用) | Long |
| メソッド | 説明 |
|---|---|
| Initialize | 各プロパティを設定して初期化する |
| Show | アイコンを表示する |
| Hide | 非表示にする |
Add や Delete メソッドではなくて、Boolean 型のプロパティ Visible で“表示、非表示を操作”します。アイコンを“追加する、削除する”という考え方ではありません。
さらに、Image プロパティと ToolTipText プロパティを設け、それぞれがアイコンの状態を表すプロパティとなり、トレイ上のアイコンの状態とシンクロします。
Show メソッドと Hide メソッドも用意しました。
VB 標準コントロールのプロパティやメソッドと同じような感覚です。
オブジェクトを正常に動作させるためには、Initialize メソッドを最初に呼んで、ターゲットとなるウィンドウのハンドルを指定します。インスタンス作成時には hWnd プロパティの値を自動的に設定できないからです。
次のコードは、このオブジェクトの使用例です。
'画像を設定
StatusIcon.Image = picIcon.Picture
'ツールチップを設定
StatusIcon.ToolTipText = txtToolTip.Text
'アイコンを表示
StatusIcon.Visible = True
'StatusIcon.Show
実際のコードでは、設計したインターフェイスと API の呼び出しをうまくリンクさせる必要があります。
Private Sub ExecuteShellNotifyIcon(ByVal Show As Boolean)
If m_hWnd = 0 Then Exit Sub
With m_nid
.hWnd = m_hWnd
If m_picImage Is Nothing Then
.hIcon = 0&
Else
.hIcon = m_picImage.Handle
End If
.szTip = m_strToolTipText & vbNullChar
End With
If Show Then
'コマンドは 表示せよ で、
If m_blnVisible Then
'既に表示しているとき
Call Shell_NotifyIcon(NIM_MODIFY, m_nid)
Else
'非表示のとき
Call Shell_NotifyIcon(NIM_ADD, m_nid)
End If
Else
'コマンドは 非表示にせよ で、
If m_blnVisible Then
'表示しているとき
Call Shell_NotifyIcon(NIM_DELETE, m_nid)
End If
End If
End Sub
これは、API Shell_NotifyIcon を呼び出す、クラス内部の中核となるサブルーチンです。プロパティが変更されたら、これを呼び出してタスクトレイに反映します。
※その他のコードは省略しますが、プロパティ変数の管理が中心で、特に難しいところはありません。
StatusIconManager を利用していたフォームモジュールのコードは以下のように置き換えられます。
Private m_theStatusIcon As StatusIcon
Private Sub Form_Load()
Set m_theStatusIcon = New StatusIcon
Call m_theStatusIcon.Initialize( _
hWnd, Icon, "Shell_NotifyIcon", True)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set m_theStatusIcon = Nothing
End Sub

“アイコンの状態をプロパティで表現・操作していること”、“総合的な管理者オブジェクトではなく、個々のアイコンのインターフェイスであること”に注目してください。その上で、API のインターフェイスを極力前に出さないようにうまく隠しています。逆に言うと、API などの低レベルな部分を隠すことがクラス化の目的なのです。
「でも、わざわざこんなことしなくても、Add と Modify と Delete でいいんじゃないの?」という頑固な人もいるかもしれません。
ここで重要なのは、“「個」をイメージすること”です。
複数のアイコンを管理することになったら、StatusIconManager を拡張するのもひとつの方法です。その場合、アイコンを表す構造体データが作られ、StatusIconManger はそのコレクションになります。(とするのなら、やはりアイコンもクラスにした方が便利ですね。)
どちらにせよ、API をラッピングするときは、直接インターフェイスをメソッドにしてしまうのではなく、抽象化できるところは抽象化してうまく表現しよう、というお話でした。