読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

ゲーム用空󠄁のウィンドウテンプレ

DirectX等を使󠄁ふゲーム用の空󠄁のウィンドウを表示するテンプレ。

#define OEMRESOURCE
#include <Windows.h>

LRESULT CALLBACK WindowProcedure(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) {
  switch (msg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(wnd, msg, wp, lp);
  }
  return 0;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
  WNDCLASSEX wc = {};
  wc.cbSize = sizeof(wc);
  wc.lpfnWndProc = &WindowProcedure;
  wc.hInstance = GetModuleHandle(nullptr);
  wc.hCursor = static_cast<HCURSOR>(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED));
  wc.lpszClassName = "GameWindowClass";
  const auto atom = RegisterClassEx(&wc);
  if (!atom) {
    return -1;
  }
  const DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
  RECT rect = {0, 0, 640, 480};
  if (!AdjustWindowRect(&rect, style, FALSE)) {
    return -1;
  }
  const auto wnd = CreateWindow(MAKEINTATOM(atom), "GameWindowHelloWorld", style, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, nullptr, nullptr, nullptr, nullptr);
  if (!wnd) {
    return -1;
  }
  ShowWindow(wnd, SW_RESTORE);
  for (;;) {
    MSG msg;
    if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
      if (msg.message == WM_QUIT) {
        return static_cast<int>(msg.wParam);
      }
      DispatchMessage(&msg);
    }
  }
}


通󠄁常の空󠄁ウィンドウアプリ作成󠄁との違󠄂ひ

  • Direct3D等を用ゐて畫面をクリアするのでWNDCLASSEXのstyleの指定やhbrBackgroundの指定が不要󠄁
  • 窓のサイズが變更󠄁できないやうにウィンドウスタイルはWS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOXとする
  • CreateWindowで指定するウィンドウサイズは枠等を含んだサイズなのでAdjustWindowRectで描畫領域ベースで枠を含んだウィンドウサイズの計算をする
  • ショートカットを利用して最大化󠄁起󠄁動されないやうにShowWindowにはSW_RESTOREを渡す
  • GetMessageの代はりにPeekMessageを使󠄁ひメッセージがWM_QUITかどうかはメッセージループ內に自分󠄁で書く
  • 一般的にウィンドウプロシージャでキーボードの處理をしないのでメッセージ處理にはDispatchMessage函數だけ呼ぶ

猶󠄂、このコードを實行すると全󠄁力で無限ループを回るのでDirect3D等で垂直同期を自動で取るか自分󠄁でタイマーを用ゐて適󠄁度に休むかをしないと大變な事になる。