カスタムコントロール


独自のコントロールを使う

これまで、ダイアログにはすでに定義されているコントロールを用いました
これでも、十分実用可能であるのですが
これ以外の、個性的なコントロールを用いたい場合は独自に実装します

カスタムコントロールの概念はサブクラス化を理解していれば難しくはありません
カスタムコントロールはリソーススクリプトで CONTROL コントロールを指定します

CONTROL text, id, class, style, x, y, width, height [, extended-style]

text はコントロールのテキストです。プログラムからは GetWindowText() で取得できます
id はコントロールの ID です
class は、コントロールのウィンドウクラスの名前を指定します

style には、CreateWindow() 関数のスタイルで指定する定数を指定できます
x , y はコントロールの始点座標、width と height は幅と高さです
extended-style は、拡張スタイルを指定することができます

class で指定するウィンドウクラスは、プログラム側で用意する必要があります
このウィンドウクラスのウィンドウプロシージャで、コントロールの描画動作をプログラムします
//リソーススクリプト
KITTY DIALOG 10 , 10 , 100 , 50
FONT 12 , "MS ゴシック"
CAPTION "Magical nyan nyan TARUTO" {
	CONTROL "Kitty on your lap" , 1 , "Control" ,
		WS_GROUP | WS_TABSTOP , 10 , 35 , 80 , 10
}
#include <windows.h>

BOOL CALLBACK DialogProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	switch (msg) {
	case WM_CLOSE:
		EndDialog(hwnd , IDOK);
		return TRUE;
	}
	return FALSE;
}

LRESULT CALLBACK CtrlProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	PSTR strText;
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;
	int iTextLength;

	switch (msg) {
	case WM_PAINT:
		iTextLength = GetWindowTextLength(hwnd) + 2;
		strText = (PSTR)malloc(iTextLength);

		GetWindowText(hwnd , strText , iTextLength);
		GetClientRect(hwnd , &rect);

		hdc = BeginPaint(hwnd , &ps);
		DrawText(hdc , strText , -1 , &rect , DT_CENTER);
		EndPaint(hwnd , &ps);

		free(strText);
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_LBUTTONUP:
		DialogBox(
			(HINSTANCE)GetWindowLong(hwnd , GWL_HINSTANCE) ,
			TEXT("KITTY") , hwnd , DialogProc
		);
		return 0;
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	HACCEL haccel;
	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;

	winc.lpfnWndProc 	= CtrlProc;
	winc.hIcon 		= NULL;
	winc.lpszClassName	= TEXT("Control");

	RegisterClass(&winc);

	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)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


このプログラムは、基本的なカスタムコントロールの実装方法を示すものです
実際には、カスタムコントロールは親ウィンドウに WM_COMMAND などの
必要なメッセージを送信するべきです

親ウィンドウにメッセージを送信する場合 GetParent() 関数を使います
この関数は、指定ウィンドウの親ウィンドウのハンドルを返します

HWND GetParent(HWND hWnd);

hWnd には子ウィンドウのハンドルを指定します
戻り値は、親ウィンドウのハンドルです。無い場合は NULL になります

もちろん、これ以外にも多くの問題が残っています
フォーカスを得た時の強調表示や、クリック時の描画動作などの対応です
しかし、これらに関してはある程度これまでの知識で対応できるはずです

また、有効/無効状態の変更に対応するために
WM_ENABLE に対する処理も考える必要があります


GetParent()

HWND GetParent(HWND hWnd);

親ウィンドウのハンドルを取得します

hWnd - 子ウィンドウのハンドルを指定します
戻り値 - 親ウィンドウのハンドル。無い場合は NULL



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