Win32APIで常駐アプリを作る

Shell_NotifyIcon()を使ってタスクバーの通知領域にアイコンを追加する事で実現できる。

Shell_NotifyIconは第一引数に操作の種類(アイコンを追加するのか、変更するのか、削除するのか)を指定し、第二引数にNOTIFYICONDATA構造体を渡す。

アイコンの追加

int AddNotifyIcon(HWND hWnd, unsigned int uID, HICON hIcon, char *szTip){
        NOTIFYICONDATA nid;

        nid.cbSize = sizeof(nid);
        nid.hWnd = hWnd;
        nid.uID = uID;
        nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
        nid.uCallbackMessage = WM_NOTIFYICON;
        nid.hIcon = hIcon;
        strcpy(nid.szTip, szTip);

        return (int)Shell_NotifyIcon(NIM_ADD, &nid);
}

アイコンを追加する時は、Shell_NotifyIconの第一引数にNIM_ADDを指定すれば良い。

cbSizeはNOTIFYICONDATA構造体のサイズで、hWndはメッセージを受け取る先のウインドウ、uIDはそのアイコンのID(1つのアプリケーションで複数のアイコンを操る場合以外には必要無い)。

uFlagsはどの構造体メンバが有効かのフラグで、hIconは実際に通知領域に表示するアイコンのハンドル。リソースなどに埋めこんである場合は、LoadIcon(hInstance, "ICONID")すれば取ってこられる。

注意するべきは、szTipである。一瞬文字列へのポインタかと思うが構造体の中身のszTipはポインタではなく実体であるので、strcpyなどを使用してszTipに文字列をコピーする必要がある。szTipのサイズはWin2k以降なら128byteもしくはUnicodeなら128文字(つまり256byte)である。基本的にそれ以下にしておけばあまり気にする事はないだろう。しかしコンパイル時の設定等でShell_NotifyIconWを使用している場合などにはstrcpyなどの部分を気にする必要があるかもしれない。

以上を見ても分かるように、メッセージを送る先のウインドウが必要であるので、CreateWindowだけして(ShowWindowしないなど)、とりあえずウインドウを作成しておくと良い。(おそらくWin32プログラミングに慣れている人なら基礎中の基礎のような事だとは思うが、何せ私は慣れていないので)

アイコンの削除

void DeleteNotifyIcon(HWND hWnd, unsigned int uID){
        NOTIFYICONDATA nid;

        nid.cbSize = sizeof(nid);
        nid.hWnd = hWnd;
        nid.uID = uID;
        nid.uFlags = 0;

        Shell_NotifyIcon(NIM_DELETE, &nid);

        return;
}

アイコンを削除する時は、Shell_NotifyIconの第一引数にNIM_DELETEを指定すれば良い。uIDがあっていれば、第二引数で渡される構造体が、追加時と同一の構造体である必要はない。