VisualStudioでC++言語を利用したWin32アプリケーションを作成する手順

## [1.]概要

### [1-1.]作業目的

「Microsoft Visual Studio」(以下VisualStudio)の「Visual C++ Community」を利用して、Windowsのメッセージボックスを表示するアプリケーションを作成する。
利用する言語はC++として、「新しいプロジェクトの作成」のウィザードの「空プロジェクト」を選択して、プロジェクトを作成する手順とする。

### [1-2.]環境・前提条件

本件手順では、以下Windows環境にMicrosoft Visual Studioがインストールされている前提とする。

- エディション：Microsoft Windows 10 Pro
- システムの種類：64 ビット オペレーティング システム、x64 ベース プロセッサ
- バージョン：21H2
- OSビルド 19044.2006
- エクスペリエンス：Windows Feature Experience Pack 120.2212.4180.0
- Microsoft Visual Studio：Microsoft Visual Studio Community 2022 (64 ビット)  CurrentVersion 17.3.5

### [1-3.]参考ページ

- [Visual C++ Win32アプリケーション作成 / インコのWindowsSDK](http://gurigumi.s349.xrea.com/programming/visualcpp/win32api2013_1.html)  
- [VC++ Windows Programming](https://web.archive.org/web/20190912204705/http://www-higashi.ist.osaka-u.ac.jp/~k-maeda/vcpp/)  
- [VC++ Windows Programming - Section5.1 ファイル入出力](https://web.archive.org/web/20190911014931/http://www-higashi.ist.osaka-u.ac.jp/~k-maeda/vcpp/sec5-1file.html)
- [ゼロからはじめるWindows API - WinMain 関数 すべての始まり編](https://news.mynavi.jp/article/20090525-windowsapi/)
- [【DXライブラリ】LNK2019未解決の外部シンボルが出た時の対処法](https://www.ay3s-room.com/entry/dxlib-lnk2019)
- [DXライブラリによるゲーム作成 - Qiita](https://qiita.com/nekoshiki0904/items/7a948220da0ac6f1677f)

## [2.]空プロジェクトの作成

[手順1.]「Visual Studio Community 2022」を起動して、起動メニューで「新しいプロジェクトの作成」を選択する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/67ed8adb-8f80-6459-dba2-8a7d3baf686a.png" width=50%>

[手順2.]次の画面で「空のプロジェクト」を選択して、「次へ」を押す。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/6fdf591c-a5a8-46ee-1b3b-fdf2f246b243.png" width=50%>

[手順3.]「空のプロジェクト」のプロパティを入力する。最後に「作成」を押す。

- プロジェクト名：Project1
- 場所：<任意の場所を指定>
- ソリューション名：Project1
- 「ソリューションとプロジェクトを同じフォルダに配置する」にチェックは入れない

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/755f1a32-5483-331c-b8f8-07ba863e7902.png" width=50%>

[手順4.]空プロジェクトが作成されるので、「ファイル」→「終了」を選択してプロジェクトを終了する。

## [3.]プロジェクトのプロパティ変更

### [3-1.]デバッグモードの設定

[手順1.]フォルダ「<プロジェクトを配置したフォルダ>\Project1」に格納されている「Project1.vcxproj」を選択して実行する。
[手順2.]上段の「構成」の値を「Debug」に変更する。
[手順3.](必要に応じて)上段で「プラットフォーム」の値を「x86」に変更する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/270c75ce-53c4-ec5f-0bd6-e0c993dc5185.png" width=50%>

### [3-2.]WindowsAPIライブラリの設定

[手順1.]ソリューションエクスプローラーを「Project1」を選択する。
[手順2.]「プロジェクト」→「プロパティ」を選択する。
[手順3.]構成を「すべての構成」、プラットフォームを「すべてのプラットフォーム」を選択する。
[手順4.]「構成プロパティ」→「リンカー」→「システム」→「サブシステム」を選択する。
[手順5.]「サブシステム」を「コンソール (/SUBSYSTEM:CONSOLE)」から「Windows(/SUBSYTEM:WINDOWS)」に変更して、「適用」を押す。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/4fca41e2-37c9-d8ad-6261-6a31d7a28c6b.png" width=50%>

### [注意事項]

「サブシステム」で「Windows(/SUBSYTEM:WINDOWS)」が選択されていない場合は、ビルド実行した際に「未解決の外部シンボル」のエラーが出力しビルドに失敗する。

(ビルドに失敗した場合のメッセージ)

```
ビルドを開始しました...
1>------ ビルド開始: プロジェクト: Project1, 構成: Debug Win32 ------
1>project1.cpp
1>MSVCRTD.lib(exe_main.obj) : error LNK2019: 未解決の外部シンボル _main が関数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) で参照されました
1><プロジェクトを配置したフォルダ>\Project1\Debug\Project1.exe : fatal error LNK1120: 1 件の未解決の外部参照
1>プロジェクト "Project1.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 成功 0、失敗 1、最新の状態 0、スキップ 0 ==========
```

### [3-3.]マルチバイト文字セットの設定

[手順1.]「構成プロパティ」→「詳細」→「文字セット」を選択する。
[手順2.]「文字セット」を「マルチバイト文字セットを使用する」に変更して、「適用」を押す。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/34e8be4b-6901-a8c6-753f-98e73babc207.png" width=50%>

### [注意事項]

「文字セット」で「マルチバイト文字セット」が指定されていない場合は、ソース内に全角文字を使用してビルド実行した際に「文字型の不一致」のエラーが出力しビルドに失敗する。

(ビルドに失敗した場合のメッセージ)

```
ビルドを開始しました...
1>------ ビルド開始: プロジェクト: Project1, 構成: Debug Win32 ------
1>project1.cpp
1><プロジェクトを配置したフォルダ>\Project1\Project1\project1.cpp(9,56): error C2664: 'int MessageBoxW(HWND,LPCWSTR,LPCWSTR,UINT)': 引数 2 を 'const char [9]' から 'LPCWSTR' へ変換できません。
1><プロジェクトを配置したフォルダ>\Project1\Project1\project1.cpp(9,19): message : 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたはかっこで囲まれた関数スタイル キャストが必要です。
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\winuser.h(9161,1): message : 'MessageBoxW' の宣言を確認してください
1>プロジェクト "Project1.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 成功 0、失敗 1、最新の状態 0、スキップ 0 ==========
```

## [4.]プロジェクトにソースファイルを追加する

### [4-1.]cppファイルの追加

[手順1.]「Project1」→「ソースファイル」を右クリックする。
[手順2.]「追加」→「新しい項目」を選択する
[手順3.]「C++ファイル(.cpp)」を選択する。ファイル名はプロジェクト名と同一とする。

名前：project1.cpp

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/a2c6d509-4a96-6a16-2bd9-fef3a3778e26.png" width=50%>

[手順4.]以下ファイルが追加されたことを確認する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/92f70622-08cc-5f35-2687-b54e4e682e42.png" width=50%>

[手順5.]ファイル」→「終了」を選択して一旦プロジェクトを終了する。確認画面で「上書き保存」を押す。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/36f847a1-5577-58a1-939b-6cb8d3af04f7.png" width=50%>

### [4-2.]ソースファイルの書き込み
「project1.cpp」ファイルに以下ソースを追記する。
保存するテキストファイル(ソースファイル)は、以下フォーマットとする。

(テキストファイルのフォーマット)
* 文字コード：SJIS
* 改行コード：CR+LF

(追記するソースコード)

```
#include <windows.h>

// プロトタイプ宣言
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

// Windows Main 関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){

	MessageBox(NULL, "処理終了", "処理終了", MB_OK);

	return 0;

}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/cf590005-ec4c-64f3-fabc-457bbc1e7ff8.png" width=50%>

## [5.]ビルドの実行(Debugビルド)

[手順1.]「ビルド」→「Project1のビルド」を選択する。
[手順2.]以下のメッセージが表示されて、ビルドが正常終了したことを確認する。

(ビルドが正常終了したメッセージ)

```
ビルドを開始しました...
1>------ ビルド開始: プロジェクト: Project1, 構成: Debug Win32 ------
1>project1.cpp
1>Project1.vcxproj -><プロジェクトを配置したフォルダ>\Project1\Debug\Project1.exe
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/7797ba41-8273-3406-b3cc-8719138dd08a.png" width=50%>

## [6.]実行確認(Debugビルド)

[手順1.]フォルダ「<プロジェクトを配置したフォルダ>\Project1\Debug」に作成された「Project1.exe」を選択して実行する。
[手順2.]「処理終了」のメッセージが表示されたら、「OK」のボタンを押してアプリケーションを終了する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77425/0cdc4f82-4289-f54a-efa2-8bb21609a22c.png" width=50%>

## [7.]pdbファイルの抑止(Releaseビルド)
Releaseビルドを行う場合には、必要に応じてpdbファイルの出力を抑止する。

1. 上部メニューバーから、[プロパティ] を選択します。
1. [構成] ボックスの一覧を[リリース]に変更します。
1. サイド ペインで、[リンカー] > [デバッグ] を選択し、[デバッグ情報の生成] のオプションを選択します。
1. [デバッグ情報を生成] の既定値で「いいえ」を選択します。
1. 下段の[適用]を押す
1. . [リリース]でビルドを行い、フォルダ[x64\Release]で「.pdbファイル」が作成されていないことを確認します。

* 参考情報(pdbファイル作成の無効化)
    * [VisualStudio2022でReleaseビルドするときにpdbファイルを出力しないようにする(VC++版)](https://qiita.com/techmilestone/items/521e953999da101d5c66)
    * [ビルド (C#、C++、Visual Basic、F#) のシンボル (.pdb) ファイルを生成する](https://learn.microsoft.com/ja-jp/visualstudio/debugger/how-to-set-debug-and-release-configurations?view=vs-2022#BKMK_symbols_release)
    * (C#の無効化手順)[VisualStudio2022でReleaseビルドするときにpdbファイルを出力しないようにする](https://qiita.com/yusuke-sasaki/items/a05e68ef855cea1165c2)

## [8.]「Previous IPDB not found」メッセージの抑止(Releaseビルド)
デフォルト設定では「Previous IPDB not found」メッセージが出力する。
```
16:13 でビルドが開始されました...
1>------ ビルド開始: プロジェクト: mjstest, 構成: Release x64 ------
1>mjstest.cpp
1>コード生成しています。
1>Previous IPDB not found, fall back to full compilation.
1>All 9 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
1>コード生成が終了しました。
1>mjstest.vcxproj -> C:\Users\user\source\repos\mjstest\x64\Release\mjstest.exe
========== ビルド: 成功 1、失敗 0、最新の状態 0、スキップ 0 ==========
=========== ビルド は 16:13 で完了し、01.385 秒 掛かりました ==========
```

以下手順でメッセージを抑止する
1. 上部メニューバーから、[プロパティ] を選択します。
1.  [構成] ボックスの一覧を[リリース]に変更します。
1.  サイド ペインで、[リンカー] > [すべてのオプション] を選択し、[リンク時のコード生成] のオプションを選択します。
1.  [リンク時のコード生成] の既定値で「リンク時のコード生成を使用(/LTCG)」を選択します。
1.  下段の[適用]を押す。
1.  [リリース]でビルドを行い、上記メッセージがされていないことを確認します。

* 参考情報(メッセージ抑止)
    * [MSVCコンパイル時に表示される「Previous IPDB not found, fall back to full compilation」メッセージについて](https://tech.sadari.co.jp/dev_program/visual-cc/msvc-ltcg-ipdb-not-fount/)

以上