potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

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のハンドルを使用した方が適切かと思います。