10

システム トレイ アイコンを確実に削除する方法はありますか?

システム トレイ アイコンを追加するには、次のようにします。

Shell_NotifyIcon(NIM_ADD, &m_tnd);

システム トレイ アイコンを削除するには、次のようにします。

Shell_NotifyIcon(NIM_DELETE, &m_tnd);

知りたいこと: アプリケーションがクラッシュした場合はどうなりますか? アイコンは、マウスオーバーするまでシステム トレイに残ります。アプリケーションがクラッシュした場合でも、アイコンが削除されることを保証する方法はありますか? さまざまな理由から、構造化された例外処理を使用したくないと思います。

私が処理したいもう 1 つのケースは、プロセスが強制終了された場合ですが、必ずしもクラッシュするとは限りません。

4

8 に答える 8

4

Another thing most programmers forget to check for is if the explorer restarts/crashes. Its nice if the application handle this and recreate its own icon.

Just check for Message WM_TASKBARCREATED and recreate the icon.

于 2009-01-20T23:58:48.013 に答える
2

アプリケーションを監視する別の、より単純な (したがっておそらくより堅牢な) プログラムを作成することもできます。このプログラムは、実際にプログラムを起動し、プロセスを監視できます。ええ、これは非常に醜い解決策です。

于 2009-01-20T03:45:50.007 に答える
2

個人的には、Vectored Exception Handler を使用します。はい、これは SEH に基づいていますが、アンワインドに必要なさまざまなスタックをすべて処理する必要はありません。

TerminateProcess() は、より破壊的でなければなりません。あなたは本当にそれから身を守ることはできません。それが起こると、プロセスは死んでいます。鉱石命令は処理されないため、アプリケーションにどんなコードがあっても問題ありません。

外部アプリケーションはあまり役に立ちませんね。それもクラッシュするか、殺される可能性があります。

于 2009-01-20T09:29:46.207 に答える
1

Shell_NotifyIcon(NIM_DELETE, &m_tnd);アプリケーションがクラッシュした場合に C++ での呼び出しを保証する方法は多数あります。使用している にRAIIラッパーをNOTIFYICONDATA使用すると、次のように機能します。

struct NID
{
    NID() : icon_data() { icon_data.cbSize = sizeof(icon_data); }
    ~NID() { Shell_NotifyIcon(NIM_DELETE, &icon_data); }
    void Show(HWND w) { icon_data.hWnd = w; Shell_NotifyIcon(NIM_ADD, &icon_data); }
    NOTIFYICONDATA icon_data;
};

これはラッパーの単純化されたバージョンですが、主なアイデアを説明します: のインスタンスをNID静的ストレージに作成すると、WinMainormain呼び出しの前に初期化され、そのデストラクタがプログラムのクリーンアップ時に呼び出されます。異常終了。

したがって、このリソースを次のようNOTIFYICONDATAにラップして使用できます。struct NID

NID nid; // <--- automatic storage duration, cleared after WinMain return
         // even if it returns normal or abnormally

int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
        // GetMessage(&message, NULL, 0, 0) loop ...
        // ...
        // use nid.icon_data as you please
    }
    catch (...)
    {
        // something bad happened...
    }

    return 0;
}

上記の例では~NID()、プログラムが終了したとき (例外の後またはプログラムを閉じた後) を呼び出し、デストラクタが呼び出さShell_NotifyIcon(NIM_DELETE, &icon_data);れ、通知領域からアイコンが削除されます。このコードは、通常の終了と例外終了をカバーしています。このトピックの詳細については、 NPEからの適切な回答を参照してください。

プロセスを強制終了する場合については、これを行う簡単な方法はありません。

私はすでにそれをテストしてstd::atexitおり、タスクマネージャーを介してプログラムを強制終了した後に関数が呼び出されないため、終了呼び出しをフックstd::at_quick_exitする必要があると思います...かなり複雑なタスクのようですが、 BSHからのこの回答で説明されています:

TerminateProcessプロセスが終了した (閉じられていない) 場合、フックまたはNtTerminateProcessタスク マネージャー プロセスで何らかのフックを開始しない限り、何も実行できません。

それが役立つことを願っています(ただし、6年後の答えです笑)

于 2015-04-27T14:06:12.817 に答える
1

うーん、システム トレイ ウィンドウへの WM_PAINT メッセージで SendMessage を呼び出す外部モニター プロセスをいつでも持つことができます (ウィンドウのクラスに基づいて実行する必要があります)。これにより、無効になったアイコンが削除されます。

于 2009-01-20T03:46:08.397 に答える
0

SetUnhandledExceptionFilterを使用して、クラッシュをキャッチできます。私は通常、クラッシュをデバッグできるようにクラッシュ ダンプ ファイルを作成するために使用しますが、トレイ アイコンを削除するなどの簡単なクリーンアップができない理由はありません。

于 2009-01-20T10:14:37.960 に答える
0

何らかの方法でクラッシュしたときにアプリケーションの終了を処理する必要があります。そうしないと、アイコンが消えません。

これが助けになるかどうかを確認してください:http://www.codeproject.com/KB/shell/ashsystray.aspx

于 2009-01-20T03:47:00.237 に答える
-1

あなたの問題に直接対処するものではありませんが、これは私にとって非常に役立つ回避策でした:

システム トレイの状態を混乱させないようにしたかったのです。したがって、私にとっては、起動時に通知トレイを「更新」するだけで十分でした。これは私が最初に考えたよりも複雑でしたが、次に示すは、実際にユーザーのカーソルを移動させる必要のないユーザー マウスオーバー クリーンアップをシミュレートする SendMessage ソリューションです。

Windows 7 マシンでは、名前Notification Areaを に置き換える必要があることに注意してくださいUser Promoted Notification Area

于 2010-11-24T09:02:33.633 に答える