画面がなければ、何もできない!
ということで、画面(window)を表示させるところからスタートです。
プロジェクトの作成
Visual Studioで新しいプロジェクトを作成します。
余計なものが含まれていない、「空のプロジェクト」にします。
空のプロジェクトを選択し、「次へ」で構成の設定へ。
プロジェクト名と場所を適当に設定します。
「ソリューションとプロジェクトを同じディレクトリに配置する」はどちらでも構いません。
設定が終わったら「作成」で完了です。
ソースファイルの追加
空の状態なので、cppファイルを追加します。
ソリューションエクスプローラーにあるプロジェクトを右クリック。
「追加」から「新しい項目」を選択します。
このままファイル名を変更して「追加」で問題ありませんが、今回は他のテンプレートも確認するために「すべてのテンプレートの表示」を選んでみます。
C++ファイルを選び、名前を「main.cpp」に変更します。(場所は初期値で問題なし)
変更が終わったら「追加」で完了です。
※「コンパクトビューの表示」で最初に出てきた表示に戻ります。
ウィンドウの作成
準備が完了したので、今回の目的であるウィンドウの表示です。
main.cppに以下を書きます。
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ウィンドウクラス
WNDCLASSEX wc{};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = DefWindowProc;
wc.lpszClassName = TEXT("practice"); // 文字は自由
wc.hInstance = hInstance;
// ウィンドウクラスを登録
RegisterClassEx(&wc);
// ウィンドウを作成
HWND hwnd = CreateWindow(
wc.lpszClassName,
TEXT("DX12を学びたい"), // 自由
WS_OVERLAPPEDWINDOW, // ウィンドウスタイル
CW_USEDEFAULT, // 位置x
CW_USEDEFAULT, // 位置y
CW_USEDEFAULT, // 幅
CW_USEDEFAULT, // 高さ
nullptr, // 親ウィンドウ
nullptr, // メニュー
wc.hInstance,
nullptr // 追加データ
);
// ウィンドウ表示
ShowWindow(hwnd, SW_SHOW);
// 登録の解除
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
書き終えたら「F5」を押して、デバッグを開始してみましょう。
一瞬何かが表示されて、すぐに消えたら問題なく動作しています。
これだとゲームどころではないので、次はウィンドウが消えないようにします。
「error LNK2019: 未解決の外部シンボル」と表示されていたら、プロパティの設定で解消できます。
プロパティの設定を開きましょう。
プロジェクトを右クリックし、プロパティを選択します。
リンカーのシステムからサブシステムを「Windows」に変更して「OK」。
これでエラーが解消されるはずです。
ウィンドウの表示
アプリケーションが終わらないようにループする処理を追加します。
下記をウィンドウ表示処理の後に追記しましょう。
// ループ
MSG msg = {};
while (true)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 終了
if (msg.message == WM_QUIT) {
break;
}
}
追記したら「F5」でデバッグ開始!
今度はウィンドウが表示され続けているはず。
これで完了!
と思いきや、これだとウィンドウを閉じても実行が終了しませんでした。
messageがWM_QUITにならないのが原因で、次はウィンドウを閉じたらプログラムも終了するように処理を追加します。
ウィンドウプロシージャの設定
プロシージャとは?
となったので、調べました。
プロシージャ:複数の命令や処理などを一つにまとめもの
雑に言うとウィンドウ関連の処理をまとめた関数がウィンドウプロシージャ。
上記では既定のウィンドウプロシージャを設定していました。
// この部分
wc.lpfnWndProc = DefWindowProc;
このままだとダメなので、自分でウィンドウプロシージャを用意します。
// ウィンドウプロシージャ
LRESULT WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
// ウィンドウが破棄される
if (msg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
ウィンドウの破棄(WM_DESTROY)が送られたとき、messageをWM_QUITにする関数を呼びます。続いて0を返す処理を追加しました。他の場合は既定の処理に。
あとは、自作のウィンドウプロシージャを使用するように変更します。
wc.lpfnWndProc = WindowProc;
「F5」でデバッグ開始!
ウィンドウを閉じると、デバッグも終了されました!
さいごに
とりあえずウィンドウが出たらOKということで、WNDCLASSEXやCreateWindowの引数はほぼデフォルトにしています。
スタイルやサイズなど、色々設定できるので変更したい場合は調べてみてください。
今回で準備回は終わりです。
次回からはDirextXを使用するはず!
コメント