먼저 UnitTool(유닛의 정보가 들어가있는)로 사용할 클래스를 하나와

UnitTool 창을 띄워줄 클래스(MyFormView) 하나를 만들어준다.

 

MyFormView의 기본 클래스는 CFormView로 지정하고,

UnitTool의 기본 클래스는 CDialog로 지정해준다.

 

 

클래스를 만들고나서 Ctrl + Alt + E를 눌러서 리소스 뷰를 띄워준다.

그 다음 Dialog 폴더에 있는 IDD_UNITTOOL을 더블클릭하면 다음과 같은 화면이 나온다.

 

여기까지 완료하였으면 Ctrl + Alt + X를 눌러서 도구 상자를 띄우고

도구 상자 안에있는 Button을 드래그해서 UNITTOOL 뷰에 옮긴다.

우리가 도구 상자에서 사용할 것은 몇개 되지 않기때문에 사용할 도구들의 의미에 대해서만 설명하려고한다.

 

Button : 버튼

Check Box : 체크 박스

Edit Control : 입력란

List Box : 정보를 표시해줄 공간

Radio Button : 동그란 체크 박스

Static Text

-> 아래에 Static으로 적혀있는 Text 도구인데 우측에 있는 입력란에 어떤 정보가 들어갈지 모른다.

-> 우측에 어떠한 정보가 들어가 있는지 알려주기 위해 표시하는 역할

도구의 이름은 한 번만 클릭하고 타자를 입력해서 변경하면 된다.

여기서 주의해야 할 점은 만약 더블 클릭을 하게 되면, 버튼에 대한 이벤트 처리기 함수가 자동으로 생성되기 때문에

원하지 않은 이벤트 처리기 함수가 추가될 경우 해당 함수가 추가된 클래스에 찾아가서

관련된 함수들을 전부 지워줘야되는 번거로움이 생기므로 주의하는 것이 좋다.

 

일단 Button1로 되어있는 이름을 Add라고 지어준다.

 

그 다음 해당 버튼이 클릭되어 있는 상태에서 오른쪽 마우스를 클릭하여 이벤트 처리기 추가를 클릭한다.

그럼 다음과 같은 창이 나올 것이다.

여기서 메시지 형식에 BN_CLIKED라고 나와있는데 이것은 버튼을 클릭 했을 때 이벤트를 발생 시킨다는 의미이다.

클래스 목록은 이벤트 처리기 함수를 추가하고싶은 클래스를 선택하는 곳이다.

함수 처리기 이름은 개인이 변경하고 싶은 함수명이 없으면 자동으로 기본 값으로 세팅이 된다.

변경할 것이 없다면 위에 상태에서 추가를 눌러준다.

 

추가를 누르게되면 다음과 같이 UnitTool 클래스에 함수가 추가된 것을 볼 수 있다.

버튼이 제대로 동작하는지 테스트를 해보자

정상적으로 나온 것을 확인할 수 있다.

 

이제 UnitTool 창을 MyFormView의 버튼을 통해서 나오도록 해보려고 한다.

 

우선 MyFormView의 버튼이 화면에 나오게 해야한다.

이전에 미니맵을 생성했을 때 사용한 Splitter를 이용해서 창 분할을 하였는데,

똑같은 방식으로 분할하여 그 위치에 표시되도록 한다.

 

MainFrame 클래스 -> OnCreateClient 함수

여기까지 하였으면 다음과 같이 정상적으로 버튼이 화면에 표시되는 것을 볼 수 있다.

 

이제 클래스뷰에서 MyFormView 클래스를 클릭하고 Alt + Enter를 눌러서 속성에 들어간 후

OnInitialUpdate 함수를 재정의해준다.

그리고 MyFormView 헤더로 가서 CUnitTool 변수를 만들어준다.

 

그 후에 만들어준 이벤트 처리기 함수에 다음과 같이 정의한다.

여기서 ShowWindow는 MyFormView에서 만든 버튼을 클릭했을 때 UnitTool의 창을 띄워주기 위해 사용하는 함수이다.

