Win32 기반 응용 프로그램 만들기(C++)
이 연습에서는 창에 "Hello, World!"를 표시하는 기본적인 Win32 기반 응용 프로그램을 만드는 방법을 보여 줍니다.이 연습에서 개발하는 코드는 다른 Win32 기반 응용 프로그램을 만드는 데 패턴으로 사용할 수 있습니다.
Win32 API(Windows API라고도 함)는 Windows 응용 프로그램을 만들기 위한 C 기반 프레임워크입니다.Win32 API에 대한 자세한 내용은 Windows API를 참조하십시오.
중요 |
---|
이 문서의 단계에서 나오는 코드의 특정 부분을 보다 명확하게 설명하기 위해 include 지시문이나 전역 변수 선언 같이 응용 프로그램 작동에 필요한 다른 코드 문은 생략될 수 있습니다.이 문서의 끝에 나오는 예제 단원에서는 전체 코드를 보여 줍니다. |
사전 요구 사항
이 연습을 완료하려면 C++ 언어의 기본적인 사항을 알고 있어야 합니다.
비디오 데모를 보려면 Visual Studio 2008 설명서에 포함된 Video How to: Creating Win32 Applications (C++)를 참조하십시오.
Win32 기반 프로젝트를 만들려면
파일 메뉴에서 새로 만들기를 클릭한 다음 프로젝트를 클릭합니다.
새 프로젝트 대화 상자의 왼쪽 창에서 설치된 템플릿을 클릭하고 **Visual C++**를 클릭한 다음 Win32를 선택합니다.가운데 창에서 Win32 프로젝트를 선택합니다.
이름 상자에 프로젝트의 이름(예: win32app)을 입력합니다.확인을 클릭합니다.
Win32 응용 프로그램 마법사의 시작 페이지에서 다음을 클릭합니다.
응용 프로그램 설정 페이지의 응용 프로그램 종류 아래에서 Windows 응용 프로그램을 선택합니다.추가 옵션에서 빈 프로젝트를 선택합니다.마침을 클릭하여 프로젝트를 만듭니다.
솔루션 탐색기에서 Win32app 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가를 클릭한 다음 새 항목을 클릭합니다.새 항목 추가 대화 상자에서 **C++ 파일(.cpp)**을 선택합니다.이름 상자에 파일 이름(예: GT_HelloWorldWin32.cpp)을 입력합니다.추가를 클릭합니다.
Win32 기반 응용 프로그램을 시작하려면
모든 C 응용 프로그램과 C++ 응용 프로그램에 시작점으로 main 함수가 있어야 하는 것처럼, 모든 Win32 기반 응용 프로그램에는 WinMain 함수가 있어야 합니다.WinMain의 구문은 다음과 같습니다.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
이 함수의 매개 변수와 반환 값에 대한 자세한 내용은 WinMain 함수를 참조하십시오.
응용 프로그램 코드에서는 기존 정의를 사용해야 하므로 파일에 include 문을 추가해야 합니다.
#include <windows.h> #include <stdlib.h> #include <string.h> #include <tchar.h>
WinMain 외에도 각 Win32 응용 프로그램에는 창 프로시저 함수도 있어야 합니다.이 함수의 이름은 일반적으로 WndProc입니다.WndProc의 구문은 다음과 같습니다.
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
이 함수는 응용 프로그램이 운영 체제로부터 받는 많은 메시지를 처리합니다.예를 들어 확인 단추를 포함하는 대화 상자가 있는 응용 프로그램에서 사용자가 이 단추를 클릭하면 운영 체제에서는 단추가 클릭되었다는 메시지를 응용 프로그램에 보냅니다.WndProc은 이 이벤트에 응답하는 작업을 담당합니다.이 예제에서 적절한 응답은 대화 상자를 닫는 것일 수 있습니다.
자세한 내용은 창 프로시저를 참조하십시오.
WinMain 함수에 기능을 추가하려면
WinMain 함수에서 WNDCLASSEX 형식의 창 클래스 구조체를 만듭니다.이 구조체에는 응용 프로그램 아이콘, 창의 배경색, 제목 표시줄에 표시할 이름, 창 프로시저 함수의 이름 등 창에 대한 정보가 들어 있습니다.다음 예제에서는 일반적인 WNDCLASSEX 구조체를 보여 줍니다.
WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
이 구조체의 필드에 대한 자세한 내용은 WNDCLASSEX를 참조하십시오.
이제 창 클래스를 만들었으므로 이를 등록해야 합니다.RegisterClassEx 함수를 사용하여 창 클래스 구조체를 인수로 전달합니다.
if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
이제 사이트를 만들 수 있습니다.CreateWindow 함수를 사용합니다.
static TCHAR szWindowClass[] = _T("win32app"); static TCHAR szTitle[] = _T("Win32 Guided Tour Application"); // The parameters to CreateWindow explained: // szWindowClass: the name of the application // szTitle: the text that appears in the title bar // WS_OVERLAPPEDWINDOW: the type of window to create // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y) // 500, 100: initial size (width, length) // NULL: the parent of this window // NULL: this application does not have a menu bar // hInstance: the first parameter from WinMain // NULL: not used in this application HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL ); if (!hWnd) { MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
이 함수는 창에 대한 핸들인 HWND를 반환합니다.자세한 내용은 Windows 데이터 형식을 참조하십시오.
이제 다음 코드를 사용하여 창을 표시합니다.
// The parameters to ShowWindow explained: // hWnd: the value returned from CreateWindow // nCmdShow: the fourth parameter from WinMain ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
아직 WndProc 함수를 구현하지 않았으므로 지금까지는 표시된 창에 많은 내용이 없습니다.
이제 운영 체제에서 보내는 메시지를 수신 대기하는 메시지 루프를 추가합니다.응용 프로그램이 메시지를 받으면 이 루프는 메시지를 처리하도록 WndProc 함수로 메시지를 디스패치합니다.메시지 루프는 다음 코드와 유사합니다.
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam;
메시지 루프의 구조체와 함수에 대한 자세한 내용은 MSG, GetMessage, TranslateMessage 및 DispatchMessage를 참조하십시오.
이때 WinMain 함수는 다음 코드와 유사합니다.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; } hInst = hInstance; // Store instance handle in our global variable // The parameters to CreateWindow explained: // szWindowClass: the name of the application // szTitle: the text that appears in the title bar // WS_OVERLAPPEDWINDOW: the type of window to create // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y) // 500, 100: initial size (width, length) // NULL: the parent of this window // NULL: this application dows not have a menu bar // hInstance: the first parameter from WinMain // NULL: not used in this application HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL ); if (!hWnd) { MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL); return 1; } // The parameters to ShowWindow explained: // hWnd: the value returned from CreateWindow // nCmdShow: the fourth parameter from WinMain ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // Main message loop: MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }
WndProc 함수에 기능을 추가하려면
WndProc 함수가 응용 프로그램에서 받은 메시지를 처리할 수 있도록 switch 문을 구현합니다.
처리할 첫 번째 메시지는 WM_PAINT 메시지입니다.표시된 창의 일부를 업데이트해야 하는 경우 응용 프로그램이 이 메시지를 받습니다.창이 처음 표시될 때는 창의 모든 내용이 업데이트되어야 합니다.
WM_PAINT 메시지를 처리하려면 먼저 BeginPaint를 호출하고, 창의 텍스트, 단추 및 기타 컨트롤을 레이아웃하는 모든 논리를 처리한 다음 EndPaint를 호출합니다.이 응용 프로그램의 경우 시작하는 호출과 끝내는 호출 사이의 논리는 "Hello, World!"라는 문자열을 창에 표시하는 것입니다.다음 코드에서 TextOut 함수는 문자열을 표시하는 데 사용됩니다.
PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Hello, World!"); switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // Here your application is laid out. // For this introduction, we just print out "Hello, World!" // in the top left corner. TextOut(hdc, 5, 5, greeting, _tcslen(greeting)); // End application-specific layout section. EndPaint(hWnd, &ps); break; }
일반적으로 응용 프로그램에서는 WM_CREATE 및 WM_DESTROY와 같은 다른 많은 메시지를 처리합니다.다음 코드에서는 기본적이지만 완전한 WndProc 함수를 보여 줍니다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Hello, World!"); switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // Here your application is laid out. // For this introduction, we just print out "Hello, World!" // in the top left corner. TextOut(hdc, 5, 5, greeting, _tcslen(greeting)); // End application specific layout section. EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; }
예제
이 예제를 빌드하려면
이 연습 앞부분의 "Win32 기반 프로젝트를 만들려면"에서 설명한 대로 Win32 기반 프로젝트를 만듭니다.
이 단계 아래의 코드를 복사한 다음 GT_HelloWorldWin32.cpp 소스 파일에 붙여 넣습니다.
빌드 메뉴에서 솔루션 빌드를 클릭합니다.
응용 프로그램을 실행하려면 F5 키를 누릅니다.텍스트를 포함 하는 창 "Hello World!" 디스플레이의 왼쪽 위 모서리에 나타납니다.
코드
// GT_HelloWorldWin32.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("win32app");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
hInst = hInstance; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, World!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, World!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}