https://docs.microsoft.com/ko-kr/windows/win32/learnwin32/your-first-windows-program
์ ๋ด์ฉ์ ์ฐธ๊ณ ํ์ฌ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค.
๋ชจ๋1. ์ฒซ ๋ฒ์งธ Windows ํ๋ก๊ทธ๋จ
4) ์ฐฝ ๊ทธ๋ฆฌ๊ธฐ
5) ์ฐฝ ๋ซ๊ธฐ
6) ์ดํ๋ฆฌ์ผ์ด์
์ํ ๊ด๋ฆฌ
์ฐฝ์ ์ฒ์ ํ์ํ ๋๋, ์ฐฝ์ ์ผ๋ถ๋ฅผ ๋ค์ ๊ทธ๋ ค์ผ ํ ๋ ์ด์์ฒด์ ๋ ์ฐฝ์ WM_PAINT ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ธ๋ค.
์ฐ๋ฆฌ๋ ์ฌ๊ธฐ์ Client Area๋ง ๊ทธ๋ฆฌ๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ฐ์ดํธ ์์ญ์ด ๋จ์์๋ ๋์์๋ ๋ค๋ฅธ WM_PAINT ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ผ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ์ด์์ฒด์ ์๊ฒ ์๋ฆฐ๋ค. ์ด ์ ๋ฐ์ดํธ ์์ญ์ ํด๋ผ์ด์ธํธ ์์ญ ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ ํ ์ง์ฐ๋ฉด ๋๋ค.
๋ค๋ฅธ ์ฐฝ์ผ๋ก ์ฐฝ์ ์ผ๋ถ๋ฅผ ๊ฐ๋ ธ๋ค๊ฐ ๋ค์ ๋ณด์ด๊ฒ ๋ ์ํฉ์์๋ ํด๋น ๋ถ๋ถ์ด ์ ๋ฐ์ดํธ ์์ญ์ ์ถ๊ฐ๋๊ณ ์ฐฝ์ ๋ค๋ฅธ WM_PAINT ๋ฉ์ธ์ง๊ฐ ํ์๋๋ค.
์ฐฝ์ ๋์ด๋ ๊ฒฝ์ฐ์๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค.
๐ ์ ์ฒด ํด๋ผ์ด์ธํธ ์์ญ ๋จ์์ผ๋ก ์ฑ์ฐ๊ธฐ
switch (uMsg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
1) BeginPaint ํจ์๋ฅผ ํธ์ถํ์ฌ ๊ทธ๋ฆฌ๊ธฐ ์์
์์
: PAINTSTRUCT ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฒญ์ ๋ํ ์ ๋ณด๋ก ์ฑ์ฐ๋ ํจ์
2) ํ์ฌ ์
๋ฐ์ดํธ ์์ญ์ PAINTSTRUCT์ rcPaint ๋ฉค๋ฒ์ ์ ์ฅ
(์
๋ฐ์ดํธ ์์ญ์ ํด๋ผ์ด์ธํธ ์์ญ ๊ธฐ์ค)
3) FillRect๋ก ์์คํ ์ ์ ์ฐฝ ๋ฐฐ๊ฒฝ์์ ์ด์ฉํ์ฌ ์ ๋ฐ์ดํธ ์์ญ์ ๋จ์ผ ์์ผ๋ก ์ฑ์ฐ๊ธฐ
4) ๊ทธ๋ฆฌ๊ธฐ ์์ ์ด ์๋ฃ๋๋ฉด EndPaint ํธ์ถ
๐ FillRect
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
๋๋ฒ์งธ ๋งค๊ฐ๋ณ์ : ์ฑ์ธ ์ฌ๊ฐํ์ ์ขํ
์ฌ๊ธฐ์๋ PAINTSTRUCT์ rcPaint ๋ฉค๋ฒ์ด๋ฉฐ rcPaint์๋ ์ ์ฒด ํด๋ผ์ด์ธํธ ์์ญ์ด ํฌํจ๋๋ค.
์ฌ์ฉ์๊ฐ ์ฐฝ์ ๋ซ์ผ๋ฉด ์ฐฝ์์ WM_CLOSE ๋ฉ์ธ์ง๊ฐ ์์ ๋๋ค. WM_CLOSE ๋ฉ์ธ์ง๋ ์ฐฝ์ ๋ซ๊ธฐ ์ ์ ์ฌ์ฉ์์๊ฒ ๋ฉ์ธ์ง๋ฅผ ํ์ํ๋ฉฐ ์ฐฝ์ ๋ซ์ผ๋ ค๋ฉด DestroyWindow ํจ์๋ฅผ ํธ์ถ, ๊ทธ๋ ์ง ์์ผ๋ฉด ์ด์ ์ฒด์ ์์ ๋ฉ์ธ์ง๋ฅผ ๋ฌด์ํ๊ณ ์ฐฝ์ ์ญ์ ํ์ง ์๋๋ค(WM_CLOSE ๋ฉ์ธ์ง๊ฐ 0์ ๋ฐํ)
๐ ํ๋ก๊ทธ๋จ์ด WM_CLOSE๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ
case WM_CLOSE:
if (MessageBox(hwnd, L"Really quit?", L"My application", MB_OKCANCEL) == IDOK)
{
DestroyWindow(hwnd);
}
// Else: User canceled. Do nothing.
return 0;
์ด ๊ฒฝ์ฐ ์ฌ์ฉ์๊ฐ ํ์ธ(OK)์ ํด๋ฆญํ๋ฉด ํ๋ก๊ทธ๋จ์์ DestroyWindow๋ฅผ ํธ์ถํ๊ณ , ๊ทธ๋ ์ง ์๊ณ ์ทจ์(Cancle)์ ํด๋ฆญํ๋ฉด ํธ์ถ์ ๊ฑด๋๋ฐ๊ณ ์ฐฝ์ด ์ด๋ฆฐ ์ํ๋ก ์ ์ง๋๋ค.
์ฌ์ฉ์์๊ฒ ๋ฉ์ธ์ง๋ฅผ ํ์ํ์ง ์๊ณ ์ฐฝ์ ๋ซ์ผ๋ ค๋ฉด DefWindowProc์ ์ด์ฉํ ์ ์๋ค. WM_CLOSE์ ๊ฒฝ์ฐ DefWindowProc์ DestroyWindow๋ฅผ ์๋์ผ๋ก ํธ์ถํ๋ค.
์ฐฝ์ด ์ ๊ฑฐ๋ ๋ WM_DESTROY ๋ฉ์ธ์ง๋ฅผ ๋ฐ๋๋ค. ์ด ๋ฉ์ธ์ง๋ ์๋ฉธํ๊ธฐ ์ ์ ์ ์ก๋๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก PostQuitMessage๋ฅผ ํธ์ถํ์ฌ WM_DESTOY์ ์๋ตํ๋ค.
case WM_DESTROY:
PostQuitMessage(0);
return 0;
๐ WM_CLOSE ๋ฐ WM_DESTROY ๋ฉ์ธ์ง๋ฅผ ์ฒ๋ฆฌํ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ
์๋์ฐ ํ๋ก์์ ๋ ์ํ๊ฐ ์ ์ฅ๋์ง ์๊ธฐ ๋๋ฌธ์ ํ ํจ์ ํธ์ถ์์ ๋ค์ ํจ์ ํธ์ถ๋ก ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ์ถ์ ํ๋ ๋ฐฉ๋ฒ์ด ํ์ํ๋ค.
๐ ์ ์ญ ๋ณ์์ ๋ชจ๋ ๋ฐฐ์น
์๊ท๋ชจ ํ๋ก๊ทธ๋จ์์ good.
๋๊ท๋ชจ์์๋ ์ข์ง์๋ค. (์๋์ฐ ํ๋ก์์ ๊ฐ ๋ง๋ค, ์ ์ญ ๋ณ์ ํ์ฐ)
๐ CreateWindowEx ํจ์
๋ชจ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฐฝ์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค. ์ด ํจ์๊ฐ ํธ์ถ๋๋ฉด ์๋์ฐ ํ๋ก์์ ์ ๋ค์ ๋ ๊ฐ์ ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ธ๋ค.
์ด ๋ ๋ฉ์ธ์ง๋ ์ฐฝ์ด ํ์๋๊ธฐ ์ ์ ์ ์ก๋๋ค.
CreateWindowEx์ ๋ง์ง๋ง ๋งค๊ฐ ๋ณ์๋ void* ํ์์ ํฌ์ธํฐ์ด๋ค.
์ด์ ์ด ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ดํ๋ฆฌ์ผ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ฐฝ์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
1) ์ํ ์ ๋ณด๋ฅผ ๋ณด์ ํ๋ ํด๋์ค ๋๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ๋ค.
struct StateInfo { };
2) CreateWindowEx๋ฅผ ํธ์ถํ๋ ๊ฒฝ์ฐ ์ต์ข void* ๋งค๊ฐ ๋ณ์์์ ์ด ๊ตฌ์กฐ์ฒด์ ๋ํ ํฌ์ธํฐ๋ฅผ ์ ๋ฌ
StateInfo *pState = new (std::nothrow) StateInfo;
if (pState == NULL)
{
return 0;
}
// Initialize the structure members (not shown).
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
pState // Additional application data
);
WM_NCCREATE ๋ฐ WM_CREATE ๊ฐ ๋ฉ์ธ์ง์ lParam ๋งค๊ฐ ๋ณ์๋ CREATESTRUCT ๊ตฌ์กฐ์ฒด์ ๋ํ ํฌ์ธํฐ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด CREATETRUCT ๊ตฌ์กฐ์ฒด์๋ CreateWindowEx์ ์ ๋ฌํ ํฌ์ธํฐ๊ฐ ํฌํจ๋์ด ์๋ค.
๐ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ ํฌ์ธํฐ ์ถ์ถ
1) lParam ๋งค๊ฐ ๋ณ์๋ฅผ ์บ์คํ ํ์ฌ CREATESTRUCT ๊ตฌ์กฐ์ฒด ์ป๊ธฐ
CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
2) lpCreateParams๋ฅผ ์บ์คํ ํ์ฌ ์ฌ์ฉ์ ๊ณ ์ ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ ํฌ์ธํฐ ์ป๊ธฐ
pState = reinterpret_cast<StateInfo*>(pCreate->lpCreateParams);
3) SetWindowLongPtr ํจ์๋ฅผ ํธ์ถํ๊ณ ํฌ์ธํฐ๋ฅผ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ ๋ฌ
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pState);
: ์ด๋ ๊ฒ ํ๋ฉด ํญ์ GetWindowLongPtr์ ํธ์ถํ์ฌ ์ฐฝ์์ ํฌ์ธํฐ๋ฅผ ๋ค์ ์ป์ ์ ์๋ค.
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
StateInfo *pState = reinterpret_cast<StateInfo*>(ptr);
์ด ๋ฐฉ๋ฒ์ ํด๋์ค์ ์ฐฝ์ 2๊ฐ ์ด์ ๋ง๋๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๋ค. GetWindwoLongPtr์ ํธ์ถ์ ์์ ๋์ฐ๋ฏธ ํจ์๋ก ๋ํํ๋ ๊ฒ์ด ํธ๋ฆฌํ๋ค.
inline StateInfo* GetAppState(HWND hwnd)
{
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
StateInfo *pState = reinterpret_cast<StateInfo*>(ptr);
return pState;
}
๐ ์ต์ข ์ ์ผ๋ก ์์ฑํ ์๋์ฐ ํ๋ก์์
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
StateInfo *pState;
if (uMsg == WM_CREATE)
{
CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
pState = reinterpret_cast<StateInfo*>(pCreate->lpCreateParams);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pState);
}
else
{
pState = GetAppState(hwnd);
}
switch (uMsg)
{
// Remainder of the window procedure not shown ...
}
return TRUE;
}