日記 Visual Studio 2019 C++ タスクトレイのアイコンに右クリックメニューを追加する方法


完成イメージ

手順

前提

次の記事の内容が適用されている事
日記 Visual Studio 2019 C++でタスクトレイに常駐するアプリケーションを作成

リソースにメニューを追加する





各メニューのプロパティ設定、どのメニューが選択されたか判別するIDをわかりやすい名前にする

プログラム

デスクトップアプリケーションのテンプレートに★マークで囲まれた範囲を追加
※ 一部次の記事の内容も混ざっている
 日記 Visual Studio 2019 C++でタスクトレイに常駐するアプリケーションを作成

定数、グローバル変数定義、初期処理

Sample.cpp
// Sample.cpp : アプリケーションのエントリ ポイントを定義します。
//

#include "framework.h"
#include "Sample.h"
// ★★★★★★★★★★★★★★★★★★★★
#include "shellapi.h"
// ★★★★★★★★★★★★★★★★★★★★

#define MAX_LOADSTRING 100

// ★★★★★★★★★★★★★★★★★★★★
#define WM_TASKTRAY (WM_APP + 1)                // タスクトレイのマウス・メッセージ定数
// ★★★★★★★★★★★★★★★★★★★★

// グローバル変数:
HINSTANCE hInst;                                // 現在のインターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーのテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// ★★★★★★★★★★★★★★★★★★★★
// アイコン
HICON hIcon;
// メニューに追加したIDR_MENU1のハンドルを設定するためのグローバル変数
HMENU hTaskTrayMenu;
// ★★★★★★★★★★★★★★★★★★★★

// このコード モジュールに含まれる関数の宣言を転送します:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

// ★★★★★★★★★★★★★★★★★★★★
// タスクトレ イアイコン追加、削除
VOID AddSystemTrayIcon(HWND hWnd);
VOID DellSystemTrayIcon(HWND hWnd);
// ★★★★★★★★★★★★★★★★★★★★

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: ここにコードを挿入してください。

    // ★★★★★★★★★★★★★★★★★★★★
    // アイコン AddSystemTrayIcon()で使用するため
    hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SAMPLE));

    // 作成したメニューを読み込む
    hTaskTrayMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
    // ★★★★★★★★★★★★★★★★★★★★

    // グローバル文字列を初期化する
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

メッセージ処理に処理を追加

  • タスクトレイのアイコンの右クリック時のメニューポップアップ処理
  • 各メニューを選択した時の処理の記述(コメント)
Sample.cpp
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        // ★★★★★★★★★★★★★★★★★★★★
        // タスクトレイのアイコンに対する処理
        case WM_TASKTRAY:
        {
            switch (lParam)
            {
                // 右クリック
                case WM_RBUTTONDOWN:
                {
                    // hTaskTrayMenuは初期処理でセットしている
                    if (hTaskTrayMenu)
                    {
                        // GetSubMenuは0でメニューの一番左のドロップダウンリストを取得する
                        HMENU hTrayIconSubMenu = GetSubMenu(hTaskTrayMenu, 0);
                        if (hTrayIconSubMenu)
                        {
                            // タスクトレイのアイコンを右クリックした時の座標を取得
                            POINT po;
                            GetCursorPos(&po);

                            // ウィンドウをフォアグラウンドに持ってくる
                            SetForegroundWindow(hWnd);

                            // これをしないと、メニュー外をクリックした時に、ポップアップメニューが消えない
                            SetFocus(hWnd);

                            // メニューの表示
                            TrackPopupMenu(hTrayIconSubMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN,
                                po.x, po.y, 0, hWnd, NULL
                            );
                        }
                    }
                }
                break;
            }
        }
        break;
        // ★★★★★★★★★★★★★★★★★★★★
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;

            // ★★★★★★★★★★★★★★★★★★★★
            // タスクトレイの右クリックメニューで選択されたメニューに応じた処理を追加する
            // case IDM_HOGE1:
                // break;
            // case IDM_HOGE2:
                // break;
            // ★★★★★★★★★★★★★★★★★★★★

            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT: