ウィンドウ操作


ウィンドウのサイズ変更

ユーザーによってウィンドウのサイズが変更された時もメッセージが発生します
これは、クライアントエリアのサイズが重要なプログラムにとって必要です

クライアントエリアのサイズは GetClientRect() で取得することができますが
描画毎にこれを取得するのは効率が悪いのです
クライアントエリアのサイズを得るべき瞬間は、ウィンドウの生成時と
ウィンドウのサイズ(クライアントエリアのサイズ)が変更された時です

そこで WM_SIZE メッセージを処理します
このメッセージは、ユーザーによってウィンドウサイズを変更された時に発生します

WPARAM パラメータにはリサイズフラグが入ります
これは、要求されるサイズ変更のタイプで次の定数のいずれかです

定数解説
SIZE_MAXIMIZED ウィンドウは最大表示されます
SIZE_MINIMIZED ウィンドウはアイコン化されます
SIZE_RESTORED ウィンドウはサイズ変更されますが
SIZE_MINIMIZED と SIZE_MAXIMIZED は適用されません
SIZE_MAXHIDE ほかのウィンドウが最大表示されたとき
すべてのポップアップ ウィンドウにメッセージが送られます
SIZE_MAXSHOW ほかのウィンドウが元のサイズに戻されたとき
すべてのポップアップ ウィンドウにメッセージが送られます

LPARAM は下位ワードにクライアントエリアの新しい横幅
上位ワードに、クライアントエリアの新しい高さが入ります

このメッセージを処理した場合、0を返します
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	static int width = 0, height = 0;
	static TCHAR strSize[128];

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_SIZE:
		width = LOWORD(lp);
		height = HIWORD(lp);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd , &ps);
		wsprintf(strSize , "width = %d : height = %d" , width , height);
		TextOut(hdc , 10 , 10 , strSize , lstrlen(strSize));
		EndPaint(hwnd , &ps);
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
	return msg.wParam;
}


ウィンドウサイズを変更すると、そのサイズを即座に描画します
通常、WM_SIZE は再描画処理を明示的に行う必要はありません
これは、一般的なアプリケーションは WNDCLASS の style メンバに
CS_HREDRAW と CS_VREDRAW を設定しているからです


ウィンドウの移動

ウィンドウが、ユーザーのドラッグなどによって移動した時
やはり、移動されたことを通知するメッセージを生成します

ウィンドウの位置が変更されると WM_MOVE が生成されます
LPARAM の下位ワードにウィンドウの X 座標が
上位ワードに Y 座標が、それぞれスクリーン座標で格納されています
//ただし、子ウィンドウ(後記)の場合は親ウィンドウのクライアントエリアの座標

このメッセージを処理した場合は 0 を返します
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	static int iXpos = 0, iYpos = 0;
	static TCHAR strSize[128];

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_MOVE:
		iXpos = LOWORD(lp);
		iYpos = HIWORD(lp);
		InvalidateRect(hwnd , NULL , TRUE);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd , &ps);
		wsprintf(strSize , "X = %d : Y = %d" , iXpos , iYpos);
		TextOut(hdc , 10 , 10 , strSize , lstrlen(strSize));
		EndPaint(hwnd , &ps);
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
	return msg.wParam;
}
表示されたウィンドウは、スクリーンサイズの位置を表示します
ウィンドウを移動させると、その瞬間に WM_MOVE が実行されます

表示される位置は、ウィンドウの左上のスクリーンの位置です



前のページへ戻る次のページへ