// Unicode文字セット
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#define WIDTH(rect) ((rect).right - (rect).left)
#define HEIGHT(rect) ((rect).bottom - (rect).top)
#define CLASS_NAME TEXT("StaticDraw")
// 関数プロトタイプ宣言
void Trace(LPCTSTR format, ...);
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg);
HWND CreateWnd(HINSTANCE hInstance, HWND hDlg);
LRESULT CALLBACK NewWndWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubClsWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnPaint(HWND hWnd, int nCtrlID);
void OnDrawItem(WPARAM wParam, LPARAM lParam);
// 外部変数構造体
static struct {
HINSTANCE hInstance;
HFONT hFont;
} g;
static WNDPROC PrevWndFunc;
//==============================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
g.hInstance = hInstance;
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);
return 0;
}
//------------------------------------------------------------------------------
void Trace(LPCTSTR format, ...)
{
va_list arg_ptr;
TCHAR buffer[256];
int size;
va_start(arg_ptr, format);
size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr);
va_end(arg_ptr);
OutputDebugString(buffer);
if (size < 0) {
OutputDebugString(L"...\n");
}
}
//------------------------------------------------------------------------------
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR nRet = TRUE; // メッセージを処理した
switch (uMsg) {
case WM_DRAWITEM:
OnDrawItem(wParam, lParam);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
case WM_SIZE:
{
POINTS pts = MAKEPOINTS(lParam);
Trace(L"WM_SIZE(%u, %d, %d)\n", wParam, pts.x, pts.y);
}
break;
case WM_INITDIALOG:
OnInitDialog(hDlg);
nRet = TRUE; // SetFocusでフォーカスを設定した場合はFALSE
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_DESTROY:
Trace(L"WM_DESTROY\n");
DeleteObject(g.hFont);
break;
default:
nRet = FALSE; // メッセージを処理しなかった
}
return nRet;
}
//------------------------------------------------------------------------------
void OnInitDialog(HWND hDlg)
{
HWND hWnd;
// 縦書きフォントの作成
LOGFONT lf;
ZeroMemory(&lf, sizeof lf);
lf.lfHeight = -20;
lf.lfEscapement = 2700;
lf.lfOrientation= 2700;
wcscpy_s(lf.lfFaceName, L"@MS Pゴシック");
g.hFont = CreateFontIndirect(&lf);
// ダイアログをクライアント領域に合わせる
RECT rcWindow;
RECT rcClient;
GetWindowRect(hDlg, &rcWindow);
GetClientRect(hDlg, &rcClient);
SetWindowPos(hDlg, NULL, 0, 0,
800 + (WIDTH(rcWindow) - WIDTH(rcClient)),
400 + (HEIGHT(rcWindow) - HEIGHT(rcClient)),
SWP_NOZORDER | SWP_NOMOVE);
// 新規ウィンドウ
hWnd = CreateWnd(g.hInstance, hDlg);
// サブクラス化
hWnd = CreateWindow(
L"static", NULL,
WS_CHILD | WS_VISIBLE,
300, 50, 200, 300,
hDlg, (HMENU)IDC_SUBCLS, g.hInstance, NULL);
PrevWndFunc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)SubClsWndProc);
// オーナードロー
hWnd = CreateWindow(
L"static", NULL,
WS_CHILD | WS_VISIBLE | SS_OWNERDRAW,
550, 50, 200, 300,
hDlg, (HMENU)IDC_OWNDRAW, g.hInstance, NULL);
}
//==============================================================================
HWND CreateWnd(HINSTANCE hInstance, HWND hDlg)
{
// ウィンドウクラスの登録
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof wcx);
wcx.cbSize = sizeof wcx;
// wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = NewWndWndProc;
wcx.hInstance = hInstance;
wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcx.lpszClassName = CLASS_NAME;
if (RegisterClassEx(&wcx) == 0) {
return NULL;
}
// ウィンドウの作成
HWND hWnd = CreateWindow(
CLASS_NAME, NULL,
WS_CHILD | WS_VISIBLE,
50, 50, 200, 300,
hDlg, (HMENU)IDC_NEWWND, hInstance, NULL);
return hWnd;
}
//------------------------------------------------------------------------------
LRESULT CALLBACK NewWndWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_PAINT:
OnPaint(hWnd, IDC_NEWWND);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//------------------------------------------------------------------------------
LRESULT CALLBACK SubClsWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_PAINT:
OnPaint(hWnd, IDC_SUBCLS);
return 0;
}
return CallWindowProc(PrevWndFunc, hWnd, uMsg, wParam, lParam);
}
//------------------------------------------------------------------------------
void OnPaint(HWND hWnd, int nCtrlID)
{
LPCTSTR pszStr;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
switch (nCtrlID) {
case IDC_NEWWND:
pszStr = L"新規ウィンドウ";
break;
case IDC_SUBCLS:
pszStr = L"サブクラス化";
FillRect(hdc, &ps.rcPaint, GetSysColorBrush(COLOR_WINDOW));
break;
default:
goto Exit;
}
Trace(L"OnPaint(%s)\n", pszStr);
HGDIOBJ hFontOld = SelectObject(hdc, g.hFont);
TextOut(hdc, 100, 100, pszStr, wcslen(pszStr));
SelectObject(hdc, hFontOld);
Exit:
EndPaint(hWnd, &ps);
}
//------------------------------------------------------------------------------
void OnDrawItem(WPARAM wParam, LPARAM lParam)
{
static LPCTSTR pszStr = L"オーナードロー";
LPDRAWITEMSTRUCT pdi = (LPDRAWITEMSTRUCT)lParam;
Trace(L"OnDrawItem(%u)\n", wParam);
HDC hdc = pdi->hDC;
SetBkMode(hdc, TRANSPARENT); // 背景透過モード
// 背景塗り潰し
RECT rc;
GetClientRect(pdi->hwndItem, &rc);
FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
HGDIOBJ hFontOld = SelectObject(hdc, g.hFont);
TextOut(hdc, 100, 100, pszStr, wcslen(pszStr));
SelectObject(hdc, hFontOld);
}