StatusIcon

 前章では、API Shell_NotifyIcon を利用する簡単な「ラッパークラス」を作成しました。クラスのメソッドを呼び出せば、複雑な API コーディングを気にすることなく、簡単にアイコンを表示させることができます。

この章では、クラスを検討し直し、もう少し「オブジェクト化」を進めてみたいと思います。

目次

  1. Shell_NotifyIcon
  2. フォームモジュールにおける実装
  3. クラス化
  4. もっとオブジェクト的に…
  1. 何をオブジェクトとするのか?
  2. StatusIcon
  3. 考察とまとめ

何をオブジェクトとするのか?

 前章で作った StatusIconManager は、その名の通り、タスクトレイのアイコンを操作するオブジェクトです。

StatusIconManager.cls
メソッド説明
AddStatusIcon引数に指定された属性をもつアイコンをひとつ追加する
ModifyStatusIcon追加したアイコンの状態を変更する
DeleteStatusIcon追加したアイコンを削除する

しかし、アイコンを表示させたいだけなのに、「追加」とか「変更」とか、なんとなくスマートではありません。しかもインターフェイスはメソッドしかなく、API を呼び出すときと同じような手順を踏まなければなりません。

そもそも、オブジェクト化する対象がハッキリしていません。(フォームからコピー&ペーストしただけだから。)これはオブジェクトと呼べるでしょうか?

クラスのメリットを十分に活かすためには、オブジェクト化する対象を「IconManager」から、「Icon」(アイコンそのもの)にします。

StatusIcon

 つまり、インスタンスのひとつひとつが、タスクトレイのアイコンひとつひとつを意味するように設計するのです。“アイコンの”プロパティやメソッドを考えなければなりません。

そこで、次のようなクラスを考えてみました。

StatusIcon.cls
プロパティ説明
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 をラッピングするときは、直接インターフェイスをメソッドにしてしまうのではなく、抽象化できるところは抽象化してうまく表現しよう、というお話でした。

ダウンロード

[Download]staico.lzh ... ソースコードとクライアントサンプル
2000年12月29日(金) 更新