Win32 응용 프로그램 만들기(C++)
업데이트: 2007년 11월
Win32 API(Windows API라고도 함)는 Windows 응용 프로그램을 만들기 위한 C 기반 프레임워크이며 Windows 1.0 이후로 사용되었습니다. Windows API에서 이 API에 대한 광범위한 설명서를 참조할 수 있습니다.
이 절차에서는 창에 "Hello, World!"를 표시하는 간단한 Win32 응용 프로그램을 만듭니다. 절차의 단계는 모든 Win32 응용 프로그램에 대해 동일합니다. 이 절차를 완료한 후 여기서 만든 코드를 기본 구조로 사용하여 다른 Win32 응용 프로그램을 만들 수 있습니다.
사전 요구 사항
이 항목에서는 사용자가 C++ 언어의 기본적인 사항을 알고 있는 것으로 가정합니다. 이제 C++를 배우기 시작하는 초보자는 Herb Schildt가 쓴 "C++ Beginner's Guide"(https://go.microsoft.com/fwlink/?LinkId=115303)를 참조하는 것이 좋습니다.
비디오 데모를 보려면 Video How to: Creating Win32 Applications (C++)를 참조하십시오.
새 Win32 프로젝트를 만들려면
파일 메뉴에서 새로 만들기를 클릭한 다음 프로젝트...를 클릭합니다.
프로젝트 형식 창의 Visual C++ 노드에서 Win32를 선택한 다음 템플릿 창에서 Win32 프로젝트를 선택합니다.
프로젝트의 이름(예: win32app)을 입력합니다. 프로젝트를 저장할 기본 위치를 적용하거나 다른 위치를 입력하거나 원하는 디렉터리를 찾아 선택할 수 있습니다.
Win32 응용 프로그램 마법사에서 다음을 선택합니다.
Win32 응용 프로그램 마법사의 응용 프로그램 종류에서 Windows 응용 프로그램을 선택합니다. 응용 프로그램 옵션에서 빈 프로젝트를 선택합니다. 나머지 옵션은 그대로 유지합니다. 마침을 클릭하여 프로젝트를 만듭니다.
프로젝트 메뉴에서 새 항목 추가...를 선택하여 프로젝트에 C++ 파일을 추가합니다. 새 항목 추가 대화 상자에서 C++ 파일(.cpp)을 선택합니다. 파일의 이름(예: GT_HelloWorldWin32.cpp)을 입력하고 추가를 클릭합니다.
Win32 응용 프로그램을 시작하려면
모든 C 및 C++ 응용 프로그램에 main 함수가 있어야 합니다. 이 함수는 응용 프로그램의 시작점입니다. 마찬가지로 Win32 응용 프로그램의 경우 모든 응용 프로그램에 WinMain 함수가 있어야 합니다. WinMain을 사용하기 위한 구문은 다음과 같습니다.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
이 함수의 매개 변수와 반환 값에 대한 설명은 WinMain 함수를 참조하십시오.
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 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; }
이 함수는 창에 대한 핸들인 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 함수를 구현하지 않았으므로 지금까지는 이 창에 많은 내용이 표시되지 않습니다.
WinMain의 마지막 단계는 메시지 루프입니다. 이 루프는 운영 체제가 보내는 메시지의 수신 대기를 목적으로 합니다. 응용 프로그램이 메시지를 받으면 메시지 처리를 위해 WndProc 함수로 해당 메시지가 디스패치됩니다. 메시지 루프는 다음과 같습니다.
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam;
메시지 루프에서 사용되는 구조체와 함수에 대한 자세한 내용은 MSG, GetMessage, TranslateMessage 및 DispatchMessage를 참조하십시오.
방금 완료한 단계는 대부분의 Win32 응용 프로그램에 공통적입니다. 이때 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 함수는 응용 프로그램이 받는 메시지의 처리를 목적으로 합니다. 일반적으로 스위치 함수를 사용하여 이 함수를 구현합니다.
처리할 첫 번째 메시지는 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; }
예제
설명
모든 단계를 완료한 후 코드는 다음과 유사합니다. 응용 프로그램을 빌드하려면 빌드 메뉴에서 솔루션 빌드를 선택합니다. 응용 프로그램이 오류 없이 컴파일되는 경우 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 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;
}
//
// 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;
}
다음 단계
이전:Windows 응용 프로그램 만들기(C++) | 다음:.NET Framework를 사용하여 Windows Forms 응용 프로그램 만들기(C++)