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

## 完成イメージ

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/f08fac49-4341-5dcf-229c-09105af98f39.png)

## 手順

### 前提

次の記事の内容が適用されている事
[日記 Visual Studio 2019 C++でタスクトレイに常駐するアプリケーションを作成](https://qiita.com/Yamine1San/items/47607193d17d0555a9d5)

### リソースにメニューを追加する
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/7152af56-4fe1-ae5c-e018-13c1691ec436.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/84f289a1-2a3b-d602-6003-9ecc57470397.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/c3a89fe1-2a04-fc42-0d7b-6fe595acd752.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/69f6e5cc-1d35-311c-48c7-2f5b4373a93e.png)
各メニューのプロパティ設定、どのメニューが選択されたか判別するIDをわかりやすい名前にする
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/8f711c12-91da-9725-d948-545c1e7e97b7.png)

## プログラム

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

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

```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:
```