タスクトレイのバルーンチップが表示されない

解決


どら  2008-01-23 18:17:37  No: 67359  IP: 192.*.*.*

今度はやたら初歩的な質問ですみません・・・
タスクトレイに常駐するアプリケーションを作っているのですが、タスクトレ
イにアイコン作成時にバルーンチップを表示させようとしています。

#define _WIN32_IE 0x0500

・・・

NOTIFYICONDATA ni;     //諸事情があってグローバルで宣言

・・・

・・・WinMain(・・・)
{
・・・
}

・・・WinProc(HWND hWnd, ・・・)
{
    HICON hIcon;
・・・
    switch (msg) 
    {
        case WM_CREATE:
            hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));
            ni.cbSize = sizeof(NOTIFYICONDATA);
            ni.hIcon = hIcon;
            ni.hWnd = hWnd;
            ni.uCallbackMessage = WM_USER;
            ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
            ni.uID = ID_TRAY;
            //バルーンチップに表示するための設定
            ni.uTimeout = 10;
            lstrcpy(ni.szInfoTitle, "バルーンのタイトル");
            wsprintf(ni.szInfo, "バルーンのメッセージ");
            //マウスカーソルを合せた時に表示
            wsprintf(ni.szTip, "カーソルをあわせたときのメッセージ");
            //設定したタスクトレイのアイコンを表示
            Shell_NotifyIcon(NIM_ADD, &ni);
            break;
    }
    ・・・・
}

としているのですが(かなり途中はしょっていますが・・・)、トレイにアイコ
ンが表示されたときにバルーンチップがでてこないんです。
マウスカーソルをあわせた時のメッセージなどはきちんと表示されています。

何か基本的なものが抜けていたりしているのではないかと思っているのですが
、見当もつかず・・・

わかる方いらっしゃいましたら御指摘頂けないでしょうか?

開発・実行環境はWindows XP Pro With SP2 + VS.NET 2003 Enterprise です。

よろしくおねがいいたします。

編集 削除
シャノン  2008-01-23 20:45:07  No: 67360  IP: 192.*.*.*

バルーンはマウスカーソルを乗せても勝手には出ません。
出したいタイミングで、NIM_MODIFY してやる必要があります。
ツールチップをバルーンで置き換えたいなら、uFlags に NIF_TIP を含めず、uCallbackMessage に指定したメッセージを捕まえたタイミングで NIM_MODIFY してやりましょう。

編集 削除
どら  2008-01-24 10:38:45  No: 67361  IP: 192.*.*.*

シャノンさん

いつもありがとうございます。
私がやりたい動きは、アプリケーション起動時に

    1.タスクトレイにアイコンを表示
    2.現在のステータスをバルーンで表示
    3.マウスのカーソルをあわせたときに簡略化したステータスを表示

で、トレイアイコンを右クリックしたらメニューを表示させ、選択後

    1.トレイのアイコンを変更
    2.ステータスをバルーンに表示
    3.マウスのカーソルをあわせたときに簡略化したステータスを表示

という動きにしたいのですが、この場合はいっぺんに1〜3の動作を指せること
ができないという認識で間違いないですか?

そうなると、起動時は

    1.uFlags = NIF_ICON | NIF_MESSAGE フラグでNIM_ADD
    2.uFlags = NIF_INFO フラグでNIM_MODIFY
    3.uFlags = NIF_TIP フラグでNIM_MODIFY

とすればよいのでしょうか?

よろしくおねがいいたします。

編集 削除
シャノン  2008-01-24 15:52:23  No: 67362  IP: 192.*.*.*

ごめん、なんか勘違いしてた。
マウスカーソルが乗ったときにツールチップの代わりにバルーンを出したいんだと思ってしまった。
そんなことはどこにも書いてないね。

で、結論から言うと、ご希望の動作は、一度の呼び出しで可能です。

まずそうな点は…
・uTimeOutはミリ秒で、最低10秒(10000)です。
・dwInfoFlagsが設定されていないようです。
・sizeof(NOTIFYICONDATA) が NOTIFYICONDATA_V2_SIZE と等しいことを確認してください。
かな?

編集 削除
どら  2008-01-24 17:45:43  No: 67363  IP: 192.*.*.*

>シャノンさん

ありがとうございました!!
おっしゃるとおりでした。

・uTimeOutはミリ秒で、最低10秒(10000)です。

