끝나지 않는 프로그래밍 일기

[API 탐방]


윈도우를 생성하고 표시하자!

CreateWindow, ShowWindow




자 먼저, CreateWindow의 함수 원형을 살펴보도록 합시다.

HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID lpParam);

위 원형을 보면, 첫번째 인수에는 클래스 이름이 옵니다. 전에 RegisterClass 또는 RegisterClassEx 함수로 생성된 ATOM 클래스의 포인터, 혹은 문자열이 이곳에 위치합니다. 두번째 인자로는 윈도우의 타이틀바에 나타나는 제목입니다. 세번째 인자로는 윈도우의 스타일이 들어갑니다. 아래는 dwStyle에 들어갈 수 있는 값들입니다.


스타일

설명 

WS_OVERLAPPED

디폴트 윈도우. 타이틀 바와 크기 조절이 안되는 경계선을 가진다. 아무런 스타일도 주지 않으면 이 스타일이 적용된다.

WS_POPUP

팝업 윈도우를 만든다. WS_CHILD와 함께 쓸 수 없다.

WS_CHILD

차일드 윈도우를 만든다. WS_POPUP과 함께 쓸 수 없다.

WS_MINIMIZE

최초 최소화된 상태로 윈도우를 만든다.

WS_VISIBLE

윈도우를 만들자 마자 화면에 출력한다.

WS_DISABLED

사용금지된 상태, 즉 입력을 받아들일 수 없는 상태로 만든다.

WS_CLIPSIBLINGS

차일드끼리 상호 겹친 영역은 그리기 영역에서 제외된다.

WS_CLIPCHILDREN

차일드가 위치한 영역은 그리기 영역에서 제외된다.

WS_MAXIMIZE

최초 최대화된 상태로 윈도우를 만든다.

WS_CAPTION

타이틀 바를 가진 윈도우를 만들며 WS_BORDER 스타일을 포함한다.

WS_BORDER

단선으로 된 경계선을 만들며 크기 조정은 할 수 없다.

WS_DLGFRAME

두꺼운 경계선을 가지며 타이틀 바를 가질 수 없다.

WS_VSCROLL

수직 스크롤 바를 가진 윈도우를 만든다.

WS_HSCROLL

수평 스크롤 바를 가진 윈도우를 만든다.

WS_SYSMENU

시스템 메뉴를 가진 윈도우를 만든다.

WS_THICKFRAME

크기 조정이 가능한 두꺼운 경계선을 가진다.

WS_GROUP

라디오 버튼 등 그룹을 이루는 컨트롤의 그룹 지정에 사용된다.

WS_TABSTOP

Tab키로 포커스를 이동할 수 있도록 한다.

WS_MINIMIZEBOX

최소화 버튼을 만든다.

WS_MAXIMIZEBOX

최대화 버튼을 만든다.

WS_OVERLAPPEDWINDOW

가장 일반적인 윈도우 스타일. WS_OVERLAPPED |WS_CAPTION |WS_SYSMENU |WS_THICKFRAME |WS_MINIMIZEBOX |WS_MAXIMIZEBOX 스타일들이 조합된 스타일이다.

WS_POPUPWINDOW

일반적인 팝업 윈도우. WS_POPUP |WS_BORDER |WS_SYSMENU

WS_CHILDWINDOW

WS_CHILD와 같다.

<출처: winapi>


이어서 네번째와 다섯번째 인수를 보시면 윈도우의 위치를 나타냅니다. 여섯번째와 일곱번째 인수를 보시면 윈도우의 크기를 나타냅니다. 여덟번째 인수는 부모 윈도우가 존재할경우 이곳에 부모 윈도우의 핸들을 지정합니다. 아홉번째 인수로는 윈도우에서 사용할 메뉴의 핸들을 지정합니다. 열번째 인수에서는 윈도우와 연결될 인스턴스 핸들입니다. 열한번째 인수에는 lParam에 CREATESTRUCT 구조체를 담아 WM_CREATE 메시지로 전달하기 위한 값의 포인터를 의미합니다. 아래 예를 한번 봅시다.

..
//   함수: InitInstance(HINSTANCE, int)
//
//   목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
//   설명:
//
//        이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
//        주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}
..

위를 보시면 CreateWindow는 윈도우를 생성할 뿐이지, 이를 화면에 표시하려면 ShowWindow 함수에 출력하고자 하는 윈도우의 핸들을 넘겨야 합니다. 이번엔 ShowWindow 함수에 대해서 알아볼까요? 다음은 ShowWindow의 함수 원형입니다.

BOOL ShowWindow(HWND hWnd, int nCmdShow);

첫번째 인수로는, 화면에 표시할 윈도우의 핸들을 의미합니다. 두번째 인수로는 화면 출력 옵션인데, 보통 WinMain로 전달된 인자의 nCmdShow를 그대로 입력하면 됩니다. 지정할수 있는 값은 아래와 같습니다.


설명 

SW_FORCEMINIMIZE

2000 이후에만 쓸 수 있는 플레그이다. 윈도우를 소유한 스레드가 블록된 상태에서도 윈도우를 최소화시킨다.

SW_HIDE

윈도우를 숨긴다.

SW_MAXIMIZE

윈도우를 최대화시킨다.

SW_MINIMIZE

윈도우를 최소화시키며 다음 Z순서를 가지는 윈도우가 활성화된다.

SW_RESTORE

최대, 최소화된 윈도우를 이전 위치로 복구한다.

SW_SHOW

윈도우를 활성화하며 보인다.

SW_SHOWDEFAULT

STARTUPINFO 구조체가 지정하는 보이기 상태로 만든다.

SW_SHOWMAXIMIZED

윈도우를 최대화된 상태로 활성화한다.

SW_SHOWMINIMIZED

윈도우를 최소화한 상태로 활성화한다.

SW_SHOWMINNOACTIVE

윈도우를 최소화 상태로 보이며 활성화 상태는 변경되지 않는다.

SW_SHOWNA

윈도우를 헌재 상태로 보이며 활성화 상태는 변경되지 않는다.

SW_SHOWNOACTIVATE

최근 크기와 위치에 윈도우를 보이며 활성화 상태는 변경되지 않는다.

SW_SHOWNORMAL

 윈도우를 보이며 활성화한다. 만약 윈도우가 최소화되어 있거나 최대화되어 있다면 윈도우를 원래 크기대로 복구한다. 윈도우를 처음 화면에 보일 때는 이 플래그를 사용해야 한다.

<출처: winapi>


이번에는 CreateWindow의 전달되는 인수값을 바꿔서 코드를 수정했습니다. 다음 코드는 어떨지 한번 예상해봅시다.

..
//   함수: InitInstance(HINSTANCE, int)
//
//   목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
//   설명:
//
//        이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
//        주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.

   hWnd = CreateWindow(szWindowClass, L"타이틀", WS_BORDER,
      CW_USEDEFAULT, 0, 500, 500, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}
..

결과:


위와 같이 단선으로 된 경계선을 가지고, 타이틀이란 제목을 가진 가로 500, 세로 500인 창이 화면에 표시됩니다. 윈도우가 만들어지는 과정은 다음과 같습니다. '윈도우 클래스 정의 -> 윈도우 클래스 등록 -> 윈도우 생성 -> 윈도우 표시 -> 메세지 루프'와 같이 이루어집니다.