今回は、自分で準備したアイコンイメージを使って、トレイアイコンをアニメーション表示する方法を紹介しましょう。
手順としては、アニメーションをするのに必要なだけのアイコンオブジェクトを作成しておき、 Shell_NotifyIcon 関数を繰り返し呼び出して、アイコンを変更していきます。 Shell_NotifyIcon 関数についてはこれまでに使ってきているので、特に説明の必要はないでしょう。
問題となるのはアイコンの作成です。任意のイメージからアイコンを作成するのにはいくつか方法がありますが、今回はイメージリストからアイコンを作成する方法を使ってみることにしましょう。
手順は以下のようになります。
まずは、トレイアイコンのアニメーションに使用したいイメージをすべて含んだイメージリストを作成します。透明部分を持つアイコンを作成するために、イメージリストはマスク付きで作成しておきましょう。
イメージリストについては、『イメージリストを作成してみる』の項を参照してください。
イメージリストからアイコンを作成するには、 ImageList_GetIcon 関数を呼び出します。
HICON ImageList_GetIcon(
HIMAGELIST himl, // イメージリストのハンドル
int index, // イメージのインデックス
UINT flags // 描画スタイル
);
himl パラメータにはイメージリストのハンドルを、 index パラメータにはイメージリスト中におけるイメージのインデックスを指定します。今回はマスク部分を透明化したアイコンを作成したいので、 flags パラメータには 1 (ILD_TRANSPARENT) を指定します。
この関数は、戻り値として作成されたアイコンのハンドルを返します。すべてのイメージのアイコンを作成し、ハンドルを配列変数に格納しておきましょう。
今回は、タスクトレイに表示されたアイコン上でマウスクリックされたときに、ショートカットメニューを表示するようにしてみましょう。
すべてのイメージのアイコンを作成できたら、イメージリストはもう必要なくなります。したがって、 ImageList_Destroy 関数でイメージリストを破棄しておきます。
すでにタスクバーのステータスエリアに表示されているアイコンを変更するには、まず、 NOTIFYICONDATA 構造体の uFlags メンバに 2 (NIF_ICON) を指定し、 hIcon メンバに新しいアイコンハンドルを指定します。そして、 Shell_NotifyIcon 関数の第1引数(dwMessage パラメータ)に 1 (NIM_MODIFY) を指定します。
この関数では、アイコンイメージだけでなく、ツールチップ文字列を変更することもできます。この場合には、 NOTIFYICONDATA 構造体の uFlags メンバに 4 (NIF_TIP) を指定し、 szTip メンバには新しいツールチップ文字列を格納しておきます。
さて、実際にスクリプトを書いてみます。
アイコン用のイメージとして、以下の画像を使用します。このビットマップファイルは、1つのイメージサイズが 16×16 ピクセルで、それを横に4つつなげたものになっています。マスクを生成する色として、白(RGB値は 0xFFFFFF )を指定します。
(iconlist2.bmp)
#include "llmod.as"
#module ;###### ビットマップオブジェクト作成モジュール #########
;===============================================================
; 描画中ウィンドウのイメージからビットマップオブジェクト(DIB)作成
; CreateDIB p1, p2, p3, p4
; p1 : HSPウィンドウx座標
; p2 : HSPウィンドウy座標
; p3 : 幅
; p4 : 高さ
; stat : ビットマップのハンドルが返る
;===============================================================
#deffunc CreateDIB int, int, int, int
mref px, 0 ; HSPウィンドウx座標
mref py, 1 ; HSPウィンドウy座標
mref sx, 2 ; xサイズ
mref sy, 3 ; yサイズ
mref stt, 64 ; stat
mref bmscr, 67 ; 描画中ウィンドウのBMSCR構造体
; DIBセクションオブジェクト作成
pm = bmscr.4, sx, sy
dllproc "CreateCompatibleBitmap", pm, 3, D_GDI@
hbitmap = stat ; ビットマップオブジェクトのハンドル
; メモリデバイスコンテキスト作成
pm = bmscr.4
dllproc "CreateCompatibleDC", pm, 1, D_GDI@
hdcMemory = stat ; メモリデバイスコンテキストのハンドル
; ビットマップをデバイスコンテキストに選択
pm = hdcMemory, hbitmap
dllproc "SelectObject", pm, 2, D_GDI@
; HSPウィンドウからビットマップにイメージをコピー
pm = hdcMemory, 0, 0, sx, sy, bmscr.4, px, py, $CC0020
dllproc "BitBlt", pm, 9, D_GDI@
; デバイスコンテキストを削除
dllproc "DeleteDC", hdcMemory, 1, D_GDI@
stt = hbitmap ; ビットマップオブジェクトのハンドル
return
#global ;############# モジュール終わり ########################
#module ;######### イメージリスト操作モジュール ################
;===============================================================
; イメージリストの作成
; CreateImageList p1, p2, p3, p4
; p1 : イメージの幅
; p2 : イメージの高さ
; p3 : イメージリストのタイプ
; p4 : イメージの数
; stat : イメージリストのハンドルが返る
;===============================================================
#deffunc CreateImageList int, int, int, int
mref sx, 0 ; イメージの幅
mref sy, 1 ; イメージの高さ
mref flags, 2 ; イメージリストのタイプ
mref num, 3 ; イメージの数
; イメージリストの作成
pm.0 = sx
pm.1 = sy
pm.2 = flags
pm.3 = num
pm.4 = 0
dllproc "ImageList_Create", pm, 5, D_COMCTL@
return
;===============================================================
; イメージリストに描画中ウィンドウのイメージ追加
; AddImageList p1, p2, p3, p4, p5
; p1 : イメージリストのハンドル
; p2 : HSPウィンドウx座標
; p3 : HSPウィンドウy座標
; p4 : 幅
; p5 : 高さ
; p6 : マスクに用いる色
; stat : イメージのインデックスが返る
;===============================================================
#deffunc AddImageList int, int, int, int, int, int
mref himl, 0 ; イメージリストのハンドル
mref cx, 1 ; x座標
mref cy, 2 ; y座標
mref sx, 3 ; xサイズ
mref sy, 4 ; yサイズ
mref crmask, 5 ; マスク生成に用いる色
mref stt, 64 ; stat
; DIBオブジェクトの作成
CreateDIB cx, cy, sx, sy
hbitmap = stat ; ビットマップハンドル
; ビットマップをイメージリストに追加
pm.0 = himl
pm.1 = hbitmap
pm.2 = crmask
dllproc "ImageList_AddMasked", pm, 3, D_COMCTL@
index = stat ; 最初のイメージのインデックス
; ビットマップオブジェクトを削除
dllproc "DeleteObject", hbitmap, 1, D_GDI@
stt = index ; イメージのインデックスをstatに格納
return
;===============================================================
; イメージリストの破棄
; DestroyImageList p1
; p1 : イメージリストのハンドル
;===============================================================
#deffunc DestroyImageList int
mref himl, 0 ; イメージリストのハンドル
; イメージリストを破棄
pm.0 = himl
dllproc "ImageList_Destroy", pm, 1, D_COMCTL@
return
;===============================================================
; イメージリストのイメージからアイコン作成
; GetIconImageList p1, p2
; p1 : イメージリストのハンドル
; p2 : イメージのインデックス
; stat : アイコンハンドルが返る
;===============================================================
#deffunc GetIconImageList int, int
mref himl, 0 ; イメージリストのハンドル
mref index, 1 ; イメージのインデックス
; アイコン作成
pm.0 = himl
pm.1 = index
pm.2 = 1 ; ILD_TRANSPARENT
dllproc "ImageList_GetIcon", pm, 3, D_COMCTL@
return
#global ;############# モジュール終わり ########################
; トレイアイコン用のアイコンID
#define ID_TRAYICON 1
; トレイアイコン用のメッセージコード
#define MYWM_TRAYICON 0x1000
#define ICON_SIZE_X 16 ; アイコンイメージの幅
#define ICON_SIZE_Y 16 ; アイコンイメージの高さ
#define ICON_NUM 4 ; アイコンイメージの数
; ビットマップファイルの読み込み
buffer 2,,, 0
picload "iconlist2.bmp"
; 24bit DIB イメージリスト作成(マスクあり)
CreateImageList ICON_SIZE_X, ICON_SIZE_Y, 0x0018 | 0x0001, ICON_NUM
himl = stat ; イメージリストのハンドル
; イメージをイメージリストに追加(白を透過色に)
AddImageList himl, 0, 0, ICON_SIZE_X*ICON_NUM, ICON_SIZE_Y, 0xFFFFFF
; アイコンハンドルを格納する変数
dim hicon, ICON_NUM
; イメージリストからアイコン作成
repeat ICON_NUM
GetIconImageList himl, cnt
hicon.cnt = stat
loop
; イメージリストの破棄
DestroyImageList himl
gsel 0
mref bmscr, 67 ; ウィンドウのBMSCR構造体
hwnd = bmscr.13 ; ウィンドウハンドル
; NOTIFYICONDATA 構造体
tooltext = "トレイアイコンのアニメーションのテスト"
dim nid, 22
nid.0 = 88, hwnd, ID_TRAYICON, 1|2|4, MYWM_TRAYICON, hicon.0
poke nid, 24, tooltext ; ツールチップ文字列
; タスクトレイにアイコンを追加
pm.0 = 0 ; NIM_ADD
getptr pm.1, nid ; NOTIFYICONDATA 構造体アドレス
dllproc "Shell_NotifyIconA", pm, 2, D_SHELL
onexit *onQuit
*mainloop
wait 10
if wcnt > 5 {
; 次のアイコンに変更する
gosub *ChangeIcon
wcnt = 0
}
wcnt++
goto *mainloop
*ChangeIcon
iconindex++
if iconindex >= ICON_NUM : iconindex = 0
; NOTIFYICONDATA 構造体
dim nid, 22
nid.0 = 88 ; 構造体サイズ
nid.1 = hwnd ; ウィンドウハンドル
nid.2 = ID_TRAYICON ; アイコンID
nid.3 = 2 ; NIF_ICON
nid.5 = hicon.iconindex ; 新しいアイコンのハンドル
; タスクトレイのアイコンを変更
pm.0 = 1 ; NIM_MODIFY
getptr pm.1, nid ; NOTIFYICONDATA 構造体アドレス
dllproc "Shell_NotifyIconA", pm, 2, D_SHELL
return
*onQuit
; 終了時の処理
; NOTIFYICONDATA 構造体(cbSize, uID のみセット)
dim nid, 22
nid.0 = 88 ; 構造体サイズ(=88)
nid.1 = hwnd ; ウィンドウハンドル
nid.2 = ID_TRAYICON ; アイコンID
; タスクトレイからアイコンを削除
pm.0 = 2 ; NIM_DELETE
getptr pm.1, nid ; NOTIFYICONDATA 構造体アドレス
dllproc "Shell_NotifyIconA", pm, 2, D_SHELL
; アイコンの破棄
repeat ICON_NUM
pm = hicon.cnt
dllproc "DestroyIcon", hicon, 1, D_USER
loop
end