大ボケですね、普通はミリ秒ですよね。
MSDNに「The system minimum and maximum timeout values are currently 
set at 10 seconds and 30 seconds, respectively.」だけを見てそのまま
10と入力してしまいました(^^;

・dwInfoFlagsが設定されていないようです。

とくに何も必要ないので0にしてみました。

・sizeof(NOTIFYICONDATA) が NOTIFYICONDATA_V2_SIZE と等しいことを確認してください。

全然違いました。

   sizeof(NOTIFYICONDATA) = 508
   NOTIFYICONDATA_V2_SIZE = 3435973836

でした。
で、以下のようにして解決しました。

        case WM_CREATE:
            hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));
            ni.cbSize = NOTIFYICONDATA_V2_SIZE;                    //修正
            ni.hIcon = hIcon;
            ni.hWnd = hWnd;
            ni.uCallbackMessage = WM_USER;
            ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
            ni.uID = ID_TRAY;
            //バルーンチップに表示するための設定
            ni.uTimeout = 10000;                                   //修正
            ni.dwInfoFlags = 0;                                    //追加
            lstrcpy(ni.szInfoTitle, "バルーンのタイトル");
            wsprintf(ni.szInfo, "バルーンのメッセージ");
            //マウスカーソルを合せた時に表示
            wsprintf(ni.szTip, "カーソルをあわせたときのメッセージ");
            //設定したタスクトレイのアイコンを表示
            Shell_NotifyIcon(NIM_ADD, &ni);
            break;

いつもいつもありがとうございます!!

編集 削除
シャノン  2008-01-24 19:04:30  No: 67364  IP: 192.*.*.*

> NOTIFYICONDATA_V2_SIZE = 3435973836

えー!?  そんなことはないはず。

NOTIFYICONDATA_V2_SIZE は、マクロ UNICODE が定義されているとき 936、定義されていないとき 488 です。
この値は何かというと、マクロ _WIN32_WINNT が 0x0500 以上 0x0501 未満であるときの sizeof( NOTIFYICONDATA ) です。
で、508 ってのは、マクロ _WIN32_WINNT が 0x0600 以上で UNICODE が定義されていないときの sizeof( NOTIFYICONDATA ) です。

…ごめんなさい。
XP の場合は NOTIFYICONDATA_V3_SIZE(0x0501 <= _WIN32_WINNT < 0x0600)が正しい値です。

ご存知かもしれませんが一応書きます。

_WIN32_WINNT は OS のバージョンをあらわします。
0x0500 が Windows 2000
0x0501 が Windows XP
0x0502 が Windows Server 2003
0x0600 が Windows Vista
です。

Shell_NotifyIcon は、OS のバージョンが上がるに従って機能が増えていき、それに伴って NOTIFYICONDATA のサイズも大きくなります。
Shell_NotifyIcon は、NOTIFYICONDATA::cbSize の値を見て、どの OS で実装された機能が要求されているのかを判断します。
今回、sizeof( NOTIFYICONDATA ) が 508 だったということは、_WIN32_WINNT が 0x0600 以上だったことになります。
これは、「Windows Vista から実装された機能を使う」と宣言したことになります。
しかし、実際に動かしている OS は XP SP2 ですので、その機能には対応していません。
Windows XP の Shell_NotifyIcon は、NOTIFYICONDATA::cbSize が NOTIFYICONDATA_V3_SIZE 以下でないと正常に動かないというわけです。

で、
> ni.cbSize = NOTIFYICONDATA_V2_SIZE;
これは間違いではありませんが、あまり望ましい対応方法ではありません。

各種ヘッダをインクルードする前に、
#define _WIN32_WINNT 0x0501
と書いておくのが、XP での正しいやり方です。
こう書くと、Windows XP 以降でのみ使用可能なアプリになります。

バルーンチップは Windows 2000 でも使えますので、Windows 2000以降で動くアプリを作りたければ、
#define _WIN32_WINNT 0x0500
です。
これは、Windows 2000 までで実装されている機能しか使わないことを意味します。

で、_WIN32_WINNT を適切に定義した上で、
ni.cbSize = sizeof( NOTIFYICONDATA );
とすべきです。

なお、
> #define _WIN32_IE 0x0500
これは、「IE 5.0 の新機能を使う」という意味です。

編集 削除
どら  2008-01-24 19:43:12  No: 67365  IP: 192.*.*.*

シャノンさん

>> NOTIFYICONDATA_V2_SIZE = 3435973836
>えー!?  そんなことはないはず。

ですよね・・・おっしゃるとおりです。
今気付いたのですが、実はDebug時にブレークポイントの位置を

DWORD dwtemp = NOTIFYICONDATA_V2_SIZE;

の行にしていて、それでクイックウオッチで確認したので、当然何も値を割り
当てていない状況で見てるのでこのようなおかしな値になっていました(汗)
大ボケもいいとこです>_<

実行するクライアントがWindows 2000である可能性もあるので

#define _WIN32_WINNT 0x0500

で動作を確認しました!!
重ね重ね、ありがとうございました☆

編集 削除