カスタムコントロール
独自のコントロールを使う
これまで、ダイアログにはすでに定義されているコントロールを用いました
これでも、十分実用可能であるのですが
これ以外の、個性的なコントロールを用いたい場合は独自に実装します
カスタムコントロールの概念はサブクラス化を理解していれば難しくはありません
カスタムコントロールはリソーススクリプトで 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