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

しーくさんのUp & Down - Thinking Notes

更新頻度はあまり高くないです。プログラミングやLinuxなどのことについてや、果てはゲーム記事まで。

AeroGlassっぽいやつをWINAPIで設定したウィンドウを作る

C/C++ Tips Win32

こんな感じのやつね。
f:id:uys:20151017232320p:plain

#ifndef WINVER
#define WINVER 0x0600 //Vista以降をサポート(DWM≒AeroGlass用)
#endif

#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

//DWM(AeroGlass)用
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")

namespace g {
	const TCHAR* CLASS_NAME = _T("__Win32_DWM_Window_Test__");
	const TCHAR* TITLE_DEFAULT = _T("Win32 Guided Tour Application");
};

//DWM(AeroGlass)を使用可能かチェックします
bool CheckEnableDWM() {
	BOOL enable = FALSE;
	DwmIsCompositionEnabled(&enable);
	if (enable)
		return true;
	else
		return false;
}

//DWM(AeroGlass)を有効化します
void EnableDWM(HWND hWnd) {
	DWM_BLURBEHIND dwm_bb;
	dwm_bb.dwFlags = DWM_BB_ENABLE;
	dwm_bb.fEnable = TRUE;
	DwmEnableBlurBehindWindow(hWnd, &dwm_bb);
}
//DWM(AeroGlass)を使用できるかチェックし、有効化します
//マージンの設定で-1を指定すると、クライアント領域全体に拡張されます。
void SetDWM(HWND hWnd, bool extend = true, MARGINS margin = {-1}) {
	//DWMが使用可能?
	if (CheckEnableDWM()) {
		//可能なので設定する
		EnableDWM(hWnd);
		if (extend) {
			DwmExtendFrameIntoClientArea(hWnd, &margin);
		}
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
	switch (msg) {
	case(WM_CREATE):
		SetDWM(hWnd);
		break;
	case(WM_DWMCOMPOSITIONCHANGED) ://時折流れてくるメッセージらしい。
		//無効化されてるので、必要なら再度チェックしてから有効化する。
		SetDWM(hWnd);
		break;
	case(WM_DESTROY) :
		PostQuitMessage(0);
		break;
	default:
		return ::DefWindowProc(hWnd, msg, wp, lp);
	}
	return 0;
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wcex = { 0 };
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.lpfnWndProc = ::WndProc;
	wcex.hInstance = hInstance;
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.hbrBackground = GetStockBrush(BLACK_BRUSH);
	wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcex.lpszClassName = g::CLASS_NAME;
	wcex.lpszMenuName = nullptr;
	if (!RegisterClassEx(&wcex)) {
		MessageBox(NULL, _T("Call to RegisterClassEx is Failed!"), _T("Error-Info"), MB_OK | MB_ICONERROR);
		return 1;
	}

	HWND hWnd = CreateWindow(
		g::CLASS_NAME,
		g::TITLE_DEFAULT,
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		CW_USEDEFAULT, CW_USEDEFAULT,
		800, 600,
		NULL,
		NULL,
		hInstance,
		NULL);

	if (hWnd == NULL) {
		MessageBox(NULL, _T("Call to CreateWindow is Failed!"), _T("Error-Info"), MB_OK | MB_ICONERROR);
		UnregisterClass(g::CLASS_NAME, hInstance);
		return 1;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (int)msg.wParam;
}