1. Windows 객체 윈도우
윈도우는 Windows가 관리하는 객체 중 하나이며, 사용자가 보고 있는 창은 윈도우 객체가 출력된 형태이다.
윈도우의 속성은 구조체로 관리되며 CreateWindow API의 인자와 대응된다.
HWND CreateWindow( // 반환값: 생성된 윈도우 핸들 LPCTSTR lpClassName, // 윈도우 클래스명 LPCTSTR lpWindowName, // 윈도우 이름 DWORD dwStyle, // 윈도우 스타일 int x, // 좌측상단의 x좌표 int y, // 좌측상단의 y좌표 int nWidth, // 수평 방향 크기 int nHeight, // 수직 방향 크기 HWND hWndParent, // 부모 윈도우/소유 윈도우 핸들 HMENU hMenu, // 메뉴 핸들/컨트롤 ID HINSTANCE hInstance, // 인스턴스 핸들 LPVOID lpParam // WM_CREATE 메시지에 넘길 전달 인자 ); |
윈도우의 크기는 픽셀 좌표계로 4~7번째 인자에 지정되며, 윈도우의 위치와 크기를 고정하고 싶을 경우가 아니라면 신경쓰지 않아도 된다.
2. 윈도우 스타일
윈도우 스타일은 윈도우의 외관이나 종류를 정하기 위한 32비트 정수 값이다. 제목표시줄의 유무, 크기 변경 가능 여부 등을 결정할 수 있다.
비트 필드로 정의되어 있으므로, WS_ 상수를 논리 OR 명령어로 조합해서 지정할 수 있다.
스타일 |
해당 윈도우의 구성요소 |
WS_CAPTION |
제목표시줄 |
WS_BORDER |
가는(크기 변경 불가능) 윈도우 프레임 |
WS_DLGFRAME |
대화상자에서 사용하는 윈도우 프레임 |
WS_THCKFRAME |
굵은(크기 변경 가능) 윈도우 프레임 |
WS_HSCROLL |
수평 스크롤바 |
WS_VSCROLL |
수직 스크롤바 |
WS_SYSMENU |
시스템 메뉴, WS_CAPTION과 함께 지정 |
WS_MAXIMIZEBOX |
최대화 버튼,WS_SYSMENU와 함께 지정 |
WS_MINIMIZEBOX |
최소화 버튼, WS_SYSMENU와 함께 지정 |
3. 윈도우 종류
(1) 오버랩 윈도우
애플리케이션의 메인 윈도우로 사용하는 형식
제목 표시줄과 윈도우 프레임이 필수 이며, 최대화/최소화 버튼과 메뉴 표시줄을 가지고 있음
(2) 팝업 윈도우
메인 윈도우 보다 임시 윈도우로 사용되는 경우가 많음
제목 표시줄과 윈도우 프레임이 필수가 아니라는 것을 제외하면 오버랩 윈도우와 동일
(3) 자식 윈도우
메인윈도우가 될 수 없다.
부모 윈도우가 필요하다.
스타일 |
해당 윈도우의 종류 |
WS_OVERLAPPED |
오버랩 윈도우, 제목표시줄과 프레임이 있다 |
WS_POPUP |
팝업 윈도우 |
WS_CHILD |
자식 윈도우, 메뉴 표시줄을 사용하지 못한다 |
WS_OVERLAPPEDWINDOW |
WS_OVERLAPPED 에 WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MAXIMIZEBOX, WS_MINIMIZEBOX를 조합한 윈도우 |
WS_POPUPWINDOW |
WS_POPUP에 WS_BORDER와 WS_SYSMENU를 조합한 윈도우로, WS_CAPTION을 조합했을 경우에만 메뉴가 나옴 |
WS_CHILDWINDOW |
WS_CHILD와 같음 |
4. 부모 윈도우 자식윈도우
CreateWindow API에 hWndParent의 부모 윈도우 핸들을 지정하면 자식 윈도우가 생성
부모 윈도우의 클라이언트 영역의 바깥쪽에 출력하거나 이동 불가능
자식 윈도우는 부모 윈도우의 클라이언트 영역을 여러 개로 분할 하여 다른 기능으로 사용가능
5. 소유/피소유 의존관계
부모/자식 관계와 공통점 : 닫거나 최소화 하면 자동으로 닫히거나 최소화
부모/자식 관계와 차이점 : 표시 영역이 소유 측 윈도우의 내부로 한정(소유 윈도우를 캔버스로 비유할 수 있음)
소유관계 설정
CreateWindow API에 윈도우 스타일에 WS_CHILD를 설정하지 않으면서 hWndParent에 소유 윈도우 핸들 지정
자식 윈도우면서 피소유 윈도우가 될 수 없음
소유 윈도우 생성 후 소유관계 수정 불가(부모/자식 관계에서는 부모 윈도우 변경 가능)
#include<windows.h>
#define MYWNDCLSNAME L"MyWindowClass"
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg){ case WM_DESTROY : PostQuitMessage(0); return 0; }
return DefWindowProc(hWnd, uMsg, wParam, lParam); }
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wndcls; HWND hWnd, hWndOwned, hWndChild; MSG msg;
// 윈도우 클래스 등록 ZeroMemory(&wndcls, sizeof(wndcls)); wndcls.lpfnWndProc = WndProc; wndcls.hInstance = hInst; wndcls.hIcon = LoadIcon(0, IDI_APPLICATION); wndcls.hCursor = LoadCursor(0, IDC_ARROW); wndcls.hbrBackground = (HBRUSH)COLOR_BACKGROUND; wndcls.lpszClassName = MYWNDCLSNAME; if (RegisterClass(&wndcls) == 0) return -1;
// 메인 윈도우 생성 hWnd = CreateWindow(MYWNDCLSNAME, L"Main Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, 0, 0, hInst, NULL); if (hWnd == 0) return -2;
// 자식 윈도우 생성 hWndChild = CreateWindow(MYWNDCLSNAME, L"Child Window", WS_CHILDWINDOW | WS_CAPTION | WS_VISIBLE, 0, 0, 200, 100, hWnd, 0, hInst, NULL); if (hWndChild == 0) return -2;
//피소유 윈도우 생성 hWndOwned = CreateWindow(MYWNDCLSNAME, L"Ownd Window", WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 0, 0, 200, 100, hWnd, 0, hInst, NULL); if (hWndOwned == 0) return -2;
ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
// 메시지 루프 while (GetMessage(&msg, 0, 0, 0)){ DispatchMessage(&msg); }
return msg.wParam; } |
위 소스를 실행 하였을 때, 다음과 같이 Child Window의 경우 Main Window안에서 이동할 수 있으며, Owned Window 같은 경우, Main Window 밖으로 이동이 되는 것을 볼 수 있다.
1. 컨트롤 ID와 자식 윈도우
hMenu 인자는 자식 윈도우의 상태에 따라 의미가 달라지며 컨트롤 ID 역할을 수행한다.
hMenu인자는 자식 윈도우가 아닐 경우에는 원래 윈도우 클래스에서 지정한 것과 다른 메뉴를 설정할 때 사용되며, 윈도우 클래스에서 지정한 값과 같을 때는 0을 가진다.
컨트롤 아이디
자식 윈도우를 식별하는 32비트 정수 값으로, 대화 상자에 배치된 컨트롤을 식별할 때 쓰일 수 있다.
CreateWindow API의 결과로 받은 윈도우 핸들은 프로그래머가 무슨 값이 될 지 예상하기 힘들지만 컨트롤 아이디는 프로그래머가 원하는 값을 할당할 수 있다.
GetDlgItem API를 사용하여 컨트롤 ID에 대응하는 핸들을 얻어올 수 있어, 윈도우 핸들을 보존하지 않아도 된다.
프로그래머는 컨트롤 ID의 유일성이 지켜지도록 컨트롤 ID를 부여하여야 한다.
2. SetWindowsPos
SwhoWindow API
윈도우의 출력 상태 설정을 하며, 윈도우 생성 직후 외에 실행중에도 출력상태를 변경하기 위해 호출 할 수 있다.
BOOL Showwindow( // 반환값 : 성공이면 TRUE HWND hWnd, // 대상 윈도우 핸들 int nCmdShow // 설정할 출력 상태 ); |
상수 |
의미 |
SW_HIDE |
윈도우를 숨기고, 다른 윈도우를 활성 상태로 전환 |
SW_MAXIMIZE |
윈도우를 최대화 |
SW_MINIMIZE |
윈도우를 최소화하고 다른 윈도우를 활성 |
SW_RESOTRE |
최대/최소화를 원래 상태로 복원 |
SW_SHOW |
윈도우를 나타내고 활성 상태로 만듬 |
SW_SHOWNA |
윈도우를 나타내고 활성 상태로 하지 않음 |
SW_SHOWDEFAULT |
윈도우를 처음 프로그램 시작할 때 지정된 값으로 변경 |
SW_SHOWNORMAL |
윈도우를 나타내고 활성 상태로 전환 최대화/최소화 경우에 복원 |
SW_SHOWACTIVATE |
윈도우를 활성 상태로 하지 않는 것을 하고 SW_SHOWNORAML과 같음 |
윈도우 Z의 순서
ShowWindow는 윈도우를 보여주는 방법에서 여러 윈도우가 있을 때 깊이 방향 위치의 요소를 포함한다.
(여러 윈도우가 겹쳐 있을 때 어느 윈도우 내용이 표시되는지에 대함)
Windows에서 각 윈도우를 생성할 때나 마우스로 윈도우를 선택할 때 윈도우 z 순서를 설정
- 마우스로 윈도우 클릭했을 때
활성 윈도우는 윈도우z의 순서가 맨 위인 것이다.
Z순서의 명시적 설정 – SetWindowPosAPI 사용
윈도우의 크기, 위치, 크기, Z순서를 한꺼번에 설정할 수 있으며, uflags에 플래그를 설정하는 방법으로 위치나 z 순서만 설정할 수도 있다.
BOOL SetWindowPos ( // 반환값: 성공이면 TRUE HWND hWnd, // 대상 윈도우 핸들 HWND hWndInsertAfter, // z순서상 바로 위에 있는 윈도우 핸들 int x, // 윈도우 좌측상단의 x좌표 int y, // 윈도우 좌측상단의 y좌표 int cx, // 윈도우 폭 int cy, // 윈도우 높이 UINT uFlags // 설정할 상태의 종류 ); |
플래그 |
의미 |
SWP_HIDEWINDOW |
윈도우를 숨긴다 |
SWP_NOACTIVATE |
윈도우를 활성화하지 않는다 |
SWP_NOMOVE |
윈도우를 이동하지 않는다 |
SWP_NOOWNERZORDER |
소유 윈도우의 Z 순서를 변경하지 않는다 |
SWP_NOREDRAW |
윈도우를 다시 그리지 않는다 |
SWP_NOSIZE |
윈도우의 크기를 변경하지 않는다 |
SWP_NOZORDER |
윈도우 Z의 순서를 변경하지 않는다 |
SWP_SHOWNDOW |
윈도우를 나타낸다 |
'Operating Systems > Windows' 카테고리의 다른 글
윈도우 어플리케이션의 구조 (1) | 2015.04.21 |
---|---|
API로 배우는 커널 - 1.운영체제 구조 (0) | 2015.04.12 |