エディットメッセージ
プログラムからテキストを編集
今回は、プログラムから明示的にエディットコントロールを操作する方法を解説します
ボタン同様に、ユーザーの操作をプログラムでエミュレートできるのです
実際にエディットコントロールに送ることができるメッセージは、かなりの数があります
今回は、そのうち主要なメッセージを紹介することにしましょう
メッセージの伝達は、ボタン同様に 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ミリ秒ごとにエディットコントロールを監視し
エディットコントロールの選択状況と行数をラベルに表示しています