API란 무엇인가
API: Application Programming Interface
운영체제가 응용 프로그램을 위해 제공하는 함수의 집합이라고 정의할 수 있다.
우리가 사용하는 API 좀 더 정확하게 표현하자면 Windows API라고 합니다.
API는 특정 시스템(운영체제든 하드웨어든)을 위한 함수 집합을 이르는 일반명사이며 그 중의 하나가 Windows API이나 요즘은 일반적으로 API라고 하면 Windows API를 말하는 경우가 많습니다.
API는 운영체제의 중요한 한 부분이며 운영체제 그 자체라고도 할 수 있습니다.
API도 Windows 버전에 따라 여러 가지 종류가 있습니다.
16비트 운영체제인 Windows 3.1에서 제공하는 API를 Win16 API라고 하는데 이름 그대로 16비트 Windows를 위한 API입니다.
Win32 API란 본격적인 32비트 운영체제인 Windows 95/98과 NT에서 제공하는 32비트 Windows를 위한 API입니다.
Win32 API도 Windows 버전에 따라 조금씩 다릅니다.
즉 윈95보다는 윈98의 API가 조금 더 확장되었을 것이며 현재 완벽한 Win32 API는 NT 5.0이 제공하는 것이라 할 수 있습니다.
API와 비슷한 말로 SDK라는 표현이 사용되기도 합니다.
SDK(Software Development Kit)는 원래 API를 사용하여 프로그램을 개발하는 개발 툴 킷 또는 방법론 이었으나 지금은 의미가 전용되어 API와 거의 같은 뜻으로 쓰이고 있습니다.
즉 API 함수는 곧 SDK 함수와 같은 뜻이며 이 프로그램은 SDK로 만들었습니다 라고 하는 것은 순수한 API만을 사용하여 만든 프로그램이라는 뜻이다.
클래스 라이브러리
복잡하고 양이 많은 API 함수들을 좀 더 쉽고 빠르게 사용하기 위해 클래스로 잘 포장하여 클래스 위주로 프로그램을 작성하는 방법입니다.
Windows 프로그래밍에 필요한 클래스들을 미리 작성해 놓고 클래스를 조립하여 프로그램을 만들어 나갑니다.
클래스가 워낙 잘 설계되어 있기 때문에 사용하기도 무척 쉬울 뿐만 아니라 기능 또한 아주 막강합니다.
Windows용 클래스 라이브러리에는 마이크로소프트사의 MFC와 볼랜드 사의 OWL이 대표적입니다.
MFC는 비주얼 C++에 포함되어 있으며 OWL은 볼랜드 C++에 포함되어 있습니다.
API를 공부해야 하는 이유
1) 운영체제가 제공하는 함수이므로 운영체제에 대한 프로그램을 정확히 잘 알기 위해서
2) 클래스 라이브러리에 얽매이지 않기 위하여
WINAPI에서 기억해야 할 자료형
BOOL TRUE or FALSE
BOOLEAN TRUE or FALSE
BYTE Byte (8 bits).
CALLBACK Calling convention for callback functions.
COLORREF Red, Green, Blue (RGB) color value (32 bits).
DWORD 32-bit unsigned integer.
HANDLE Handle to an object.
HBITMAP Handle to a bitmap.
HBRUSH Handle to a brush
HCURSOR Handle to a cursor.
HDC Handle to a device context (DC).
HFONT Handle to a font.
HICON Handle to an icon.
HMENU Handle to a menu.
HMENU Handle to a menu.
HWND Handle to a window.
LONGLONG 64-bit signed integer.
LPARAM 32-bit message parameter.
LPCSTR Null로 끝나는 문자 포인터
LPCTSTR Null로 끝나는 문자 포인터(유니코드)
LPCWSTR Null로 끝나는 문자 포인터(유니코드)
LPSTR Null로 끝나는 문자 포인터
LPTSTR 유니코드가 있으면 유니코드 없으면 일반 문자 포인터
LPVOID void pointer
PCSTR 이전 문자열 포인터
PCTSTR 이전 문자열 포인터
TBYTE 2Byte
TCHAR 유니코드 문자
UINT Unsignedint
WCHAR 유니코드 문자
WORD 16-bit unsigned integer.
WPARAM 32-bit message parameter.
RECT 사각영역 구조체
POINTS 1개의 좌표 구조체
Visual C++에서 유니코드 입력
1. TEXT를 이용하는 방법
TEXT ("문자열")
2. _T를 이용하는 방법
_T("문자열")
3. L를 이용하는 방법
L"문자열"
모두 유니코드 문자열로 인식함
API 첫 번째 예제 작성(윈도우 창 만들기)
API 첫 번째 예제 작성(윈도우 창 만들기)
예제1)
1. [파일] – [새로 만들기] – [프로젝트] – Visual C++에서 Win32를 선택하고 Win32 프로젝트를 선택하고 프로젝트 이름을 입력합니다.
2. 응용 프로그램 종류에서 Windows 응용 프로그램을 선택하고 빈 프로젝트를 체크한 후 마침을 누릅니다.
3. 솔루션 탐색기에서 소스 파일을 선택하고 마우스 오른쪽을 클릭한 후 Visual C++ 탭을 선택하고 C++ 파일을 선택하고 파일명을 입력합니다.
4. 아래와 같은 소스를 입력합니다
첫 번째 예제에 대한 이해
1. 헤더 파일
우선 제일 첫 행을 보면 windows.h 하나만 인클루드되어 있습니다.
도스에서는 사용하는 함수에 따라 여러 개의 헤더 파일을 포함하지만 API에서는 하나의 헤더 파일에 모든 API 함수들의 원형과 사용하는 상수들을 대부분 정의하고 있기 때문에 windows.h만 포함해 주면 됩니다.
2. 시작점
프로그램의 시작점인 엔트리 포인트(Entry Point)는 main 함수가 아니라 WinMain이라는 점입니다.
윈도우즈 프로그램의 시작점은 main이 아닌 WinMain입니다.
원형은 다음과 같습니다.
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance , LPSTR
lpszCmdParam,int nCmdShow)
도스에서의 main 함수는 인수 사용여부에 따라 여러 가지 원형이 있지만 WinMain의 원형은 위와 같이 고정되어 있습니다.
APIENTRY 지정자는 __stdcall형 호출 규약을 사용한다는 뜻인데 일단은 없다고 생각해도 무방합니다.
4개의 인수를 취하는데 각 인수의 의미는 다음과 같습니다.
인수 | 의미 |
hInstance | 프로그램의 인스턴스 핸들 |
hPrevInstance | 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들. 없을 경우는 NULL이 되며 WIN32에서는 항상 NULL입니다. |
lpCmdLine | 명령행으로 입력된 프로그램 인수입니다. 도스의 argv인수에 해당합니다. |
nCmdShow | 프로그램이 실행될 형태이며 최소화 보통모양 등이 전달됩니다 |
이 중 hInstance 이외에는 잘 사용되지 않습니다.
인스턴스(Instance)라는 말은 클래스가 메모리에 실제로 구현된 실체를 의미합니다.
윈도우즈용 프로그램은 여러 개의 프로그램이 동시에 실행되는 멀티 태스킹 시스템일 뿐만 아니라 하나의 프로그램이 여러 번 실행될 수도 있습니다.
이때 실행되고 있는 각각의 프로그램을 프로그램 인스턴스라고 하며 간단히 줄여서 인스턴스라고 합니다.
그리고 lpszClass라는 전역 문자열이 정의되어 있는데 이 문자열은 윈도우 클래스를 정의하는데 사용됩니다.
3. 메시지 처리 함수
이 프로그램을 자세히 보면 두 개의 함수만 있습니다.
하나는 프로그램의 시작점인 WinMain이며 나머지 하나는 WndProc입니다.
도스에서는 main 함수만으로도 프로그램을 작성할 수 있지만 API에서는 아주 특별한 경우를 제외하고는 이 두 개의 함수가 모두 있어야 합니다.
WinMain에서는 윈도우를 만들고 화면에 출력하기만 할 뿐이며 대부분의 일은 WndProc에서 이루어집니다.
WinMain은 프로그램을 시작시키기만 하며 실질적인 처리는 대부분 WndProc에서 이루어집니다.
WinMain의 모양은 대체로 일정하며 특별한 일을 하지 않지만 WndProc는 프로그램에 따라 천차만별로 달라집니다.
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
그리고 소스의 뒷부분에는 이 함수의 본체가 정의되어 있습니다.
4. 윈도우 클래스
WinMain 함수에서 하는 가장 중요한 일은 윈도우를 만드는 일입니다. 윈도우가 있어야 사용자로부터 입력을 받을 수 있고 출력을 보여줄 수도 있기 때문입니다. 윈도우를 만들려면 윈도우 클래스를 먼저 등록한 후 CreateWindow 함수를 호출해야 합니다. 모든 윈도우는 윈도우 클래스를 기반으로 하여 만들어지며 윈도우 클래스는 만들어질 윈도우의 여러가지 특성을 정의합니다. 윈도우 클래스는 windows.h에 다음과 같이 정의되어 있는 구조체입니다. typedef struct tagWNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCSTR lpszMenuName; LPCSTR lpszClassName; } WNDCLASS; style 윈도우의 스타일을 정의합니다. 윈도우가 어떤 형태를 가질 것인가를 지정하는 멤버입니다. 이 멤버가 가질 수 있는 값은 무지하게 많지만 가장 많이 사용하는 값이 CS_HREDRAW와 CS_VREDRAW이다. 이 두 값을 OR 연산자(|)로 연결하여 사용합니다. 이 값들의 의미는 윈도우의 수직(또는 수평) 크기가 변할 경우 윈도우를 다시 그린다는 뜻입니다. 이 밖에도 많은 값이 올 수 있습니다. CS_NOCLOSE를 |로 연결하면 종료 버튼이 없어질 것이다. lpfnWndProc 이 멤버는 윈도우의 메시지 처리 함수를 지정합니다. 메시지가 발생할 때마다 여기서 지정한 함수가 호출되며 이 함수가 모든 메시지를 처리합니다. 메시지 처리 함수의 이름은 물론 마음대로 정할 수 있지만 거의 WndProc으로 정해져 있는 편입니다. cbClsExtra, cbWndExtra 일종의 예약 영역입니다. 윈도우즈가 내부적으로 사용하며 아주 특수한 목적에 사용되는 여분의 공간입니다. 예약 영역을 사용하지 않을 경우는 0으로 지정합니다. hInstance 이 윈도우 클래스를 사용하는 프로그램의 번호이며 이 값은 WinMain의 인수로 전달된 hInstance값을 그대로 대입해주면 됩니다. hIcon, hCursor 이 윈도우가 사용할 마우스 커서와 최소화되었을 경우 출력될 아이콘을 지정합니다. LoadCursor 함수와 LoadIcon 함수를 사용하여 지정합니다. 사용자가 직접 아이콘과 커서를 만들어 사용할 수도 있지만 여기서는 윈도우즈가 디폴트로 제공하는 아이콘과 커서를 사용하고 있습니다. hbrBackground 윈도우의 배경 색상을 지정합니다. GetStockObject라는 함수를 사용하여 윈도우에서 기본적으로 제공하는 브러시를 지정합니다. 지정할 수 있는 브러시에는 여러 가지 종류가 있지만 가장 일반적인 흰색 배경(WHITE_BRUSH)이 많이 사용됩니다. lpszMenuName 이 프로그램이 사용할 메뉴를 지정합니다. 메뉴는 프로그램 코드에서 만드는 것이 아니라 리소스 에디터에 의해 별도로 만들어진 후 링크시에 같이 합쳐집니다. 메뉴를 사용하지 않을 경우 이 멤버에 NULL을 대입해 주면 됩니다. lpszClassName 윈도우 클래스의 이름을 정의합니다. 여기서 지정한 이름은 CreateWindow 함수에 전달 되어지며 CreateWindow 함수는 윈도우 클래스에서 정의한 특성 값을 참조하여 윈도우를 만듭니다. 윈도우 클래스를 정의한 후 RegisterClass 함수를 호출하여 윈도우 클래스를 등록합니다. ATOM RegisterClass( CONST WNDCLASS *lpWndClass); RegisterClass 함수의 인수로 WndClass 구조체의 번지를 넘겨주면 됩니다. 이런 이런 특성을 가진 윈도우를 앞으로 사용하겠다는 등록 과정입니다. 윈도우 클래스를 등록한 후에는 등록한 윈도우 클래스를 기본으로 윈도우를 실제 생성해야 합니다. 윈도우를 생성할 때는 CreateWindow 함수를 사용합니다. HWND CreateWindow(lpszClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight, hwndParent, hmenu, hinst, lpvParam) lpszClassName 생성하고자 하는 윈도우의 클래스를 지정하는 문자열입니다. lpszWindowName 윈도우의 타이틀 바에 나타날 문자열입니다. dwStyle 만들고자 하는 윈도우의 형태를 지정하는 인수입니다. 일종의 비트 필드 값이며 거의 수 십 개를 헤아리는 매크로 상수들이 정의되어 있고 이 상수들을 OR연산자로 연결하여 윈도우의 다양한 형태를 지정합니다. 윈도우가 경계선을 가질 것인가, 타이틀 바를 가질 것인가 또는 스크롤 바의 유무 등등을 세세하게 지정해 줄 수 있습니다. 가능한 스타일 값에 관한 자세한 내용은 레퍼런스를 참조하되 WS_OVERLAPPEDWINDOW를 사용하면 가장 무난한 윈도우 설정 상태가 됩니다. 시스템 메뉴, 최대 최소 버튼, 타이틀 바, 경계선을 가진 윈도우를 만들어 줍니다. X, Y, nWidth, nHeight 인수의 이름이 의미하듯이 윈도우의 크기와 위치를 지정하며 픽셀 단위를 사용합니다. x, y좌표는 메인 윈도우의 경우는 전체 화면을 기준으로 하며 차일드 윈도우는 부모 윈도우의 좌상단을 기준으로 합니다. 정수 값을 바로 지정해도 되며 CW_USEDEFAULT를 사용하면 윈도우즈가 알아서 적당한 크기와 위치를 설정해 줍니다. hWndParent 부모 윈도우가 있을 경우 부모 윈도우의 핸들을 지정해 줍니다. MDI 프로그램이나 팝업 윈도우는 윈도우끼리 수직적인 상하관계를 가져 부자(parent-child) 관계가 성립되는데 이 관계를 지정해 주는 인수입니다. 부모 윈도우가 없을 경우는 이 값을 NULL로 지정하면 됩니다. hmenu 윈도우에서 사용할 메뉴의 핸들을 지정합니다. WndClass에도 메뉴를 지정하는 멤버가 있는데 윈도우 클래스의 메뉴는 그 윈도우 클래스를 기반으로 하는 모든 윈도우에서 사용되는 반면 이 인수로 지정된 메뉴는 현재 CreateWindow 함수로 만들어지는 윈도우에서만 사용됩니다. 만약 WndClass에서 지정한 메뉴를 그대로 사용하려면 이 인수를 NULL로 지정하면 되며 WndClass에서 지정한 메뉴 대신 다른 메뉴를 사용하려면 이 인수에 원하는 메뉴 핸들을 주면 됩니다. hinst 윈도우를 만드는 주체, 즉 프로그램의 핸들을 지정합니다. WinMain의 인수로 전달된 hInstance를 대입해 주면 됩니다. lpvParam CREATESTRUCT라는 구조체의 번지이며 특수한 목적에 사용됩니다. 보통은 NULL값을 사용합니다. CreateWindow 함수는 윈도우에 관한 모든 정보를 메모리에 만든 후 윈도우 핸들을 리턴 값으로 넘겨줍니다. 넘겨지는 윈도우 핸들은 hWnd라는 지역 변수에 저장되었다가 윈도우를 참조하는 모든 함수의 인수로 사용됩니다. 메모리에 만들어진 윈도우를 화면으로 보이게 하려면 다음 함수를 사용해야 합니다. BOOL ShowWindow(hWnd, nCmdShow); hWnd 인수는 화면으로 출력하고자 하는 윈도우의 핸들이며 CreateWindow 함수가 리턴한 핸들을 그대로 넘겨주면 됩니다. nCmdShow는 윈도우를 화면에 출력하는 방법을 지정하며 다음과 같은 매크로 상수들이 정의되어 있습니다. SW_HIDE 윈도우를 숨긴다. SW_MINIMIZE 윈도우를 최소화시키고 활성화시키지 않는다. SW_RESTORE 윈도우를 활성화시킨다. SW_SHOW 윈도우를 활성화시켜 보여준다. SW_SHOWNORMAL 윈도우를 활성화시켜 보여준다. nCmdShow 인수에 어떤 값을 넘겨줄 것인가는 하는 문제는 WinMain 함수의 인수로 전달된 nCmdShow를 그대로 넘겨주기만 하면 됩니다. 윈도우를 만들고 화면에 나타내는 코드는 다음 두 줄입니다. hwnd = CreateWindow (szAppName, // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow(hWnd,nCmdShow); 여기까지 실행하면 화면에 윈도우가 출력됩니다. 이 후부터는 메시지 루프가 시작되며 프로그램이 사용자와 윈도우즈, 그리고 다른 프로그램과 상호 정보를 교환하며 실행됩니다. |
메시지 루프
윈도우즈를 메시지 구동 시스템(Message Driven System)이라고 하며 이 점이 도스와 가장 뚜렷한 대비를 이루는 윈도우즈의 특징입니다. 도스에서는 프로그래머에 의해 미리 입력된 일련의 명령들을 순서대로 실행하는 순차적 실행방법을 사용합니다. 윈도우즈는 이와 다르게 프로그램의 실행 순서가 명확하게 정해져 있지 않으며 상황에 따라 실행 순서가 달라지는 데 여기서 말하는 상황이란 바로 어떤 메시지가 주어졌는가를 의미합니다. 메시지란 사용자나 시스템 내부적인 동작에 의해 발생된 일체의 변화에 대한 정보를 의미합니다. 예를 들어 사용자가 마우스의 버튼을 눌렀다거나 키보드를 눌렀다거나 윈도우가 최소화되었다거나 하는 변화에 대한 정보들이 메시지입니다. 메시지가 발생하면 프로그램에서는 메시지가 어떤 정보를 담고 있는가를 분석하여 어떤 루틴을 호출할 것인가를 결정합니다. 순서를 따르지 않고 주어진 메시지에 대한 반응을 정의하는 방식으로 프로그램이 실행됩니다. 윈도우즈 프로그램에서 메시지를 처리하는 부분을 메시지 루프라고 하며 보통 WinMain 함수의 끝에 아래와 같은 형식으로 존재합니다. while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; 메시지 루프는 세 개의 함수 호출로 이루어져 있으며 전체 루프는 while문으로 싸여져 있습니다. BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); 이 함수는 시스템이 유지하는 메시지 큐에서 메시지를 읽어 들이게 됩니다. 읽어 들인 메시지는 첫 번째 인수가 지정하는 MSG 구조체에 저장됩니다. 이 함수는 읽어 들인 메시지가 프로그램을 종료하라는 WM_QUIT일 경우 False를 리턴하며 그 외의 메시지이면 True를 리턴합니다. 따라서 WM_QUIT 메시지가 읽혀질 때까지, 즉 프로그램이 종료될 때까지 전체 while 루프가 계속 실행됩니다. 나머지 세 개의 인수는 읽어 들일 메시지의 범위를 지정합니다. BOOL TranslateMessage( CONST MSG *lpMsg); 키보드 입력 메시지를 가공하여 프로그램에서 쉽게 쓸 수 있도록 해주는 함수입니다. 윈도우즈는 키보드의 어떤 키가 눌러졌다거나 떨어졌을 때 키보드 메시지를 발생시키는데 이 함수는 키보드의 눌림(WM_KEYDOWN)과 떨어짐(WM_KEYUP)이 연속적으로 발생할 때 문자가 입력되었다는 메시지(WM_CHAR)를 만드는 역할을 합니다. 예를 들어 A키를 누른 후 다시 A키를 떼면 A문자가 입력되었다는 메시지를 만들어 냅니다. LONG DispatchMessage( CONST MSG *lpmsg); 시스템 메시지 큐에서 꺼낸 메시지를 프로그램의 메시지 처리 함수(WndProc)로 전달합니다. 이 함수에 의해 메시지가 프로그램으로 전달되며 프로그램에서는 전달된 메시지를 점검하여 다음 동작을 결정하게 됩니다. 메시지 루프에서 하는 일은 메시지를 꺼내고, 필요한 경우 약간 형태를 바꾼 후 응용 프로그램으로 전달하는 것뿐입니다. 이 과정은 WM_QUIT 메시지가 전달될 때까지, 즉 프로그램이 종료될 때까지 반복됩니다. 결국 메시지 루프가 하는 일이란 메시지 큐에서 메시지를 꺼내 메시지 처리 함수로 보내주는 것 입니다. 실제 메시지 처리는 별도의 메시지 처리 함수(WndProc)에서 수행합니다. 메시지는 시스템의 변화에 대한 정보이며 MSG라는 구조체에 보관됩니다. MSG 구조체는 아래와 같이 정의되어 있다. typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; 각 멤버의 의미는 다음과 같다.
GetMessage 함수는 읽은 메시지를 MSG형의 구조체에 대입해 주며 이 구조체는 DispatchMessage 함수에 의해 응용 프로그램의 메시지 처리 함수(WndProc)로 전달됩니다. 메시지는 실제로 하나의 정수값으로 표현되는데 메시지의 종류가 무척 많아 메시지의 번호를 일일이 암기하여 사용할 수가 없으므로 windows.h에 메시지별로 매크로 상수를 정의해 두었으며 접두어 WM_으로 시작됩니다. 가장 자주 사용되는 메시지
도스에서 사용하는 탈출 코드와 동일한 의미를 가지며 사용되는 경우가 거의 없습니다 |
WndProc
메시지 처리 함수란 메시지가 발생할 때 프로그램의 반응을 처리하는 일을 하며 WinMain 함수와는 별도로 WndProc이라는 이름으로 존재합니다. 윈도우 프로시저(Window Procedure)라는 뜻으로 WndProc은 WinMain에서 호출하는 것이 아니라 윈도우즈에 의해 호출됩니다. WinMain내의 메시지 루프는 메시지를 메시지 처리 함수로 보내주기만 할 뿐이며 WndProc은 메시지가 입력되면 윈도우즈에 의해 호출되어 메시지를 처리합니다. 운영체제에 의해 호출되는 응용 프로그램내의 함수를 콜백(CallBack) 함수라고 합니다. WndProc의 인수는 모두 4개이며 MSG 구조체의 멤버 4개와 동일합니다. hWnd는 메시지를 받을 윈도우의 핸들이며 message는 어떤 종류의 메시지인가, 즉 어떤 변화가 발생했는가에 관한 정보를 가집니다. message가 WM_MOVE이면 윈도우의 위치가 변경되었음을 알리고 WM_DESTROY이면 윈도우가 파괴되었음을 알리는 것입니다. wParam, lParam은 message의 메시지에 따른 부가적인 정보를 가지게 됩니다. 예를 들어 마우스 버튼이 눌러졌다는 WM_LBUTTONDOWN 메시지가 입력되었다면 화면의 어디쯤에서 마우스 버튼이 눌러졌는가, 그때의 키보드 상황(Shift, Ctrl, Alt)은 어떠한가에 관한 정보가 추가로 필요하며 WM_CHAR 메시지, 즉 키보드로부터 키가 입력되었다는 메시지가 입력되었다면 어떤 키가 입력되었는가에 관한 추가적인 정보가 필요합니다. 이런 추가 정보들이 wParam, lParam으로 전달됩니다. wParam, lParam에 실제로 어떤 값을 전달되는지는 메시지 별로 다릅니다. WndProc의 구조는 대체로 다음과 같은 형태를 가집니다. 메시지의 종류에 따라 다중 분기하여 메시지 별로 처리를 진행합니다. switch(message) { case Msg1: 처리1; return; case Msg2: 처리2; return; case Msg3: 처리3; return; default: return DefWindowProc(...); } Msg1 메시지가 전달되면 처리1을 한 후 종료하고 Msg2 메시지가 전달되면 처리2를 한 후 종료합니다. case문은 프로그램이 처리할 메시지의 수만큼 반복될 것입니다. 제일 끝에 있는 DefWindowProc 함수는 WndProc에서 처리하지 않은 나머지 메시지에 관한 처리를 해 준다. 예를 들어 시스템 메뉴를 더블 클릭하면 프로그램이 종료되는데 이런 처리는 별도로 해 주지 않아도 DefWindowProc 함수에서 해 주게 됩니다. 그래서 윈도우의 이동이나 크기변경 따위의 처리는 직접 해 줄 필요없이 DefWindowProc으로 넘겨주기만 하면 됩니다. 예제의 메시지 처리 함수는 다음과 같이 되어 있습니다. LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } WM_DESTROY 메시지만을 처리하고 있으며 나머지 메시지에 대해서는 DefWindowProc에게 맡깁니다. WM_DESTROY 메시지는 사용자가 시스템 메뉴를 더블 클릭하거나 Alt+F4를 눌러 프로그램을 끝내려고 할 때 발생하는 메시지입니다. WndProc에서 이 메시지가 발생하면 PostQuitMessage 함수를 호출하여 WM_QUIT 메시지를 보냅니다. WM_QUIT 메시지가 입력되면 메시지 루프의 GetMessage 함수 리턴 값이 False가 되어 프로그램이 종료됩니다. WM_DESTROY 이외의 메시지는 모두 DefWindowProc 함수로 전달되며 이 함수에서 디폴트 처리를 수행해 줍니다. DefWindowProc 함수가 메시지를 처리했을 경우 이 함수가 리턴한 값을 WndProc 함수가 다시 리턴해 주어야 합니다. |
(예제) 윈도우의 타이틀 바꾸기
(예제) 윈도우의 크기 바꾸기
윈도우 스타일 변경
CreateWindow함수의 세 번째 인수 dwStyle은 윈도우즈의 여러가지 속성을 정의하는 32비트 정수값이며 이 값을 변경함에 따라 다양한 모양의 윈도우를 만들 수 있습니다. 아래의 값들을 OR연산자로 연결하여 여러 가지 속성을 한꺼번에 지정합니다.
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) 여기서 WS_OVERLAPPED는 실제로 0이므로 아무런 의미가 없으며 타이틀 바, 시스템 메뉴, 크기조절이 가능한 경계선, 최소, 최대 버튼 등의 스타일이 한꺼번에 정의되어 있습니다. WS_OVERLAPPEDWINDOW 스타일을 사용하면 가장 평범한 모양의 윈도우가 만들어집니다. CreateWindow의 dwStyle 인수를 다음과 같이 변경해 보세요. WS_CAPTION | WS_SYSMENU 타이틀 바와 시스템 메뉴만 있을 뿐 최대, 최소화 버튼은 없습니다. 윈도우의 크기를 조절하는 경계선이 없기 때문에 경계선을 드래그하여 윈도우의 크기를 변경할 수도 없게 됩니다. WS_OVERLAPPEDWINDOW | WS_VSCROLL 이렇게 변경한 후 다시 프로그램을 실행시키면 수직 스크롤 바가 달린 윈도우가 만들어집니다. 이외에 윈도우의 모양을 변경할 수 있는 상당히 많은 dwStyle값들이 있습니다. |
배경색 바꾸기
우리가 만든 예제의 배경색은 흰색입니다.
배경색이 흰색이 되었는가 하면 WndClass의 멤버 중 배경색상을 지정하는 hbrBackground가 흰색 브러시로 지정되어 있기 때문입니다.
WndClass.hbrBackground=GetStockObject(WHITE_BRUSH);
여기서 사용된 GetStockObject 함수는 윈도우즈가 기본적으로 제공하는 브러시, 펜 등의 핸들을 구해주는 함수인데 이 함수의 인수로 WHITE_BRUSH가 사용되었기 때문에 배경색을 칠하는 데 흰색 브러시가 사용되었습니다.
이 값을 BLACK_BRUSH로 변경하면 검정색이 배경색으로 사용되며 LTGRAY_BRUSH로 변경하면 옅은 회색 배경이 만들어집니다.
윈도우즈가 제공하는 브러시 이외의 브러시를 사용하려면 다음과 같은 방법을 사용해야 gk합니다.
WndClass.hbrBackground=CreateSolidBrush(RGB(0,0,255));
커서 바꾸기
예제의 윈도우위에 마우스 커서를 위치시키면 화살표 모양의 커서가 나타납니다. 이 커서가 사용되는 이유는 WndClass에서 커서를 지정하는 멤버가 다음과 같이 정의되어 있기 때문입니다. WndClass.hCursor=LoadCursor(NULL,IDC_ARROW); hCursor 멤버는 윈도우가 기본적으로 사용할 커서를 지정하며 LoadCursor 함수는 커서를 읽어오는 함수입니다. HCURSOR LoadCursor( HINSTANCE hInstance, LPCTSTR lpCursorName ); 첫 번째 인수 hInstance는 커서를 가지고 있는 프로그램의 인스턴스 핸들이되 윈도우즈가 제공하는 디폴트 커서를 사용하려면 이 인수를 NULL로 지정하면 됩니다. 두 번째 인수 lpCursorName은 사용하고자 하는 커서의 이름을 지정합니다. 윈도우즈가 디폴트로 제공하는 커서에는 다음과 같은 종류가 있습니다.
|
아이콘 바꾸기
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION); 위의 부분을 아래와 같이 수정하면 아이콘이 바뀌게 됩니다. WndClass.hIcon=LoadIcon(NULL,IDI_HAND); |
'C & C++ > C & C++' 카테고리의 다른 글
[API] API 메시지 처리 (0) | 2011.04.25 |
---|---|
[API] 화면 출력 API (0) | 2011.04.25 |
메시지 훅(Message Hook) (0) | 2011.04.25 |
[MFC] 프로세스 간의 통신 (0) | 2011.04.25 |
[MFC] Thread (0) | 2011.04.25 |
댓글