一つのウィンドウがあたかも真ん中の境界線で
分割しているかのように見えます。
境界線をドラッグすると左右の領域の大きさを変えることができます。
実は右半分はエジットコントロールなのです。左半分は
親のクライアント領域です。両方ともコントロールなり、
子供ウィンドうなりを貼ればよかったのですがプログラムの
簡略化のためにこのようにしてみました。真ん中の境界線は
エジットコントロールの枠なのです。また、左右と下の
境界線は親ウィンドウのものです。
(エジットコントロールの上・右・下の境界線は親ウィンドウから
はみ出しているため見えない)
何か、インチキ臭いプログラムですが中身を見てみましょう。
今回は、気分転換のためにちょっといつもと雰囲気を変えてみました。// split01.cpp #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); char szClassNme[] = "split01"; HINSTANCE hInst; int w1x, w1y, w2x, w2h; void GetWinRect(HWND, int *, int *); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow) { HWND hWnd; MSG lpMsg; WNDCLASSEX myProg; hInst = hInstance; myProg.cbSize = sizeof(WNDCLASSEX); myProg.style = CS_HREDRAW | CS_VREDRAW; myProg.lpfnWndProc = WndProc; myProg.cbClsExtra = 0; myProg.cbWndExtra = 0; myProg.hInstance = hInstance; myProg.hIcon = LoadIcon(NULL, IDI_APPLICATION); myProg.hCursor = LoadCursor(NULL, IDC_ARROW); myProg.hbrBackground = GetStockObject(WHITE_BRUSH); myProg.lpszMenuName = NULL; myProg.lpszClassName = szClassNme; myProg.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassEx(&myProg)) return FALSE; hWnd = CreateWindow(szClassNme, "猫でもわかるプログラミング", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage(&lpMsg, NULL, 0, 0)) { TranslateMessage(&lpMsg); DispatchMessage(&lpMsg); } return (lpMsg.wParam); }
親が作られたらすぐに、エジットコントロールを作ります。 このとき、ウィンドウスタイルにWS_THICKFRAMEを加えないと サイズ変更の可能なウィンドウ枠が作られないので注意してください。 また、左上の座標を(300, 0)にせず(300, -3)にしている点に 注意してください。(わずかに上方向に枠の太さ分ずらしています) 枠の太さはGetSystemMetrics関数で求めることができますが 手抜きで適当な値にしておきました。LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { int id; static HWND hEdit; static int wx, wy, wsx, wsy;//クライアント領域の幅、高さ HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_CREATE: GetWinRect(hWnd, &wx, &wy); hEdit = CreateWindow( "EDIT", "ウィンドウ2です", WS_CHILD | WS_THICKFRAME | WS_VISIBLE | ES_MULTILINE | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 300, -3, wx-300+3, wy+6, hWnd, (HMENU)100, hInst, NULL); break; case WM_SIZE: GetWinRect(hWnd, &wx, &wy); GetWinRect(hEdit, &wsx, &wsy); if (wsx > wx) wsx = wx; if (wsx < 3) wsx = 3; MoveWindow(hEdit, wx-wsx, -3, wsx+3, wy+6, TRUE); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 0, 0, "ウィンドウ1です", 16); EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return 0; }
親ウィンドウのサイズが変化したら(WM_SIZE)エジットコントロールの 大きさも変更しています。この時まず親とエジットコントロールの 大きさを調べておきます。そして、エジットコントロールの サイズを変更しています。この場合サイズ変更のウィンドウは 1つだけなので簡単のためにMoveWindow関数を利用しています。 2つ以上のウィンドウを変更するときは違う関数があります。 必要が生じたら解説します。
ウィンドウのクライアント領域のサイズを調べる関数を 自作してみました。(あまり意味はありませんが・・)void GetWinRect(HWND hWnd, int *x, int *y) { RECT rc; GetClientRect(hWnd, &rc); *x = rc.right - rc.left; *y = rc.bottom - rc.top; return; }
今回のプログラムは実際に自分でいろいろ動かしてみると 不備な点がたくさんあります。改良してみてください。 そして、左半分にも子供ウィンドウを貼り付けたものにも 挑戦してみてください。この時どちらかの子供ウィンドウを 枠なしにしておくとよいです。
Update Mar/25/1998 By Y.Kumei