エディットメッセージ


プログラムからテキストを編集

今回は、プログラムから明示的にエディットコントロールを操作する方法を解説します
ボタン同様に、ユーザーの操作をプログラムでエミュレートできるのです

実際にエディットコントロールに送ることができるメッセージは、かなりの数があります
今回は、そのうち主要なメッセージを紹介することにしましょう
メッセージの伝達は、ボタン同様に SendMessage() 関数を用いて行います

現在、エディットコントロールで選択されている文字で
クリップボードに文字を転送し、文字を削除するには WM_CUT を使います
これは、エディットコントロールのポップアップメニュー「切り取り」に等しい動作です
//クリップボードについての解説は後記する

クリップボードに転送せずに、ただ単純に削除するには WM_CLEAR
削除せずに、単純にクリップボードに転送するには WM_COPY を送ります
これは、ポップアップの「削除」と「コピー」に等しい動作です

これらのメッセージにパラメータはないので、 0 を指定してください
戻り値もないので SendMessage() が返す値に関心はありません

ユーザーが行った一つ前の動作のテキストに戻すには EM_UNDO を送ります
このメッセージは「元に戻す」の動作と同じです
このメッセージにパラメータはありません

1行エディットコントロールならば、戻り値は常に真です
マルチライン(複数行)のエディットコントロールの場合、成功すれば TRUE
失敗すれば FALSE が返ります
#include <windows.h>

enum	{ BID_CUT = 2 , BID_DEL , BID_COPY , BID_UNDO };

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

	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
		);
		CreateWindow(
			TEXT("BUTTON") , TEXT("切り取り") , 
			WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 
			200 , 0 , 100 , 50 , hwnd , (HMENU)BID_CUT ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		CreateWindow(
			TEXT("BUTTON") , TEXT("削除") , 
			WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 
			200 , 50 , 100 , 50 , hwnd , (HMENU)BID_DEL ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		CreateWindow(
			TEXT("BUTTON") , TEXT("コピー") , 
			WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 
			200 , 100 , 100 , 50 , hwnd , (HMENU)BID_COPY ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		CreateWindow(
			TEXT("BUTTON") , TEXT("元に戻す") , 
			WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 
			200 , 150 , 100 , 50 , hwnd , (HMENU)BID_UNDO ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wp)) {
		case BID_CUT:
			SendMessage(edit , WM_CUT , 0 , 0);
			break;
		case BID_DEL:
			SendMessage(edit , WM_CLEAR , 0 , 0);
			break;
		case BID_COPY:
			SendMessage(edit , WM_COPY , 0 , 0);
			break;
		case BID_UNDO:
			SendMessage(edit , EM_UNDO , 0 , 0);
			break;
		}
		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;
}


ボタンを押すと、ボタンIDを識別して各種のメッセージが
エディットコントロールに送られ、テキストが編集されます

因みに WM_PASTE メッセージを送れば
キャレットの位置にクリップボードの内容を転送することもできます
パラメータは両方とも 0、戻り値はありません

エディットコントロールの情報を得る場合もメッセージを使う
EM_GETSEL を送れば、現在選択されているテキストの位置を知ることができる
これは、WPARAM に開始位置を格納するための32ビット整数型変数へのポインタを
LPARAM には、終了位置を格納するための32ビット整数型変数へのポインタを指定します

ただし、このメッセージは SendMessage() 関数の戻り値からも値を取得できます
下位ワードに選択範囲の開始位置、上位ワードに終了位置が格納されています
この方法で値を取得する時、変数で受け取る必要がない場合
WPARAM と LPARAM のパラメータには NULL を指定することができます

因みに、逆に EM_SETSEL メッセージを送ることで
選択範囲をプログラム側から指定することも可能です
この場合、WPARAM に開始位置、LPARAM に終了位置を指定します
戻り値はありません

複数行入力エディットコントロールの場合、EM_GETLINECOUNT を使って
エディットコントロールの行数を取得することができます
パラメータには 0 を指定します。戻り値はエディットコントロールの行数です
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	static HWND edit , label;
	TCHAR strText[1024];

	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
		);
		label = CreateWindow(
			TEXT("STATIC") , NULL , 
			WS_CHILD | WS_VISIBLE ,
			200 , 0 , 200 , 200 , hwnd , (HMENU)2 ,
			((LPCREATESTRUCT)(lp))->hInstance , NULL
		);
		SetTimer(hwnd , 1 , 100 , NULL);
		return 0;
	case WM_TIMER:
		wsprintf(strText , 
			TEXT("先頭 = %d\n末尾 = %d\n行数 = %d") ,
			LOWORD(SendMessage(edit , EM_GETSEL , NULL , NULL)) , 
			HIWORD(SendMessage(edit , EM_GETSEL , NULL , NULL)) ,
			SendMessage(edit , EM_GETLINECOUNT , 0 , 0)
		);
		SetWindowText(label , 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;
}


100ミリ秒ごとにエディットコントロールを監視し
エディットコントロールの選択状況と行数をラベルに表示しています



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