OnInitialUpdate 함수에서 Create함수는 인자에 들어간 ID로 만들어져 있는 클래스의 창을 만들어주는 역할을 한다.

아이디는 리소스 뷰에서 다음과 같이 확인할 수 있다.

여기까지 했으면 MyFormView에서 만든 버튼을 클릭 했을 때 정상적으로 ToolView의 창이 나오는 것을 확인할 수 있다.

이 다음은 UnitTool Part2에서 이어서 작성하도록하겠다.

'Programming > MFC' 카테고리의 다른 글

MFC - UnitTool Part2(리스트에 정보 추가 및 삭제)  (0) 2020.12.05
MFC - 미니맵  (1) 2020.11.29
MFC - 기본 이론 , 계층 구조  (0) 2020.11.29
MFC - 타일 픽킹(내적)  (0) 2020.11.29
MFC - 타일 픽킹(직선의 방정식)  (0) 2020.11.25

 

1. MFC란 ?

MFC(Microsoft Foundation Class)

윈도우 어플리케이션(Window Application)을 생성하기 위해 만들어진 C++ 클래스 라이브러리이다.

대부분의 클래스들은 C++ 언어를 확장(wrapper)하여 만들어졌으며,

이는 개발자로 하여금 손쉬운 GUI 기반의 프로그램 제작 환경을 만들어 주었다.

 

MFC를 이용하여 프로그램을 개발함으로써 얻을 수 있는 이점으로는 크게 두 가지로 생각해 볼 수 있다.

첫 번째로 프로그램 개발 시간을 크게 단축시켜 줌으로써 기존의 Win32 API를 이용한 프로그램 제작할 때,

개발자 스스로가 도맡아 해오던 수많은 실행 함수에 대한 코딩의 번거로움을 개선해주었다.

두 번째로는 ActiveX, OLE 등 다양한 인터페이스의 기본 제공으로  손쉬운 프로그래밍을 가능하게 해주었다는 점이다.

 

MFC 프로그램은

크게 단일 윈도우(SDI : Single Document Interface) 와 다중 윈도우(MDI : Multiple Document Interface)로 나눌 수 있다.

아래 그림은 SDI에 대한 기본 구조로써,

MFC는 기본적으로 네 개의 클래스가 모여 하나의 윈도우를 생성함을 알 수 있다.

#1. CFrameWnd

-> 윈도우의 외곽 경계를 담당

-> 메뉴, 툴바, 상태바를 가지고 있음

 

#2. CVIew

-> 실제 화면 처리를 담당

-> 문자 출력, 그래픽 출력 등

 

#3. CDocument

->디스크에서 데이터를 읽고 저장

 

여기까지 MFC 이론에 대해서 살짝 정리를 해보았고,

 

다음은 MFC 계층 구조이다.

 

계층 구조

#1. CObject 클래스(최상위 클래스)

메모리에 클래스를 설정하는 기능

클래스를 할당하기 위해 new 연산자가 오버로딩 된다.

/MFC/Include/Afx.h 설정

클래스의 기능과 종류를   있는 함수가 있다.

- IsSerializable() : 현재 클래스가 데이터를 디스크에 저장할  있는 기능을 자지고 있는지 없는지를 확인하는 함수

- AssertValid( ) : 현재 클래스가 유효한 클래스인가를 확인하는 함수

- Dump() : 현재 클래스의 상태를 확인하는 함수

디버깅할   함수를 이용하여 데이터의 상태를 확인하고 오류를 정리할  있음

 

#2. CCmdTarget클래스

메시지 전송을 담당하는 클래스

실질적으로 메시지를 처리하는 것이 아니라WM_COMMAND OLE 메시지만 담당

 

#3. CWnd 클래스

화면에 보이는 윈도우들은 모두 CWnd 에서 상속 받음

가장 많이 사용되는 클래스

윈도우의 최상위 클래스

상속해서 사용하지 직접 CWnd 클래스를 사용하지는 않는다.

 

#4. CWndThread 클래스

윈도우가 스레드로 돌아갈  있도록 구동 되는 클래스

