일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Win32
- c++
- 포인터
- 지식나눔강좌
- Direct2D
- 알고리즘
- Programming
- Desktop
- Tips강좌
- 함수
- CS
- 리뷰
- 김성엽
- 이지스퍼블리싱
- Visual Studio
- Windows
- c
- 배열
- doit코틀린프로그래밍
- c#
- 티스토리
- 백준
- 연산자
- Kotlin
- tipssoft
- VS ERROR
- Javascript
- 문법
- Tips프로그래밍강좌
- 프로그래밍
- Yesterday
- Today
- Total
F.R.I.D.A.Y.
Win32 프로그램 생성하기 5 본문
윈도우 프로시저를 이제 작성해보겠습니다.
윈도우 프로시저
윈도우 프로시저는 Windows에서 수신한 정보를 토대로 그에 알맞은 행동을 정의해놓은 공간이라고 생각할 수 있습니다. 윈도우 프로시저는 아래의 모양을 가지고 있습니다.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
뭐 하나 알만한 것이 없습니다. 그렇지만 차근차근 알아가면 못할 것도 없죠. 함수의 자세한 설명은 이 포스트를 참고하세요. 작성하면 기본으로 반환해줄 값이 하나 있습니다. DefWindowProc 함수를 이용하는 것인데요.
DefWindowProc
윈도우에서는 기본으로 처리하는 작업이 있습니다. 윈도우의 이동이 타이틀바에 존재하는 시스템 메뉴[# 최대/최소화 버튼, 창닫기 버튼]의 행동을 담당하는 것들이 있죠. 원래대로라면 이런 작업도 전부 우리 개발자가 담당해서 개발해야하는 내용입니다. 그렇지만 공통적인 부분이기 때문에 Windows에서는 DefWindowProc라는 함수를 이용해 기본 사항들을 처리할 수 있게 됩니다.
LRESULT LRESULT DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
구조는 윈도우 프로시저와 동일합니다. 윈도우의 기본적인 부분을 담당하는 함수이다보니, 프로시저의 공통작업을 그대로 엮어온 것이라고 보면 되겠습니다.
필수 처리할 메시지
이렇게 만들면 다음은 필수 처리할 메시지를 알아보겠습니다.
WM_CLOSE
시스템 메뉴의 창닫기 버튼을 클릭하는 등 윈도우를 닫으려 할 때 발생하는 이벤트입니다. 이 메시지가 들어온 시점에서는 윈도우를 닫을 것인지 선택할 수 있습니다. 이 메시지에 대한 자세한 내용은 다음 문서를 참고하세요.
WM_DESTROY
이 메시지가 들어온 시점에는 윈도우를 닫을 것인지 말 것인지는 결정할 수 없습니다. 이미 윈도우를 없애겠다고 선언된 시점이기 때문입니다. 대신 이 시점엔 완전히 파괴되기 전에 할 작업을 처리할 수 있습니다. 예컨데 프로그램에서 수정된 파일을 임시 저장하는 것입니다.
프로시저 구성하기
프로시저는 이렇게 구성할 수 있습니다.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE:{
PostQuitMessage(0);
return 0;
}
case WM_DESTROY: {
DestroyWindow(hwnd);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
저는 주로 switch 구문을 활용해 프로시저를 구성합니다. if 구문에 비해서 편하니까요.
엔트리 포인트에 바인딩하기
이전 엔트리 포인트를 작성할 때 남겨둔 부분이 있습니다.
wc.lpfnWndProc = nullptr;
이 부분의 nullptr을 WindowProc로 변경해줍니다.
wc.lpfnWndProc = WindowProc;
중간 점검
여태 작성한 코드를 나열하면 다음과 같습니다.
# 중간 코드 점검
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE:{
PostQuitMessage(0);
return 0;
}
case WM_DESTROY: {
DestroyWindow(hwnd);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nCmdShow) {
WNDCLASS wc{};
wc.lpfnWndProc = nullptr;
wc.lpszClassName = L"Hello world";
wc.hInstance = hInstance;
RegisterClass(&wc);
HWND hWnd = CreateWindow(L"Hello world", L"My First Win32 Program", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd) return -1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
코드 다듬기
실행하고 기본 작업을 살펴보겠습니다. 사이즈 조정을 한번 해보세요. 어떻게 되나요?
조정을 하면 이렇게 검은 칸이 생길 수 있습니다. 줄였다 늘리면 하얀색 공간이 줄어들기도 하구요. 사이즈 조절하고 나서 마우스 커서를 보면 다시 화살표로 돌아오지 않을 수도 있습니다.
우리가 WNDCLASS 등록을 할 때 비워두었던 속성이 있습니다.
wc.hCursor;
wc.hbrBackground;
다른 항목도 있지만 여기에서는 이 두 항목이 문제의 원입니다. 아무것도 지정하지 않았으니 이리 되는 것입니다. 아래처럼 wc 초기화에 코드를 추가해 등록하겠습니다.
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = L"Hello world";
wc.hInstance = hInstance;
// 추가된 항목
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
이제 크기를 늘리거나 줄여도 정상적으로 출력이 되는 것을 알 수 있습니다.
최종 코드
# 최종 코드
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE:{
PostQuitMessage(0);
return 0;
}
case WM_DESTROY: {
DestroyWindow(hwnd);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nCmdShow) {
WNDCLASS wc{};
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = L"Hello world";
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
RegisterClass(&wc);
HWND hWnd = CreateWindow(L"Hello world", L"My First Win32 Program", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd) return -1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
이것으로 Win32 프로그래밍을 위한 기본적인 틀이 잡혔습니다. 다음으로는 Window Hello의 사진암호와 비슷한 실행을 가지는 프로그램을 구현해보겠습니다.
# index
'DEV > C C++' 카테고리의 다른 글
Win32 프로그램 생성하기 7: 사진 암호 part2. 마우스 입력 (0) | 2021.04.03 |
---|---|
Win32 프로그램 생성하기 6: 사진 암호 part1. 격자 생성 (0) | 2021.04.02 |
Win32 프로그램 생성하기 4 (2) | 2021.04.02 |
Win32 프로그램 생성하기 3 (0) | 2021.04.02 |
Win32 프로그램 생성하기 2 (0) | 2021.04.01 |