///
/// インクルード
///
#include <Windows.h>
#include <string>
#include <CommCtrl.h>
///
/// ライブラリのリンク
///
#pragma comment(lib, "comctl32.lib")
///
/// 定数
///
const std::wstring WINDOW_CAPTION_NAME{ L"Sample Skeleton" };
const std::wstring WINDOW_CLASS_NAME{ L"WINDOW PROGRAM" };
const int s_Window_Width{ 1280 };
const int s_Window_Height{ 720 };
const DWORD dwStyle { WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME };
const DWORD dwExStyle{ WS_EX_OVERLAPPEDWINDOW };
const UINT_PTR uIdSubclassMainWindowId{ 10000 };
///
/// プロトタイプ宣言
///
LRESULT CALLBACK MainWindowSubclassProc(HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);
///
/// グローバル変数
///
HINSTANCE g_hInstance = nullptr; // インスタンスハンドル
HWND g_hMainWindow = nullptr; // ウィンドウハンドル
BOOL g_fActive = FALSE; // アクティブフラグ
///
/// WinMain()
/// memo: Windows Programming において最初に呼ばれる関数
///
int WINAPI
WinMain(
HINSTANCE hInst, // 実行時のインスタンスハンドル
HINSTANCE hPrevInst, // Windows 95以降は常にNULL
LPSTR lpszCmdLine, // 実行時のコマンドライン
int nCmdShow) // 実行時のウィンドウの状態
{
// インスタンスハンドルのコピー
g_hInstance = hInst;
// ウィンドウクラスの設定
WNDCLASSEX wcex = {
sizeof(WNDCLASSEX),
CS_VREDRAW | CS_HREDRAW,
DefWindowProc,
0, 0,
static_cast<HINSTANCE>(GetModuleHandle(nullptr)),
LoadIcon(nullptr, IDI_APPLICATION),
LoadCursor(nullptr, IDC_ARROW),
static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)),
nullptr,
WINDOW_CLASS_NAME.c_str(),
nullptr,
};
// ウィンドウクラスの登録
if (!RegisterClassEx(&wcex)) {
LPCTSTR lpMessage{ TEXT("ウィンドウクラスの登録に失敗") };
LPCTSTR lpTitle{ TEXT("RegisterClassEx()") };
UINT type = MB_OK;
MessageBox(nullptr, lpMessage, lpTitle, type);
return 0;
}
HWND hwnd;
RECT window_rect, client_rect;
RECT window_size = { 0, 0, s_Window_Width, s_Window_Height };
const auto& target_width = window_size.right - window_size.left;
const auto& target_height = window_size.bottom - window_size.top;
// ウィンドウの作成
hwnd = CreateWindowEx(dwExStyle, WINDOW_CLASS_NAME.c_str(),
WINDOW_CAPTION_NAME.c_str(),
dwStyle, CW_USEDEFAULT, CW_USEDEFAULT,
target_width, target_height, nullptr, nullptr, g_hInstance, nullptr);
if (hwnd == nullptr) {
LPCTSTR lpMessage{ TEXT("ウィンドウの作成に失敗") };
LPCTSTR lpTitle{ TEXT("CreateWindowEx()") };
UINT type = MB_OK;
MessageBox(nullptr, lpMessage, lpTitle, type);
return 0;
}
if (!GetWindowRect(hwnd, &window_rect)) {
LPCTSTR lpMessage{ TEXT("ウィンドウ全体のサイズの取得に失敗") };
LPCTSTR lpTitle{ TEXT("GetWindowRect()") };
UINT type = MB_OK;
MessageBox(nullptr, lpMessage, lpTitle, type);
return 0;
}
if (!GetClientRect(hwnd, &client_rect)) {
LPCTSTR lpMessage{ TEXT("ウィンドウのクライアント領域のサイズの取得に失敗") };
LPCTSTR lpTitle{ TEXT("GetClientRect()") };
UINT type = MB_OK;
MessageBox(nullptr, lpMessage, lpTitle, type);
return 0;
}
// フレームサイズの算出
const int frame_size_x = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
const int frame_size_y = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
// リサイズ用のウィンドウサイズの算出
const int resize_width = frame_size_x + target_width;
const int resize_height = frame_size_y + target_height;
SetWindowPos(hwnd, nullptr, CW_USEDEFAULT, CW_USEDEFAULT, resize_width, resize_height, SWP_NOMOVE);
// ウィンドウハンドルのコピー
g_hMainWindow = hwnd;
// ウィンドウハンドルとプロシージャーの関連付け
SetWindowSubclass(g_hMainWindow, MainWindowSubclassProc, uIdSubclassMainWindowId, 0);
// ウィンドウの表示と描画の更新
ShowWindow(g_hMainWindow, nCmdShow);
UpdateWindow(g_hMainWindow);
// メッセージループ
MSG msg = {};
while (1) {
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
// ウィンドウがアクティブな時だけ処理をする
if (g_fActive) {
//
} else {
WaitMessage();
}
}
}
// ウィンドウクラスの登録解除およびウィンドウハンドルとプロシージャーの関連付けを解除
UnregisterClass(WINDOW_CLASS_NAME.c_str(), g_hInstance);
RemoveWindowSubclass(g_hMainWindow, MainWindowSubclassProc, uIdSubclassMainWindowId);
return static_cast<int>(msg.wParam);
}
///
/// MainWindowSubclassProc()
/// memo: 発行されたウィンドウメッセージの処理を行う
///
LRESULT CALLBACK MainWindowSubclassProc(
HWND hWnd, // メッセージが発行されたウィンドウハンドル
UINT msg, // 発行されたメッセージ
WPARAM wParam, // 発行されたメッセージの情報その1
LPARAM lParam, // 発行されたメッセージの情報その2
UINT_PTR uIdSubclass, // サブクラスID
DWORD_PTR dwRefData) // サブクラスの参照データ
{
switch (msg) {
case WM_ACTIVATEAPP:
g_fActive = static_cast<BOOL>(wParam);
return 0;
case WM_KEYDOWN:
switch (LOWORD(wParam)) {
case VK_ESCAPE:
DestroyWindow(hWnd);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefSubclassProc(hWnd, msg, wParam, lParam);
}