- 스레드는 독립적인 형태로 구동 되는 하나의 모듈

 개의 프로그램을 독립적으로 움직이려면  개의 프로그램은   이상의 CWinThread 포함해야 한다

- Multi-tasking 가능

 

#5. CWndApp 클래스

 개의 프로그램을 포함하고 관장하는 클래스

 

#6. CDocument 클래스

데이터를 디스크에서 읽어 들이거나 디스크에 저장하는 부분을 담당하는 클래스

주로 알고리즘을 저장

나중에 다른 프로그램에서 재사용이 용이

 

#7. CWnd를 상속 받은 기타 클래스

CFrameWnd : 프레임 형태의 윈도우

CControlBar : 컨트롤바

CPrepertySheet : 프로퍼티 시트

CDialog : 대화 상자

CView : View 윈도우

Control Class : 각종 컨트롤들

'Programming > MFC' 카테고리의 다른 글

MFC - 미니맵  (1) 2020.11.29
MFC - UnitTool Part1(기본 구성), 이벤트 처리기  (0) 2020.11.29
MFC - 타일 픽킹(내적)  (0) 2020.11.29
MFC - 타일 픽킹(직선의 방정식)  (0) 2020.11.25
MFC - 타일 배치  (0) 2020.11.25

이전에 직선의 방정식을 통하여 타일 픽킹을 해보았는데,

이번에는 조금 더 편하게 내적을 통해 타일 픽킹을 해보자.

 

#1. 마름모꼴 구하기

D3DXVECTOR3 vVertex[4] = 
{
	{m_vecTile[iIndex]->vPos.x, m_vecTile[iIndex]->vPos.y + (TILECY * 0.5f), 0.f},
	{m_vecTile[iIndex]->vPos.x + (TILECX * 0.5f), m_vecTile[iIndex]->vPos.y, 0.f},
	{ m_vecTile[iIndex]->vPos.x, m_vecTile[iIndex]->vPos.y - (TILECY * 0.5f), 0.f },
	{ m_vecTile[iIndex]->vPos.x - (TILECX * 0.5f), m_vecTile[iIndex]->vPos.y, 0.f },
}; 

 

#2. 마름모꼴의 방향벡터

D3DXVECTOR3 vVertexDir[4] = 
{		
	vVertex[1] - vVertex[0],
	vVertex[2] - vVertex[1],
	vVertex[3] - vVertex[2],
	vVertex[0] - vVertex[3],
};

 

#3. 법선벡터 뽑아내기

D3DXVECTOR3 vNormalVector[4] = 
{	
	{ -vVertexDir[0].y, vVertexDir[0].x, 0.f },
	{ -vVertexDir[1].y, vVertexDir[1].x, 0.f },
	{ -vVertexDir[2].y, vVertexDir[2].x, 0.f },
	{ -vVertexDir[3].y, vVertexDir[3].x, 0.f }
}; 

 

#4. 마지막으로 마름모꼴 정점에서 마우스를 바라보는 방향벡터를 구하기

D3DXVECTOR3 vMouseDir[4]; 
for (int i = 0 ; i < 4 ; ++i)
	vMouseDir[i] = vPos - vVertex[i];

for (int i = 0 ; i < 4 ; ++i)
{
	D3DXVec3Normalize(&vNormalVector[i], &vNormalVector[i]); 
	D3DXVec3Normalize(&vMouseDir[i], &vMouseDir[i]);
}

for (int i = 0 ; i < 4 ; ++i )
{
	if (0 < D3DXVec3Dot(&vMouseDir[i], &vNormalVector[i]))
		return false; 
}

return true; 

 

타일 픽킹이란 타일을 클릭하였을 때를 말한다.

예를 들어 클릭한 타일이 교체된다던지 해당 타일에 충돌 처리 시킨다는 등의 옵션을 넣을 수도 있다.

 

이번에는 해당 타일을 클릭하였을 때 타일의 그림을 교체해보자.

먼저 마우스 포인터가 마름모 꼴로 되어있는 타일의 안에 있는지 확인해야한다.

 

확인하는 방법은 여러가지가 있다.

