[C++] ダイアログベースアプリのひな型

# もくじ

https://tera1707.com/entry/2022/02/06/144447

# やりたいこと

久しぶりにC++でダイアログベースで実験用ソフトを作ろうと思って、15年以上前に[猫でもわかるWindowsプログラミング](https://www.amazon.co.jp/%E7%8C%AB%E3%81%A7%E3%82%82%E3%82%8F%E3%81%8B%E3%82%8BWindows%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E7%AC%AC4%E7%89%88-%E7%8C%AB%E3%81%A7%E3%82%82%E3%82%8F%E3%81%8B%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E7%B2%82%E4%BA%95-%E5%BA%B7%E5%AD%9D/dp/4797370890)を見て勉強しながら書いた自分のテンプレートを引っ張り出してビルドしたらビルドできなくなってたので、今(VisualStudio2019)の環境でビルドできるように手なおしして、実験に使えるようにしたい。
(今、WindowsのC++でUIのあるソフトを作ろうとしたときの選択肢って、何か増えてましたっけ？勉強不足で追いつけてない...)

# コード
下記が今回作ったコード。
https://github.com/tera1707/Cpp/tree/master/CppDlgbaseTemplate

# 今回VS2019でひな型を作った時の手順メモ

### 1.プロジェクトの作成

まず「新しいプロジェクトの作成」で、「Windowsデスクトップアプリケーション」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/88b67d4b-deff-de57-38a4-6bbbff64474d.png)

そうすると、ひな型として、

- wWinMain
- MyRegisterClass
- InitInstance
- WndProc
- About

の関数を持ったcppファイルが出来上がるので、このうち

- wWinMain

だけを残してあとの関数を全部消す。

### 2.ダイアログの追加

実験用ダイアログのリソースを追加する。

ソリューションエクスプローラーの中の「リソースファイル」を右クリック＞[追加]＞[リソース]を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/a38e1da4-8a54-1b26-f1cb-3005a0cec8cc.png)

出てきた「リソースの追加」ダイアログで、「Dialog」を選択し「新規作成」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/f418449a-d586-af79-330c-6d060e30df54.png)

→リソースビューを開いて、プロジェクトの中の「Dialog」フォルダを開くと「IDD_DIALOG1」というダイアログが、追加されているので、それを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/46be6f00-74fd-2e40-bc00-069e8961cdd1.png)

### 3.IDの変更

開いた「IDD_DIALOG1」ダイアログのプロパティの中の「ID」のところが「IDD_DIALOG1」となっているので、「""」でくくった文字列で、好きな名前を付ける。
※ここでは`"MYTESTDLGBASE_MAIN"`とした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/978f41c8-c745-fa5b-b88a-4272de9ea2d2.png)

### 4.ボタンの追加

ダイアログには、元々OKボタンとCancelボタンがついているが、追加でボタンを1個追加する。
「ツールボックス」の中の「Button」を選択して、ダイアログエディタの中のダイアログの上でクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/760afca3-ded3-c890-da75-25d2a52aa460.png)
ボタンが出来上がる。
作ったボタンのプロパティを見ると、IDが「IDC_BUTTON1」となっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/26b7c42f-9870-654e-edd3-1038f5573ea4.png)

### 5.ダイアログプロシージャを書く

次に、メインのcppファイルに戻って、実験用ダイアログのプロシージャを書く。
追加したボタンを押したときの処理を書きたい場合は`case IDC_BUTTON1:`のところに書く。
(今回は、なにも中身のないMsgBoxを試しに出している)

```cpp
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg) {
    case WM_COMMAND:
        switch (LOWORD(wp)) {
        case IDOK:
            EndDialog(hDlg, IDOK);
            return TRUE;
        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            return TRUE;
        case IDC_BUTTON1:
            MessageBox(NULL, L"", L"", MB_OK);
            break;
        }
        return FALSE;
    }
    return FALSE;
}
```

### 6.DialogBoxを呼ぶ

`wWinMain()`の中で、上で作ったダイアログプロシージャを指定して、`DialogBox()`を呼ぶ。

```cpp
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    hInst = hInstance;

    // ダイアログの名前と、プロシージャを指定してDialogBoxを開く
    DialogBox(hInst, L"MyTestDlgBase_Main", NULL, (DLGPROC)MyDlgProc);

    return (int)0;
}
```

これで、とりあえず最小限のダイアログが開く。
コントロール類を追加したいときは、追加したボタンと同じようなやり方で追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/91d0a43d-ed76-6106-1b61-abc73401340b.png)

# メイン部分のコード全体

```WindowsProject1.cpp
#include "framework.h"
#include "WindowsProject1.h"
#include "resource.h"

// グローバル変数:
HINSTANCE hInst;

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

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

    DialogBox(hInst, L"MyTestDlgBase_Main", NULL, (DLGPROC)MyDlgProc);

    return (int)0;
}

// ダイアログプロシージャ
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg) {
    case WM_COMMAND:
        switch (LOWORD(wp)) {
        case IDOK:
            EndDialog(hDlg, IDOK);
            return TRUE;
        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            return TRUE;
        case IDC_BUTTON1:
            MessageBox(NULL, L"", L"", MB_OK);
            break;
        }
        return FALSE;
    }
    return FALSE;
}
```


# 参考

猫でもわかるWindowsプログラミング
http://www.kumei.ne.jp/c_lang/index_sdk.html