๐Ÿ“˜ Windows - ์ฐฝ (2)

ํŒŒ์ธยท2022๋…„ 2์›” 3์ผ
0

Windows Programming

๋ชฉ๋ก ๋ณด๊ธฐ
3/3
post-thumbnail

https://docs.microsoft.com/ko-kr/windows/win32/learnwin32/your-first-windows-program

์œ„ ๋‚ด์šฉ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.




๋ชจ๋“ˆ1. ์ฒซ ๋ฒˆ์งธ Windows ํ”„๋กœ๊ทธ๋žจ

4) ์ฐฝ ๊ทธ๋ฆฌ๊ธฐ
5) ์ฐฝ ๋‹ซ๊ธฐ
6) ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ ๊ด€๋ฆฌ




๐Ÿ“ Creating a Window

์ฐฝ์„ ์ฒ˜์Œ ํ‘œ์‹œํ•  ๋•Œ๋‚˜, ์ฐฝ์˜ ์ผ๋ถ€๋ฅผ ๋‹ค์‹œ ๊ทธ๋ ค์•ผ ํ•  ๋•Œ ์šด์˜์ฒด์ œ๋Š” ์ฐฝ์— 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์—๋Š” ์ „์ฒด ํด๋ผ์ด์–ธํŠธ ์˜์—ญ์ด ํฌํ•จ๋œ๋‹ค.




๐Ÿ“ Closing the Window

์‚ฌ์šฉ์ž๊ฐ€ ์ฐฝ์„ ๋‹ซ์œผ๋ฉด ์ฐฝ์—์„œ 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 ๋ฉ”์„ธ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•




๐Ÿ“ Managing Application State

์œˆ๋„์šฐ ํ”„๋กœ์‹œ์ €๋Š” ์ƒํƒœ๊ฐ€ ์ €์žฅ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์—์„œ ๋‹ค์Œ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค.

๐Ÿ”Ž ์ „์—ญ ๋ณ€์ˆ˜์— ๋ชจ๋‘ ๋ฐฐ์น˜

์†Œ๊ทœ๋ชจ ํ”„๋กœ๊ทธ๋žจ์—์„œ good.
๋Œ€๊ทœ๋ชจ์—์„œ๋Š” ์ข‹์ง€์•Š๋‹ค. (์œˆ๋„์šฐ ํ”„๋กœ์‹œ์ €๊ฐ€ ๋งŽ๋‹ค, ์ „์—ญ ๋ณ€์ˆ˜ ํ™•์‚ฐ)

๐Ÿ”Ž CreateWindowEx ํ•จ์ˆ˜

๋ชจ๋“  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ฐฝ์— ์ „๋‹ฌํ•œ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์œˆ๋„์šฐ ํ”„๋กœ์‹œ์ €์— ๋‹ค์Œ ๋‘ ๊ฐœ์˜ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ธ๋‹ค.

  • WM_NCCREATE
  • WM_CREATE

์ด ๋‘ ๋ฉ”์„ธ์ง€๋Š” ์ฐฝ์ด ํ‘œ์‹œ๋˜๊ธฐ ์ „์— ์ „์†ก๋œ๋‹ค.

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;
}

profile
๊ณต๋ถ€์ •๋ฆฌ์šฉ

0๊ฐœ์˜ ๋Œ“๊ธ€