그 중에서 직선의 방정식을 이용하여 판별하는 방법과 내적을 통해서 판별하는 방법을 알아보겠다.

 

직선의 방정식을 통해 판별하는 방법부터 알아보자.

직선의 방정식 공식을 다음과 같다.

y = ax + b

 

먼저 기울기부터 구해보자.

기울기(a)는 (y의 증가량) / (x의 증가량) 이며, 기울기는 수평선과 평행하면 0이고,

오른쪽 끝이 올라가면 양의 기울기이고 내려가면 음의 기울기를 가진다.

 

즉 x가 증가할 때 그에따른 y값이 증가하면 양의 기울기,

x가 증가할 때 그에따른 y값이 감소하면 음의 기울기,

x값이 증가할 때, y의 값이 변화가 없다면 기울기는 0이 나오게 된다.

float fSlope[4] = 
{
	(TILECY * 0.5f) / (TILECX * 0.5f), 
	-(TILECY * 0.5f) / (TILECX * 0.5f),
	(TILECY * 0.5f) / (TILECX * 0.5f),
	-(TILECY * 0.5f) / (TILECX * 0.5f)
};

 

타일의 Y축 크기 * 0.5 / 타일의 X축 크기 * 0.5

-타일의 Y축 크기 * 0.5 / 타일의 X축 크기 * 0.5

타일의 Y축 크기 * 0.5 / 타일의 X축 크기 * 0.5

-타일의 Y축 크기 * 0.5 / 타일의 X축 크기 * 0.5

 

이렇게 4개의 정점의 기울기를 구하였고,

이제 마름모꼴 정점 4개를 구해보자.

ax = -b x y

 

D3DXVECTOR3 vVertex[4] = 
{
	{m_vecTile[iIndex]->vPos.x, m_vecTile[iIndex]->vPos.y + (TILECY * 0.5f), 0.f},
	{m_vecTile[iIndex]->vPos.x + (TILECX * 0.5f), m_vecTile[iIndex]->vPos.y, 0.f},
	{ m_vecTile[iIndex]->vPos.x, m_vecTile[iIndex]->vPos.y - (TILECY * 0.5f), 0.f },
	{ m_vecTile[iIndex]->vPos.x - (TILECX * 0.5f), m_vecTile[iIndex]->vPos.y, 0.f },
}; 

마름모꼴의 정점은 해당 타일의 중점과 타일의 사이즈를 알고있다는 점을 응용해서 찾아낼 수 있다.

 

 

이제 기울기와, 4개의 정점를 모두 알고 있으므로 마지막으로 b(y 절편)을 구하면된다. 

b = y - ax;

float fY_Intercept[4] = 
{
	vVertex[0].y - fSlope[0] * vVertex[0].x, 
	vVertex[1].y - fSlope[1] * vVertex[1].x,
	vVertex[2].y - fSlope[2] * vVertex[2].x,
	vVertex[3].y - fSlope[3] * vVertex[3].x,
};

0 = ax + b - y

if (0 < fSlope[0] * vPos.x  + fY_Intercept[0] - vPos.y &&
    0 < fSlope[1] * vPos.x + fY_Intercept[1] - vPos.y &&
    0 > fSlope[2] * vPos.x + fY_Intercept[2] - vPos.y &&
    0 > fSlope[3] * vPos.x + fY_Intercept[3] - vPos.y )
{
	return true; 
}

return false;

식이 계산되었으므로, 부등호로 직선보다 위 또는 아래에 있는지 판단하여

위에 있으면 음수 아래에 있으면 양수가 된다.

즉, 클릭한 좌표가 직선 위에 있으면 범위 밖이기 때문에 false가 되고 아래에 있으면 범위 안이므로 true가 된다.

'Programming > MFC' 카테고리의 다른 글

MFC - 기본 이론 , 계층 구조  (0) 2020.11.29
MFC - 타일 픽킹(내적)  (0) 2020.11.29
MFC - 타일 배치  (0) 2020.11.25
MFC - 싱글 텍스처, 멀티 텍스처  (0) 2020.11.22
MFC - 디바이스 초기화  (0) 2020.11.22

+ Recent posts