본문 바로가기

Win32 api

Win32 api 강의 44 - 45화.

- Tile 클래스 설계.

// CTile.h
#pragma once
#include "CObject.h"        

class CTexture;

class CTile : public CObject
{
private:
    CTexture* m_pTexture;

public:
    virtual void update() override;
    virtual void render(HDC hDC) override;

public:
    CLONE(CTile)
    void SetTexture(CTexture* pTexture) { m_pTexture = pTexture; }

public:
    CTile();
    virtual ~CTile();
};

 

Tool 씬에서 쓸 준비로 Tile 클래스를 간단 설계함.

// CTile.cpp
...
void CTile::render(HDC hDC)
{
    if(!m_pTexture)
    {
        return;
    }

    Vector2 pos = CCamera::GetInstance()->WorldToScreen(GetPos());
    Vector2 size = GetSize();
    
    TransparentBlt(hDC,
        static_cast<int>(pos.x), static_cast<int>(pos.y),
        static_cast<int>(size.x), static_cast<int>(size.y),
        m_pTexture->GetDC(),
        128, 0,
        static_cast<int>(size.x), static_cast<int>(size.y),
        RGB(255, 0, 255));
}

CTile::CTile()
    : CObject()
    , m_pTexture(nullptr)
{
    SetSize(Vector2(TILE_SIZE, TILE_SIZE));
}
...

 

일단 간단하게 로드된 텍스처를 렌더링함. 타일의 좌표를 좀 체계화해서 계산하려면 적당한 타일셋 이미지가 필요할 듯.

임시방편으로 아무 타일셋 이미지를 사용했다.

// CScene_Tool.cpp
...
void CScene_Tool::Enter()
{
    CTexture* pTileTexture = CResourceMgr::GetInstance()->LoadTexture(L"Tileset", L"texture\\Tile\\Tileset_Spring.bmp");

    for (int i = 0; i < 5; ++i)
    {
        for (int j = 0; j < 5; ++j)
        {
            CTile* pTile = new CTile();
            pTile->SetPos(Vector2((float)j * TILE_SIZE, (float)i * TILE_SIZE));
            pTile->SetTexture(pTileTexture);
            AddObject(pTile, GROUP_TYPE::TILE);
        }
    }

    CCamera::GetInstance()->SetTarget(nullptr);
    POINT ptResolution = CCore::GetInstance()->GetResolution();
    CCamera::GetInstance()->SetPosition(Vector2(ptResolution.x / 2.f, ptResolution.y / 2.f));
}

 

Tool 씬에서 해당 텍스처를 로드하고 타일들을 생성해줌. TILE_SIZE 는 그냥 매크로로 16 을 넣어줌. 현재 사용중인 타일 크기임.

 

- Tool 윈도우를 만드는 과정.

먼저 프로젝트의 리소스 뷰에 메뉴바와 메뉴를 추가해준다.

"타일 개수" 메뉴의 ID 값은 IDM_TILECOUNT 라고 지어줌.

또 리소스 뷰에서 Dialog 윈도우도 추가해준다.

 

대충 이런식으로 만들어주고...해당 Dialog 의 ID 값은 IDD_TILECOUNT 라고 지정.

2개의 Edit control 에 ID 값은 IDC_EDIT_TILECOUNTCOLUMN, IDC_EDIT_TILECOUNTROW 라고 지정해줌.

확인/취소 버튼은 IDOK, IDCANCEL 이라고 지정해주자.

 

이러한 ID 값들은 리소스 뷰에서 우클릭 → 리소스 기호 를 눌러보면

 

이렇게 매크로로 지정된 값을 확인할 수 있다. 사용중이지 않은 것은 삭제해도 됨.

아니면 솔루션 탐색기에서 Default → Resource.h 라는 파일을 찾아볼 수 있음. 

// Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++에서 생성한 포함 파일입니다.
// client.rc에서 사용되고 있습니다.
//
#define IDS_APP_TITLE                   103
#define IDD_ABOUTBOX                    103
#define IDM_ABOUT                       104
#define IDM_EXIT                        105
#define IDI_CLIENT                      107
#define IDI_SMALL                       108
#define IDC_CLIENT                      109
#define IDD_TILECOUNT                   130
#define IDC_EDIT_TILECOUNTCOLUMN        1001
#define IDC_EDIT_TILECOUNTROW           1002
#define IDM_TILECOUNT                   32777
#define IDC_STATIC                      -1

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC                     1
#define _APS_NEXT_RESOURCE_VALUE        132
#define _APS_NEXT_COMMAND_VALUE         32780
#define _APS_NEXT_CONTROL_VALUE         1005
#define _APS_NEXT_SYMED_VALUE           110
#endif
#endif

 

이런식으로 파일에 정의되어 있는 것을 수정할 수 있다. 다만 사용중인 ID 값은 자동으로 채워지는 모양.

 

이제 CScene_Tool.cpp 파일로 가서

// CScene_Tool.cpp
...
#pragma region tile count input dialog
INT_PTR CALLBACK TileCountInputProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
#pragma endregion

 

간단하게 확인/취소 버튼이 눌리면 닫히는 콜백 함수를 만들어주고

main.cpp 파일로 가서

// main.cpp
...
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    TileCountInputProc(HWND, UINT, WPARAM, LPARAM);	// 추가.

 

이런식으로 해당 함수를 전방 선언해준다.

// main.cpp
...
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;
            // 추가.
            case IDM_TILECOUNT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_TILECOUNT), hWnd, TileCountInputProc);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
...

 

WndProc 함수에 해당 코드를 추가해줌. IDM_ABOUT 이 기존에 자동으로 만들어진 정보 창이다.

이것과 똑같이 만들어둠.

 

이제 실행해서

메뉴를 클릭하면!

 

만들어둔 콜백 함수로 들어오는 것을 확인.

게임 실행 중 윈도우가 생성된다. 확인 버튼을 누르면

 

IDOK 값이 들어오면서 걸리는 것도 확인.

 

이제 이 콜백 함수에서 원하는 기능을 구현해보자.

'Win32 api' 카테고리의 다른 글

Win32 api 강의 47화.  (0) 2025.09.24
Win32 api 강의 46화.  (0) 2025.09.24
Win32 api 강의 43화.  (0) 2025.09.23
Win32 api 강의 41 - 42화.  (0) 2025.09.23
Win32 api 강의 39 - 40화.  (0) 2025.09.22