ビジュアルスタイルでコントロールの描画をするために uxtheme.dll の関数を使用します。
OSにdllが存在することを確認するため、リンカの設定で uxtheme.dll を遅延読み込み(/DELAYLOAD)に指定します。
基本的な描画の手順は次のようになります。
(1)OpenThemeData でテーマを開く。
(2)DrawThemeBackground で背景イメージを描画。
(3)GetThemeBackgroundContentRect でコントロールのコンテンツ領域を取得。
(4)DrawThemeText でテキストを描画。
(5)CloseThemeData でテーマを閉じる。
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tchar.h>
#include <uxtheme.h>
#include <tmschema.h>
#pragma comment(lib, "uxtheme.lib")
#define IDM_EXIT 101
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool IsThemingSupported();
HINSTANCE hInst;
LPCTSTR lpszAppName = TEXT("MyApp");
LPCTSTR lpszAppTitle = TEXT("MyApp");
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg = {0};
HWND hWnd;
WNDCLASSEX wc = {0};
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
//メインウィンドウクラス登録
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = lpszAppName;
wc.hIconSm = NULL;
if(RegisterClassEx(&wc) == 0) {
return 0;
}
hInst = hInstance;
//メニュー作成
HMENU hMenu = CreateMenu();
HMENU hPopMenu = CreatePopupMenu();
AppendMenu(hPopMenu, MF_STRING, IDM_EXIT, TEXT("&Exit"));
AppendMenu(hMenu, MF_POPUP | MF_STRING, reinterpret_cast<UINT_PTR>(hPopMenu), TEXT("&File"));
//メインウインドウ作成
hWnd = CreateWindow(lpszAppName, lpszAppTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, hMenu, hInstance, NULL
);
if(hWnd == NULL) {
return 0;
}
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
//メイン メッセージ ループ
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static bool isThemingSupported = IsThemingSupported();
static HTHEME hThemeButton = NULL;
switch(uMsg) {
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_EXIT: //終了
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_CREATE:
{
if(isThemingSupported) {
hThemeButton = OpenThemeData(hWnd, L"BUTTON");
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
RECT rect = {100, 100, 200, 200};
if(hThemeButton != NULL) {
//ビジュアルスタイル適用あり
HRESULT hr = DrawThemeBackground(hThemeButton, ps.hdc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL);
if(SUCCEEDED(hr)) {
RECT contentRect;
hr = GetThemeBackgroundContentRect(hThemeButton, ps.hdc, BP_PUSHBUTTON, PBS_NORMAL, &rect, &contentRect);
if(SUCCEEDED(hr)) {
LPCWSTR pszText = L"button";
DrawThemeText(hThemeButton, ps.hdc, BP_PUSHBUTTON, PBS_NORMAL, pszText, lstrlenW(pszText),
DT_CENTER | DT_VCENTER | DT_SINGLELINE, 0, &contentRect);
}
}
}
else {
//ビジュアルスタイル適用なし
if(DrawFrameControl(ps.hdc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH)) {
LPCTSTR pszText = TEXT("button");
SetBkMode(ps.hdc, TRANSPARENT);
DrawText(ps.hdc, pszText, lstrlen(pszText), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
EndPaint(hWnd, &ps);
}
break;
case WM_THEMECHANGED:
{
if(hThemeButton != NULL) {
CloseThemeData(hThemeButton);
}
if(isThemingSupported) {
hThemeButton = OpenThemeData(hWnd, L"BUTTON");
}
}
break;
case WM_DESTROY:
{
if(hThemeButton != NULL) {
CloseThemeData(hThemeButton);
}
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
bool IsThemingSupported()
{
HINSTANCE hThemeDll = LoadLibrary(TEXT("uxtheme.dll"));
bool themingSupported = (hThemeDll != NULL);
if(hThemeDll != NULL) {
FreeLibrary(hThemeDll);
}
return themingSupported;
}