MID 프로그래밍
CLIENTCREATESTRUCT 구조체
typedef struct { HANDLE hWindowMenu; // 응용 프로그램의 메인 메뉴 중 선택한 부메뉴에 대한 핸들 값 UINT idFirstChild; // 생성할 자식 윈도우의 ID로 사용할 정수값, } CLIENTCREATESTRUCT; |
MDICREATESTRUCT 구조체
typedef struct tagMDICREATESTRUCT { LPCTSTR szTitle; // MDI 자식 창의 제목 HANDLE hOwner; // MDI 클라이언트 창을 만드는 응용 프로그램의 인스턴스에 대한 핸들 int y; // MDI 자식 창의 초기 수직 위치 (클라이언트 좌표)입니다. 이 멤버가 int cx; // MDI 자식 창의 초기 너비 (장치 단위)입니다. 이 멤버가 CW_USEDEFAULT 이면 int cy; // MDI 자식 창의 초기 높이 (장치 단위)입니다. 이 멤버가 CW_USEDEFAULT 로 설정 되면 DWORD style; // MDI 자식 창의 스타일 LPARAM lParam; // 애플리케이션 정의 값 } MDICREATESTRUCT |
DWORD style : MDI 자식 창의 스타일입니다. MDI 클라이언트 창이 MDIS_ALLCHILDSTYLES 창 스타일 로 생성 된 경우이 멤버는 창 스타일 페이지에 나열된 창 스타일의 조합이 될 수 있습니다 . 그렇지 않으면이 멤버는 다음 값 중 하나 이상이 될 수 있습니다.
값의미
WS_MINIMIZE | 처음에 최소화 된 MDI 자식 창을 만듭니다. |
WS_MAXIMIZE | 처음에 최대화 된 MDI 자식 창을 만듭니다. |
WS_HSCROLL | 가로 스크롤 막대가있는 MDI 자식 창을 만듭니다. |
WS_VSCROLL | 세로 스크롤 막대가있는 MDI 자식 창을 만듭니다. |
MID 프로그램 만들기
#include <windows.h> #include <TCHAR.H> #include "resource.h" LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK ChildWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { HWND hwnd; MSG msg; WNDCLASS WndClass; hInst = hInstance; WndClass.style = CS_HREDRAW | CS_VREDRAW; WndClass.lpfnWndProc = FrameWndProc; WndClass.cbClsExtra = 0; WndClass.cbWndExtra = 0; WndClass.hInstance = hInstance; WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); WndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); WndClass.lpszClassName = _T("Window Class Name"); RegisterClass(&WndClass);
WndClass.lpfnWndProc = ChildWndProc; WndClass.lpszMenuName = NULL; WndClass.lpszClassName = _T("Child Window Class Name"); RegisterClass(&WndClass);
hwnd = CreateWindow( _T("Window Class Name"), _T("Main Window Title"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; }
LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HWND hwndClient; CLIENTCREATESTRUCT clientcreate; MDICREATESTRUCT mdicreate; HWND hwndChild;
switch (iMsg) { case WM_CREATE: clientcreate.hWindowMenu = GetSubMenu(GetMenu(hwnd), 0); clientcreate.idFirstChild = 100; hwndClient = CreateWindow( _T("MDICLIENT"), NULL, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 0, 0, 0, hwnd, NULL, hInst, (LPSTR)&clientcreate ); ShowWindow(hwndClient, SW_SHOW); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_FILENEW: mdicreate.szClass = _T("Child Window Class Name"); mdicreate.szTitle = _T("Child Window Title Name"); mdicreate.hOwner = hInst; mdicreate.x = CW_USEDEFAULT; mdicreate.y = CW_USEDEFAULT; mdicreate.cx = CW_USEDEFAULT; mdicreate.cy = CW_USEDEFAULT; mdicreate.style = 0; mdicreate.lParam = 0; hwndChild = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0, return 0; } break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefFrameProc(hwnd, hwndClient, iMsg, wParam, lParam); }
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT iMsg,WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_CREATE: break; case WM_DESTROY: return 0; } return DefMDIChildProc(hwnd, iMsg, wParam, lParam); } |
실행 결과]
자식 윈도우 창 정렬하기
switch (LOWORD(wParam)) { case ID_FILENEW: mdicreate.szClass = _T("Child Window Class Name"); mdicreate.szTitle = _T("Child Window Title Name"); mdicreate.hOwner = hInst; mdicreate.x = CW_USEDEFAULT; mdicreate.y = CW_USEDEFAULT; mdicreate.cx = CW_USEDEFAULT; mdicreate.cy = CW_USEDEFAULT; mdicreate.style = 0; mdicreate.lParam = 0; hwndChild = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0, return 0; case ID_WINDOW_CLOSE: hwndChild = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0); if (SendMessage(hwndChild, WM_QUERYENDSESSION, 0, 0)) SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndChild, 0); return 0; case ID_TILE: SendMessage(hwndClient, WM_MDITILE, 0, 0); return 0; case ID_CASCADE: SendMessage(hwndClient, WM_MDICASCADE, 0, 0); return 0; case ID_ARRANGE: SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0); } |
실행 결과]
윈도우 분할하기
분할 윈도우도 메인 윈도우와 같은 방법으로 생성하고 CreateWindowEx()함수를 사용한다.
CreateWindowEx() 함수
HWND CreateWindowExA( DWORD dwExStyle, // 생성되는 확장 윈도우의 스타일 LPCSTR lpClassName, // 등록된 윈도우 클래스 LPCSTR lpWindowName, // 윈도우 타이틀 텍스트 DWORD dwStyle, // 기본 윈도우 스타일 int X, // 생성 윈도우 위치의 X 값 int Y, // 생성 윈도우 위치의 Y 값 int nWidth, // 생성 윈도우의 너비 int nHeight, // 생성 윈도우의 높이 HWND hWndParent, // 부모 윈도우 핸들 HMENU hMenu, // 사용될 메뉴의 핸들 HINSTANCE hInstance, // 응용 프로그램 인스턴스 LPVOID lpParam // 창에 전달할 값을 가리키는 포인터 ); |
HWNDChildHwnd[2]; LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HWND hwndClient; CLIENTCREATESTRUCT clientcreate; MDICREATESTRUCT mdicreate; HWND hwndChild;
RECT rectView;
switch (iMsg) { case WM_CREATE: GetClientRect(hwnd, &rectView); ChildHwnd[0] = CreateWindowEx( WS_EX_CLIENTEDGE, // 생성되는 확장 윈도우 스타일 _T("Child Window Class Name"), // 등록된 윈도우 클래스 NULL, // 윈도우 타이틀 WS_CHILD | WS_VISIBLE, // 기본 윈도우 스타일 0, // 윈도우 X좌표 0, // 원도우 Y좌표 rectView.right, // 윈도우 너비 rectView.bottom / 2 - 1, // 윈도우 높이 hwnd, // 부모 윈도우 핸들 NULL, // 사용될 메뉴의 핸들 hInst, // 응용 프로그램 인스턴스 NULL // 창에 전달될 정보 );
ChildHwnd[1] = CreateWindowEx( WS_EX_CLIENTEDGE, _T("Child Window Class Name"), NULL, WS_CHILD | WS_VISIBLE, 0, rectView.bottom / 2 + 1, rectView.right, rectView.bottom / 2 - 1, hwnd, NULL, hInst, NULL ); return 0; case WM_COMMAND: |
실행 결과]
메인 윈도우의 크기 조정하기
MoveWindow() 함수
BOOL MoveWindow( HWND hWnd, // 윈도우 핸들 int X, // 윈도우 새 위치의 x 좌표 int Y, // 윈도우 새 위치의 y 좌표 int nWidth, // 윈도우의 새 너비 int nHeight, // 윈도우의 새 높이 BOOL bRepaint // 재조정 후 재출력 여부 ); |
LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { .... RECT rectView; static BOOL split;
switch (iMsg) { case WM_CREATE: split = FALSE; return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_SPLIT_2X1: if (split == TRUE) break; split = TRUE; GetClientRect(hwnd, &rectView); ChildHwnd[0] = CreateWindowEx( WS_EX_CLIENTEDGE, _T("Child Window Class Name"), NULL, WS_CHILD | WS_VISIBLE, 0, 0, rectView.right, rectView.bottom / 2 - 1, hwnd, NULL, hInst, NULL );
ChildHwnd[1] = CreateWindowEx( WS_EX_CLIENTEDGE, _T("Child Window Class Name"), NULL, WS_CHILD | WS_VISIBLE, 0, rectView.bottom / 2 + 1, rectView.right, rectView.bottom / 2 - 1, hwnd, NULL, hInst, NULL ); return 0; |
실행 결과]
자식 윈도우의 크기 조정하기
LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { .... static BOOL split; static HCURSOR hCursor; static int boundary = -1;
switch (iMsg) { case WM_CREATE: split = FALSE; return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_SPLIT_2X1: .... return 0; case WM_MOUSEMOVE: if (HIWORD(lParam) >= boundary - 2 && HIWORD(lParam) <= boundary + 2) if (wParam == MK_LBUTTON && split == TRUE) { GetClientRect(hwnd, &rectView); if (rectView.top + 5 < HIWORD(lParam) && HIWORD(lParam) < rectView.bottom - 5) MoveWindow(ChildHwnd[0], 0, 0, rectView.right, boundary - 1, TRUE); MoveWindow(ChildHwnd[1], 0, boundary + 1, rectView.right, rectView.bottom - boundary + 1, TRUE); } return 0; case WM_LBUTTONDOWN: if (split == TRUE) { SetCursor(hCursor); SetCapture(hwnd); // 마우스를 윈도우 내에 캡처하기 } return 0; case WM_LBUTTONUP: if (split == TRUE) return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefFrameProc(hwnd, hwndClient, iMsg, wParam, lParam); }
|
실행 결과]
자식 윈도우 메시지 처리하기(타이머을 이용하여 원형 출력하기)
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT iMsg,WPARAM wParam, LPARAM lParam) { HDC hdc; static int x[2] = { 20, 20 }, y[2] = { 20, 20 }, flag[2]; int select;
switch (iMsg) { case WM_CREATE: break; case WM_TIMER: x[wParam] = x[wParam] + 20; hdc = GetDC(hwnd); Ellipse(hdc, x[wParam] - 20, y[wParam] - 20, x[wParam] + 20, y[wParam] + 20); ReleaseDC(hwnd, hdc); break; case WM_LBUTTONDOWN: if (hwnd == ChildHwnd[0]) select = 0; else select = 1; flag[select] = 1 - flag[select]; if (flag[select]) SetTimer(hwnd, select, 100, NULL); else KillTimer(hwnd, select); break; case WM_DESTROY: return 0; } return DefMDIChildProc(hwnd, iMsg, wParam, lParam); } |
실행 결과]