// Client.cpp : 애플리케이션에 대한 진입점을 정의합니다.
//
#include "pch.h"
#include "Client.h"
#define MAX_LOADSTRING 100
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// 생략 ...
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
// 생략 ...
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
// 생략 ...
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// 생략...
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
// 생략...
}
Windows 데스크톱 프로그래밍을 처음 생성했을 떄의 구성요소를 확인할 수 있습니다.
wWinMain : Window 프로그램의 진입점
MyRegiesrClass : Window Class 등록함수
InitInstance : Instance 핸들을 전역변수hInst
에 저장합니다.
WndProc : 프로그래머가 윈도우 메시지를 어떻게 처리할 지에 대해서 정의할 수 있습니다. 다만 이미 인자 형태와 반환 값의 형태가 지정되어 있는 형태의 함수입니다.
About : 정보 대화상자의 메시지 처리기입니다.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
// 전역 문자열을 초기화합니다.
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_CLIENT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 애플리케이션 초기화를 수행합니다:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLIENT));
MSG msg;
// 기본 메시지 루프입니다:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
Win32 프로그램의 시작 함수입니다.
hInstance
: 이 프로그램의 instance 핸들 값이 전달됩니다.hPrevInstance
: 현재 사용되지 않는 매개변수 (항상 NULL입니다.)lpCmdLine
: main 함수의 argc, argv 인자처럼 실행 인자가 전달 됨. main 함수처럼 인자들이 배열로 하나씩 나누어져서 전달되는 것이 아니라 하나의 문자열로 전달됩니다. ⇒ 실행 파일은 포함되지 않습니다.Hello soft
라는 문자열이 전달됩니다.nCmdShow
: 응용 프로그램의 초기 시작 형식이 전달됩니다. 보통의 경우 SW_SHOWDEFAULT 값이 전달되며 사용자가 단축 아이콘이나 다른 응용 프로그램에서 특정 값을 지정하면 해당 값이 이 매개변수로 전달됩니다.int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// ... 생략
MyRegisterClass(hInstance);
// ... 생략
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW 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_CLIENT));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_CLIENT);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
윈도우 클래스를 등록하는 부분입니다.
각 Window 단위로 실행 명령어에 대한 중복을 줄이기 위한 개념이 윈도우 클래스이고 해당 클래스의 구조체를 정의 한뒤 RegisterClass 함수를 이용하여등록하는 부분입니다.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// ... 생략
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// ... 생략
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
인스턴스 핸들을 전역 변수에 저장합니다
CreateWindowW 함수를 사용하여 프로그램에서 사용할 윈도우를 생성합니다.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// ... 생략
SG msg;
// 기본 메시지 루프입니다:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// ... 생략
}
Win32 응용 프로그램은 운영체제 또는 다른 응용 프로그램과 메시지를 주고받는 형식으로 진행됩니다.
응용 프로그램은 메시지를 수신할 수 있도록 메시지큐를 가지고 있습니다.
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}
메시지 큐에 전달된 메시지를 읽어올 때 사용하는 구조체입니다.
GetMessage 함수
TranslateMessage 함수
DispatchMessage 함수
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 메뉴 선택을 구문 분석합니다:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Window Procedure를 사용자가 재정의한 함수입니다.
CALLBACK 형태를 따르기 때문에 함수의 원형은 매개변수와 반환형을 사용자가 변경할 수 없지만 함수의 이름이나, 내부 구현은 변경이 가능합니다.해당 함수에서는 사용자가 처리하고 싶은 메시지만 처리하면 됩니다.
필수적으로 처리하면 안되는 메시지를 놓쳐선 안되기 때문에 DefWindowProc 함수를 호출함으로써 내부적으로 정해진 작업을 수행합니다.