API란?
Application Programming Interface의 약자로 운영체제에서 응용프로그램을 쉽게 개발할 수 있도록 제공하는 함수들의 집합을 말합니다.
운영체제는 응용프로그램과 하드웨어 사이에서 응용프로그램이 하드웨어로 부터 필요한 동작과 자원들을 함수를 통해 제공해 개발자가 하드웨어의 특성을 잘 알지 못해도 그 함수를 이용하면 해당하는 동작을 할 수 있도록 도와줍니다.
Microsoft는 Windows 에서 동작하는 API를 Win32 API로 명명하고 개발자들에 제공하고 있습니다.
이번시간에는 Win32API를 사용해 다양한 프로그램을 만들어 보겠습니다.
그 수준은 그리 높지 않으니 너무 걱정 마시기 바랍니다.
아차! Microsoft TECH CAMP관련 포스팅의 모든 강의자료와 강의 내용들은 실제 현장 강의내용들과 MVP님이 운영하시는 tipssoft(http://www.tipssoft.com/)에서 참고하여 만든 것이므로 더욱 자세한 내용을 원하시는 분은 위 링크로 접속하시면 됩니다. 이 포스트들은 제가 이해한 만큼, 나중에 까먹었을 때 다시 참고하기 위해 끄적이는 내용들 입니다.
이번 시간에는 Win32 API를 활용해 클릭했을 때 다양한 이벤트가 발생하도록 하는 예제를 만들어 볼 겁니다.
먼저 새 프로젝트를 만들겠습니다.
Win32 디렉토리의 Win32 프로젝트를 선택하시고 응용프로그램 설정에서 SDL 검사만 해제하시면 됩니다.
*SDL 검사란?
Security Development Lifecycle 의 준말로, 보안에 문제가 생길수 있는 함수들을 검사하고 다른 함수를 사용하도록 유도하는 기능입니다. MVP님의 말씀에 따르면 이 검사를 하는 것보다는 보다 본질적인 것을 수정하는 것이 도움이 될 것이라고 합니다. 가령 scanf 혹은 strcpy와 같은 함수들이 문제가 될 수 있고, scanf_s, strcpy_s로 수정하라고 경고가 아닌 에러로 표시를 해줄 것입니다.
// RandPoint.cpp : 응용 프로그램에 대한 진입점을 정의합니다. // #include "stdafx.h" #include "RandPoint.h"
솔루션 탐색기에서 RandPoint.cpp 파일을 연 뒤, 위의 내용만 남기고 모두 지워줍니다.
그냥 써도 될테지만 벽돌 한 장 한 장 쌓아올리는 기쁨을 얻으시라고 지우는 겁니다 ㅎㅎ
// RandPoint.cpp : 응용 프로그램에 대한 진입점을 정의합니다. // #include "stdafx.h" #include "RandPoint.h" LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; wchar_t my_app_class_name[] = L"tipssoft"; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hInstance = hInstance; wc.lpfnWndProc = WndProc; wc.lpszClassName = my_app_class_name; wc.lpszMenuName = NULL; wc.style = NULL; RegisterClass(&wc); HWND hWnd = CreateWindow(my_app_class_name, L"www.tipssoft.com", WS_OVERLAPPEDWINDOW, 400, 100, 800, 600, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
윈도우에서 창을 띄우기 위한 가장 기본적인 소스를 작성했습니다.Win32API에서 가장 중요한 두가지 기능을 방금 작성했습니다. WndProc 와 WinMain 인데요. WndProc 는 Window Procedure의 약어이며, WM_ 로 시작하는 메시지들을 받았을 때 처리과정을 정의하고 그에 맞는 메시지를 보내주는 함수들의 집합입니다. WinMain은 실제 창을 그리고 메시지를 받아서 처리할 우체통도 만드는 역할을 합니다.
먼저 WinMain을 뜯어보겠습니다.
WNDCLASS : 윈도우 클래스(Windows가 아닙니다)
Windows는 메시지 기반 운영체제 입니다. 마우스를 움직이거나 키보드가 동작하거나 창을 움직이는 등의 모든 행위들이 메시지로 전달되어 프로그램이 동작하게 됩니다. 이런 메시지들은 Winmain의 메시지큐에 전달되어 처리됩니다. 이름처럼 FIFO(First In First Out) 구조를 가지고 있어 이 메시지를 받아 번역한 뒤 윈도 프로시져에 전달하면 처리하는 구조를 가지고 있습니다. 메시지큐는 while문으로 구성되어 있으며 wParam값을 리턴합니다.
그럼 이제 다음 작업으로 넘어가 창닫기 버튼을 누르면 정상종료할 것인지 물어보고 닫는 코드를 작성해보겠습니다.
// RandPoint.cpp : 응용 프로그램에 대한 진입점을 정의합니다. // #include "stdafx.h" #include "RandPoint.h" LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: if (IDCANCEL == MessageBox(hWnd, L"R U sure?", L"Close", MB_OKCANCEL | MB_ICONWARNING)) return 1; break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
윈도 프로시져에서 Switch 문을 활용해 메시지의 종류에 따라 다른 동작을 할 수 있도록 합니다. 메시지루프에서 번역을 끝낸 메시지가 윈도 프로시져에 들어오면 각 WM_ 이하의 프로시져를 수행한 뒤 마지막 디폴트 윈도 프로시져를 반환합니다.
윈도우를 종료하는 방법은 크게 세가지 메시지가 있습니다. 먼저 WM_DESTROY는 윈도우가 파괴될때 전달됩니다. WM_CREATE의 반대동작을 하며 할당해 둔 메모리를 해제하고 열린 파일을 닫는 행위를 실시하는 녀석입니다.
WM_CLOSE는 윈도우가 닫히기 전 전달되는 메시지로, 메시지박스를 호출하는 행위를 통해 한 번 물어볼 수 있도록 하는 자비로운 녀석입니다. 물론 종료하겠냐는 물음에 좋다고 하면 WM_DESTROY 메시지를 호출하여 처리합니다.
WM_QUIT는 위의 두 메시지 후 응용프로그램을 종료하라는 신호입니다. 메시지 루프를 종료하는 역할을 합니다.
사용자가 X 버튼을 누르면 WM_CLOSE, WM_DESTROY, WM_QUIT의 메시지가 차례대로 큐에 쌓이게 됩니다.
'Tech > C/C++/C#' 카테고리의 다른 글
Microsoft Tech Camp Day 3 C++의 역사부터 함수포인터까지 (0) | 2015.12.26 |
---|---|
Microsoft Tech Camp Day 2 (3) 메모리 동적할당 (0) | 2015.12.23 |
Microsoft Tech Camp Day 2 (2) C 배열과 (악마의) 포인터 (0) | 2015.12.23 |
Microsoft Tech Camp Day 2 (1) C 전처리기부터 변수까지 (0) | 2015.12.16 |
Microsoft Tech Camp Day 1 (2) C의 구성요소와 함수들 (0) | 2015.12.08 |