エディット


テキストの入力

一般に、GUI システムで文字の出力に printf() を使わないように
文字の入力を scanf() のように標準入力から行うことはできません
GUI システムでは、入力専用のコントロールなどを用いてユーザーに入力を促します

CreateWindow() の定義済みウィンドウクラスの中に
入力動作を高度なレベルで補ってくれるコントロールが存在します
それが エディットコントロール です

エディットコントロール を用いれば、比較的簡単にメモ帳(notepad.exe)を実現できます
これを子ウィンドウとして配置するには、CreateWindow() のウィンドウスタイルの指定に
EDIT を指定することで、エディットコントロールを作成できます

エディットコントロールは、デフォルトの状態で1行入力コントロールです
メッセージループで TranslateMessage(); によって仮想キーコードを処理すれば
入力や、クリップボードとのやりとりが可能となっています

デフォルトの状態では、エディットコントロールに枠はありません
枠を表示するには WS_BORDER などを選択する必要があります
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		CreateWindow(
			TEXT("EDIT") , TEXT("Kitty on your lap") , 
			WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT ,
			0 , 0 , 200 , 30 , hwnd , (HMENU)1 ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		return 0;
	}
	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)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


メモ帳愛好家(?)にとっては、お馴染みのポップアップだと思います
このように、エディットコントロールは選択範囲、各種の操作を
デフォルトの状態でサポートしています(ポップアップは右クリックで表示)

もちろん、TranslateMessage() を処理しているのでキーボード入力も受けつけます
エディットコントロールに文字を表示するには SetWindowText() 関数を
入力された文字を取得するには GetWindowText() 関数を用います

複数行のエディットコントロールの生成には、スタイルに ES_MULTILINE を指定します
これで、Enter キーで改行して複数行のテキストの編集が行えます

通常、テキスト入力が可変個数の文字を扱うならば
スクロールバーによってスクロールさせたほうが、断然便利です
実は、エディットクラスではこれらの動作を簡単に実現させることができます

スクロールバーは、WS_HSCROLL と WS_VSCROLL をスタイルに指定することで
水平、または垂直バーをエディットコントロールに付加することができます

改行や、文字の追加で自動的にスクロールするようにしたい場合
水平バーは ES_AUTOHSCROLL
垂直バーは ES_AUTOVSCROLL を指定します
これで、文字が左右に表示しきれない時や最下行で改行した時にスクロールします

また、テキストを左揃えで表示するには ES_LEFT
中央揃えは ES_CENTER 右揃えは ES_RIGHT を指定します
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		CreateWindow(
			TEXT("EDIT") , NULL , 
			WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
			ES_AUTOHSCROLL | ES_AUTOVSCROLL |
			ES_LEFT | ES_MULTILINE ,
			0 , 0 , 400 , 200 , hwnd , (HMENU)1 ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		return 0;
	}
	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)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


このように、自由にテキストを編集することができます
これに、簡単な検索機能と保存と読みこみ機能をつければ、簡易テキストエディタ作れます

ただし、定義済みウィンドウクラスであるのエディットコントロールは
最大で 32K バイトまでしか対応していないという制限がある
32K バイトを超えるテキストを扱う場合、何らかの別の対応が必要になります


エディットの通知コード

エディットコントロールは、親ウィンドウに WM_COMMAND を送ります
WPARAM の下位ワードに子ウィンドウのID、上位ワードに通知コード
LPARAM に子ウィンドウのハンドルが格納されています
これは、ボタンコントロールの時と同じですね

エディットコントロールの通知コードは次のようなものがあり
これを調べることで、エディットコントロールに何が発生したか認識できます

通知コード解説
EN_CHANGE テキストが変更された可能性のある動作がされた
EN_UPDATE通知メッセージとは異なり
この通知メッセージはシステムがスクリーンを更新したあと送られる
EN_ERRSPACE 十分な記憶を割り当てることができないとき送られる
EN_HSCROLL ユーザーが水平スクロール・バーをクリックするとき
スクリーンが更新される前に送られる
EN_KILLFOCUS キーボードフォーカスを失った時に送られる
EN_MAXTEXT ES_AUTOHSCROLL または ES_AUTOVSCROLL スタイル指定がなく
テキストの挿入がスペースを上回った時に送られる
EN_SETFOCUS キーボードフォーカスを得た時に送られる
EN_UPDATE テキストの内容が変更された後
テキストを表示しようとしている時に送られる
EN_VSCROLL ユーザーが垂直スクロール・バーをクリックするとき
スクリーンが更新される前に送られる
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	static HWND edit , copy;
	PSTR strText;

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		edit = CreateWindow(
			TEXT("EDIT") , NULL , 
			WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
			ES_AUTOHSCROLL | ES_AUTOVSCROLL |
			ES_LEFT | ES_MULTILINE ,
			0 , 0 , 200 , 200 , hwnd , (HMENU)1 ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		copy = CreateWindow(
			TEXT("EDIT") , NULL , 
			WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
			ES_AUTOHSCROLL | ES_AUTOVSCROLL |
			ES_LEFT | ES_MULTILINE ,
			200 , 0 , 200 , 200 , hwnd , (HMENU)2 ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		return 0;
	case WM_COMMAND:
		if (LOWORD(wp) == 1 && HIWORD(wp) == EN_UPDATE) {
			strText = malloc(32768);
			GetWindowText(edit , strText , 32768);
			SetWindowText(copy , strText);
			free(strText);
		}
		return 0;
	}
	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)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


左のエディットボックスに文字列を挿入すると
即座に右のエディットボックスに内容がコピーされるプログラムです

左のエディットコントロールに、何らかの文字を挿入すると
親ウィンドウが WM_COMMAND を受けとって、右のエディットコントロールに
左のエディットコントロールが持つウィンドウテキストを渡します



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