potisanのプログラミングメモ

プログラミング素人です。昔の自分を育ててくれたネット情報に少しでも貢献できるよう、情報を貯めていこうと思っています。Windows環境のC++やC#がメインです。

C++17 Win32 APIでウィンドウを表示する

Win32 APIでウィンドウを表示するよくあるサンプルコードです。ウィンドウのクライアント領域に青い正方形を描画します。

#include <memory>

#define STRICT
#define NOMINMAX
#include <Windows.h>

static const auto MainWindowClassName = L"MainWindow";
static const auto MainWindowTitle = L"MainWindow";
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

using unique_brush_handle = std::unique_ptr<std::remove_pointer_t<HBRUSH>, decltype(&DeleteObject)>;
unique_brush_handle CrateSolidBrush_unique(COLORREF color) noexcept;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int iCmdShow)
{
    // メインウィンドウのウィンドウクラス登録
    WNDCLASSEXW wcex{
        sizeof(WNDCLASSEXW),
        CS_HREDRAW | CS_VREDRAW,
        WndProc,
        0,
        0,
        hInstance,
        nullptr,
        LoadCursor(nullptr, IDC_ARROW),
        reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1),
        nullptr,
        MainWindowClassName };
    if (!RegisterClassExW(&wcex))
    {
        return GetLastError();
    }

    // メインウィンドウの作成・表示
    auto hwnd = CreateWindowExW(
        WS_EX_OVERLAPPEDWINDOW,
        MainWindowClassName,
        MainWindowTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        nullptr, nullptr, hInstance, nullptr);
    if (hwnd == nullptr)
    {
        return GetLastError();
    }
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    // メッセージループ
    MSG msg;
    int ret;
    while (ret = GetMessageW(&msg, nullptr, 0, 0))
    {
        if (ret == -1)
        {
            break;
        }
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            auto hdc = BeginPaint(hwnd, &ps);

            RECT rcFill{ 0, 0, 100, 100 };
            auto hbr = CrateSolidBrush_unique(0x00ff0000);
            FillRect(hdc, &rcFill, hbr.get());

            EndPaint(hwnd, &ps);
        }
        return TRUE;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}

unique_brush_handle CrateSolidBrush_unique(COLORREF color) noexcept
{
    return unique_brush_handle(::CreateSolidBrush(color), &::DeleteObject);
}

ブラシハンドルの解放を自動化するためにstd::unique_ptrを特殊化していますが、実際にはWILのハンドルを使用した方が適切かと思います。