DirectX12 ① ウィンドウの作成

開発環境

言語 : C++
開発環境 : Visual Studio 2020
OS : Windows10
CPU : AMD Ryzen5 3600
RAM : 24.0GB
GPU : NVIDIA GeForce GTX 1050

DirectX12について

ここでは、Direct3D 12のことをDirectX12と呼ぶ。DirectX12は、Microsoftが開発する、DirectX12互換GPUを搭載したPCにおいてグラフィックス機能や計算機能をアプリケーションで利用すためのAPIである。

Win32 APIについて

ウィンドウの表示にはWin32 APIを使う。
Win32 APIは、ウィンドウの描画などWindowsの機能を使用するためのAPIである。
DirectX12はOpenGLのようにglutやGLFWなどの簡単にウィンドウを表示するための機能がないため、Win32 APIによってウィンドウの表示を行う。



main.cpp

#include "App.h"

int main() {
    App app(1080, 720);
    app.Run();
}

App.h

#pragma once

#include <Windows.h>
#include <cstdint>
#include <string>

class App {
public:
    App(uint32_t width, uint32_t height);

    void Run();

private:
    bool InitApp();
    bool InitWindow();

    void MainLoop();

    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

private:
    const std::wstring WindowClassName = L"WindowClass";

    uint32_t _width;
    uint32_t _height;

    HWND _hwnd;
    HINSTANCE _hInstance;

};

App.cpp

#include "App.h"

App::App(uint32_t width, uint32_t height) {
    _width = width;
    _height = height;
    _hwnd = nullptr;
    _hInstance = nullptr;
}

void App::Run() {
    if (!InitApp()) {
        return;
    }

    MainLoop();
}

//初期化
bool App::InitApp() {

    if (!InitWindow()) {
        return false;
    }

    return true;
}

//ウィンドウの初期化
bool App::InitWindow() {
    _hInstance = GetModuleHandle(nullptr);
    if (_hInstance == nullptr) {
        return false;
    }

    //ウィンドウの設定
    WNDCLASSEX wc = {};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;     //水平方向と垂直方向のサイズ変更で再描画
    wc.lpfnWndProc = WndProc;   //ウィンドウプロシージャの登録
    wc.hIcon = LoadIcon(_hInstance, IDI_APPLICATION);    //アイコン
    wc.hCursor = LoadCursor(_hInstance, IDC_ARROW);      //マウスカーソル
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //背景色は黒
    wc.hInstance = _hInstance;  //インスタンスハンドル
    wc.lpszMenuName = nullptr;  //メニュー
    wc.lpszClassName = WindowClassName.c_str();      //ウィンドウクラスの名前
    wc.hIconSm = LoadIcon(_hInstance, IDI_APPLICATION);      //小さいアイコン

    RegisterClassEx(&wc);    //ウィンドウクラスの登録

    //ウィンドウサイズ
    RECT rc = {};
    rc.right = static_cast<long>(_width);    //ウィンドウの幅
    rc.bottom = static_cast<long>(_height); //ウィンドウの高さ

    auto style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
    AdjustWindowRect(&rc, style, false);

    _hwnd = CreateWindowEx(
        0,
        WindowClassName.c_str(),
        L"Title",
        style,
        CW_USEDEFAULT, CW_USEDEFAULT,
        rc.right - rc.left, rc.bottom - rc.top,
        nullptr, nullptr,
        _hInstance,
        nullptr
    );

    ShowWindow(_hwnd, SW_SHOWNORMAL);

    SetFocus(_hwnd);

    return true;
}

//メインループ
void App::MainLoop() {
    MSG msg = {};
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE == true))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            // ここに描画処理を書く


        }
    }
}

//ウィンドウプロシージャ
LRESULT CALLBACK App::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        break;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

実行結果