공부 중 메모/DirectX

1. 윈도우 띄우기

라이피 (Lypi) 2018. 12. 17. 20:35
반응형

# 아무 기능 없이 윈도우만 띄우는 기능까지만 들어간 라이브러리.

# 헤더파일의 DX관련 헤더와 라이브러리는 참조하기 쉽게 위치를 옮겨놨다.

# 실질적인 기능은 zCore파일에서 정의된다. 


stdHeader_L.h

#pragma once
#define DIRECTINPUT_VERSION 0x0800
#define _CRT_SECURE_NO_WARNINGS    
#pragma warning( disable:4005) //매크로 재정의 에러 띄우지 않기.

//#define _DISABLE_EXTENDED_ALIGNED_STORAGE //메모리 자동 정렬 사용 안함?

#pragma region //헤더 파일 및 라이브러리 파일 추가

#include <Windows.h>

#include <wrl.h> //Windows Runtime C++ Template Library //ComPtr사용

#include <tchar.h>
#include <time.h>
#include <cassert>

#include <memory> //스마트 포인터 사용

//stl헤더
#include <set>
#include <list>
#include <map>
#include <vector>
#include <algorithm>
#include <functional>
#include <unordered_map>
#include <iterator>

//dx (순서 주의)
#include "d3dx11.h"  
#include "D3D11.h" 
#include "dxgi.h"
#include "D3Dcompiler.h"
#include "D2D1.h"
#include "D2D1Helper.h"
#include "DWrite.h"
#include "dinput.h"


//라이브러리 포함
#pragma comment (lib, "D3D11.lib")

#if defined(DEBUG) || defined(_DEBUG)
#pragma comment( lib, "d3dx10d.lib" )	
#pragma comment( lib, "d3dx11d.lib" )	
#else
#pragma comment( lib, "d3dx10.lib" )
#pragma comment( lib, "d3dx11.lib" )
#endif

#pragma comment (lib, "dxgi.lib")
#pragma comment (lib, "D3Dcompiler.lib")
#pragma comment (lib, "D2D1.lib")
#pragma comment (lib, "DWrite.lib")
#pragma comment (lib, "dxguid.lib")
#pragma comment (lib, "dinput8.lib")

#pragma endregion

#pragma region //namespace 사용
using namespace std;
using namespace Microsoft::WRL;
using namespace D2D1;
#pragma endregion

namespace Lypi
{
#pragma region	//문자열 타입정의
	typedef basic_string<TCHAR>     T_STR;
	typedef basic_string<wchar_t>   W_STR;
	typedef basic_string<char>      C_STR;
	typedef vector<T_STR>		    T_STR_VECTOR;
#pragma endregion

#pragma region	//매크로
#define str(x) L#x
#define randf(x) (((float)x)*rand()/(float)RAND_MAX) //0~x사이의 랜덤한 실수값을 반환
#define randstep(fMin,fMax) (fMin+randf(fMax-fmin))  //min에서 max까지의 랜덤할 실수값을 반환
#define clamp(x,MinX,MaxX) if (x>MaxX) x=MaxX; else if (x<MinX) x=MinX;  //x값이 min보다 작으면 min으로, max보다 크면 max로 고정시킴.

#define SAFE_NEW(A, B)              { if (!A) A = new B; }                    //A가 널포인트이면 A에 B를 동적할당한다.
#define SAFE_DEL(A)                 { if (A) delete A; (A)=nullptr; }         //A가 널포인트가 아니면 A의 메모리를 해제하고, Nullptr로 설정한다.
#define SAFE_NEW_ARRAY(A, B, C)	    { if (!A && C>0) A = new B[C]; }          //A가 널포인트가 아니고 C가 1이상이면 A에 B를 C개의 배열로 동적할당한다.
#define SAFE_DELETE_ARRAY(A)		{ if (A) delete[] A; (A)=nullptr; }       //A가 널포인트가 아니면 A에 할당된 배열 메모리를 해제하고, nullptr로 설정한다.
#define SAFE_RELEASE(A)				{ if(A) { (A)->Release(); (A)=NULL; } }   //A가 널포인터가 아니면 A를 릴리즈하고 nullptr로 설정한다.

#define V(x)                        { hr = (x); }
#define V_FRETURN(x)                { hr = (x); if( FAILED(hr) ) { return hr; } }


//디버그 메시지 출력용
#define	DEBUGMSG(lpText)\
	{\
		TCHAR szBuffer[256];\
		_stprintf_s(szBuffer, _T("[File: %s][Line: %d]\n[Note : %s]"), _CRT_WIDE(__FILE__), __LINE__, lpText);	\
		MessageBox(NULL, szBuffer, _T("ERROR"), MB_ICONERROR);}



#if defined(DEBUG) | defined(_DEBUG) 
#define H_RETURN(x){ if (FAILED(x)){\
		LPWSTR output;\
		WCHAR buffer[256]={0,};\
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_ALLOCATE_BUFFER,\
		NULL,x,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&output,0,NULL);\
		wsprintf(buffer,L"File=%s\nLine=%s", str(__FILE__),str(__LINE__));\
		MessageBox(NULL, buffer,output,MB_OK); return hr;}\
	}

#define H(x){ if (FAILED(x)){\
		LPWSTR output;\
		WCHAR buffer[256]={0,};\
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_ALLOCATE_BUFFER,\
		NULL,x,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&output,0,NULL);\
		wsprintf(buffer,L"File=%s\nLine=%s", str(__FILE__),str(__LINE__));\
		MessageBox(NULL, buffer,output,MB_OK);}\
	}

#else
#define H_RETURN(x) (x)
#define H(x) (x)
#endif

#pragma endregion

#pragma region //외부변수 정의
	class winL;

	//device_DX
	extern ID3D11Device*             g_pD3dDevice;
	extern ID3D11DeviceContext*      g_pD3dContext;
	extern IDXGISwapChain*           g_pSwapChain;
	extern ID3D11RenderTargetView*   g_pRenderTagetView;	
	extern ID3D11DepthStencilView*   g_pDepthStencilView;  
	extern D3D11_VIEWPORT            g_d3dViewPort;		   

	//WndC_DX
	extern HINSTANCE    g_hInst;      //윈도우의 인스턴스 핸들값
	extern HWND         g_hWnd;       //생성된 윈도우의 핸들값
	extern RECT         g_rtWindow;   //윈도우 영역
	extern RECT         g_rtClient;   //클라이언트 영역 (작업영역)
	extern winL*        g_pWindow;    //현재 생성된 윈도우에 대한 포인터

	extern float        g_dSPF;       //SPF


}

DxDevice.h

#pragma once
#include "stdHeader_L.h"

namespace Lypi
{
	class DxDevice
	{
	protected:
		ID3D11Device*              m_pD3dDevice;           // 디바이스 객체
		ID3D11DeviceContext*       m_pD3dContext;          // 디바이스 컨텍스트 객체
		IDXGISwapChain*            m_pSwapChain;           // 스왑체인 객체

		D3D_DRIVER_TYPE            m_d3dDriverType;        // 디바이스 타입 (디폴트 : 하드웨어 가속)
		D3D_FEATURE_LEVEL          m_d3dFeatureLevel;	   // DX의 기능 수준

		IDXGIFactory*              m_pGIFactory;		   // DXGI 객체
		ID3D11RenderTargetView*    m_pRenderTagetView;	   // 메인 렌더타켓 뷰
		ID3D11DepthStencilView*    m_pDepthStencilView;    // 깊이 스텐실 뷰

		D3D11_VIEWPORT             m_d3dViewPort;		   // 뷰 포트

	protected:
		//디바이스 생성
		HRESULT InitDevice();                   // 장치를 순서대로 생성한다.

		HRESULT CreateDevice();                 // 디바이스 및 디바이스 컨텍스트를 생성한다.
		HRESULT	CreateGIFactory();	 			// IDXGIFactory 객체 생성
		HRESULT	CreateSwapChain();	            // IDXGIFactory를 이용하여 스왑체인 생성
		HRESULT CreateDpethStencilView();       // 깊이 스텐실 뷰 생성
		
		HRESULT	SetRenderTargetView();	// 타겟 뷰 설정
		HRESULT	SetViewPort();     		// 뷰 포트 설정

	protected:
		bool CreanupDevice();      // 생성한 것을 역순으로 삭제한다.

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

DxDevice.cpp

#include "DxDevice.h"

namespace Lypi
{
	ID3D11Device*              g_pD3dDevice;           // 디바이스 객체
	ID3D11DeviceContext*       g_pD3dContext;	       // 디바이스 컨텍스트
	IDXGISwapChain*            g_pSwapChain;		   // 스왑체인 객체
	ID3D11RenderTargetView*    g_pRenderTagetView;     // 메인 렌더타켓뷰 정보 얻기
	ID3D11DepthStencilView*    g_pDepthStencilView;    // 깊이 스텐실 정보 얻기
	D3D11_VIEWPORT             g_d3dViewPort;          // 뷰포트 정보 얻기

	DxDevice::DxDevice()
	{
		//어댑터(그래픽카드)를 사용하여 디바이스 객체를 생성해야 하므로 NULL로 선택.
		m_d3dDriverType = D3D_DRIVER_TYPE_NULL;

		//쉐이더5.0을 사용해야 하므로 11을 선택.
		m_d3dFeatureLevel = D3D_FEATURE_LEVEL_11_0;

		//선언 후 생성 전 초기화. 
		m_pD3dDevice = nullptr;
		m_pD3dContext = nullptr;
		m_pGIFactory = nullptr;
		m_pSwapChain = nullptr;

		m_pRenderTagetView = nullptr;
		m_pDepthStencilView = nullptr;
	}

#pragma region //디바이스 생성
	//ID3D11Device 인터페이스를 생성한다.
	HRESULT DxDevice::CreateDevice()
	{
		HRESULT hr;
		//d2d를 쓰려면 이 플래그를 써야함.
		UINT uCreateDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;  //디바이스 생성 플래그

		#if defined(DEBUG) || defined(_DEBUG)
		uCreateDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
		#endif
		//디바이스 생성 타입
		D3D_DRIVER_TYPE dxDriverTypes[] =
		{
			D3D_DRIVER_TYPE_UNKNOWN,    //디바이스 객체를 생성할 수 있는 최상의 드라이브 타입이 자동적으로 선택된다는데...?
			D3D_DRIVER_TYPE_HARDWARE,   //최선
			D3D_DRIVER_TYPE_WARP,       //차선
			D3D_DRIVER_TYPE_REFERENCE   //최악 (그래픽 카드가 안 받쳐줄때 개발용으로 사용)
		};
		UINT uNumDriverTypes = sizeof(dxDriverTypes) / sizeof(dxDriverTypes[0]);

		//선택될 수 있는 피처레벨 배열
		D3D_FEATURE_LEVEL dxFeatureLevels[] =
		{
			D3D_FEATURE_LEVEL_11_0,
			D3D_FEATURE_LEVEL_10_1,
			D3D_FEATURE_LEVEL_10_0,
			D3D_FEATURE_LEVEL_9_3,
		};
		UINT uNumFeatureLevels = sizeof(dxFeatureLevels) / sizeof(dxFeatureLevels[0]);

		//피쳐레벨이 11로 생성될 때까지 돌리기 위한 반복문
		for (UINT uDriverTypeIndex = 0; uDriverTypeIndex < uNumDriverTypes; uDriverTypeIndex++) {

			m_d3dDriverType = dxDriverTypes[uDriverTypeIndex];

			hr = D3D11CreateDevice(
				NULL,                  //디스플레이 시스템(어댑터) NULL이면 주디스플레이로 자동 선택됨.
				m_d3dDriverType,       //드라이버 타입 지정.
				NULL,                  //특정 소프트웨어의 모듈을 사용하는 디바이스를 만들때 사용.
				uCreateDeviceFlags,    //디바이스 생성 플래그
				dxFeatureLevels,       //선택될 수 있는 피처 레벨이 담겨있는 배열
				uNumFeatureLevels,     //위의 배열의 원소수
				D3D11_SDK_VERSION,     //SDK 버전
				&m_pD3dDevice,         //생성된 디바이스를 반환받을 주소
				&m_d3dFeatureLevel,    //선택된 피처레벨을 반환받을 주소.
				&m_pD3dContext);       //생성된 DC를 반환받을 주소.

		    //디바이스를 생성하는데 성공하였지만 버전이 11이 아닐 경우 다시 생성하게 한다.
			if (SUCCEEDED(hr)) {
				if (FAILED(hr) || m_d3dFeatureLevel < D3D_FEATURE_LEVEL_11_0) {
					if (m_pD3dContext) { m_pD3dContext->Release(); }
					if (m_pD3dDevice) { m_pD3dDevice->Release(); }
					continue;
				} break;
			}
		}

		if (FAILED(hr)) {
			return false;
		}

		g_pD3dDevice = m_pD3dDevice;
		g_pD3dContext = m_pD3dContext;

		return S_OK;
	}

	//DXGIFactory 인터페이스를 생성한다. 
	HRESULT	DxDevice::CreateGIFactory()
	{
		if (m_pD3dDevice == nullptr) { return E_FAIL; }

		HRESULT hr;
		IDXGIDevice* pDXGIDevice;
		IDXGIAdapter* pDXGIAdapter;

		//생성되어 있는 ID3D11Device로부터 출발해서 IDXGIFactory를 넘겨받는다.
		hr = m_pD3dDevice->QueryInterface(__uuidof(IDXGIDevice), (LPVOID*)(&pDXGIDevice));
		hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (LPVOID*)(&pDXGIAdapter));
		hr = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (LPVOID*)(&m_pGIFactory));

		pDXGIDevice->Release();
		pDXGIAdapter->Release();
		return hr;
	}

	//DXGIFactory 인터페이스로부터 IDXGISwapChain 인터페이스를 생성한다.
	HRESULT	DxDevice::CreateSwapChain()
	{
		HRESULT hr = S_OK;
		if (m_pGIFactory == nullptr) { return S_FALSE; }

		//스왑체인 구조체를 생성한 뒤 필요한 내용을 채워서 이를 이용해 스왑체인 객체를 생성한다.
		DXGI_SWAP_CHAIN_DESC sd;
		ZeroMemory(&sd, sizeof(sd));

		sd.BufferCount = 1;                                  //버퍼 개수         
		sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;   //버퍼의 색상 포맷 (필수)
		sd.BufferDesc.RefreshRate.Numerator = 60;            //화면 주사율 (분자)
		sd.BufferDesc.RefreshRate.Denominator = 1;           //화면 주사율 (분모)
		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;    //버퍼 용도
		sd.OutputWindow = g_hWnd;                            //어느 윈도우에 뿌릴지 (필수)
		sd.Windowed = true;                                  //false 전체화면, true 창모드
		sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

		//샘플링 수준
		sd.SampleDesc.Count = 1;
		sd.SampleDesc.Quality = 0;

		//스왑체인 버퍼의 크기. 깊이스텐실뷰와 같은 크기로 생성해야 호환이 된다.
		//왜냐하면 스왑체인에서 백버퍼를 생성할 것이기 때문.
		sd.BufferDesc.Width = g_rtClient.right;
		sd.BufferDesc.Height = g_rtClient.bottom;

		//화면 크기 변경을 막아놓았기 때문에 
		//sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 
		//는 쓰지 않았다.

		//스왑체인 생성
		hr = m_pGIFactory->CreateSwapChain(m_pD3dDevice, &sd, &m_pSwapChain);
		if (FAILED(hr)) { return hr; }

		g_pSwapChain = m_pSwapChain;

		return hr;
	}

	//깊이 스텐실 뷰 생성
	HRESULT DxDevice::CreateDpethStencilView()
	{
		if (m_pD3dDevice == nullptr) { return E_FAIL; }

		HRESULT hr = S_OK;
		ID3D11Texture2D* m_pTex2D;  // 깊이 스텐실 버퍼

		D3D11_TEXTURE2D_DESC td;
		td.MipLevels = 1;    // 밉맵 갯수.
		td.ArraySize = 1;    // 텍스쳐 배열의 텍스쳐 수

		td.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
		td.Usage = D3D11_USAGE_DEFAULT;
		td.BindFlags = D3D11_BIND_DEPTH_STENCIL;

		//기타 옵션
		td.CPUAccessFlags = 0;
		td.MiscFlags = 0;

		//샘플링 수준
		td.SampleDesc.Count = 1;
		td.SampleDesc.Quality = 0;

		//깊이스텐실 버퍼의 크기. 백버퍼의 크기와 같아야 한다.
		td.Width = g_rtClient.right;
		td.Height = g_rtClient.bottom;

		hr = g_pD3dDevice->CreateTexture2D(&td, 0, &m_pTex2D);
		if (FAILED(hr)) { return hr; }

		D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
		dsvd.Format = td.Format;

		//3차원이니까 2차원 자원을 깊이스텐실맵으로 사용.
		dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
		dsvd.Texture2D.MipSlice = 0; //밉맵의 첫번째 인덱스.
		dsvd.Flags = 0;              //옵션값

		//깊이스텐실뷰 생성 (생성에 사용할 리소스, 생성 정보, 반환인자)
		hr = g_pD3dDevice->CreateDepthStencilView(m_pTex2D, &dsvd, &m_pDepthStencilView);
		if (FAILED(hr)) { return hr; }

		g_pDepthStencilView = m_pDepthStencilView;

		return hr;
	}

	//렌더타겟뷰 생성 및 세팅
	HRESULT	DxDevice::SetRenderTargetView()
	{
		HRESULT hr;
		ID3D11Texture2D* pBackBuffer;

		hr = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);  	//백버퍼를 받아옴
		hr = m_pD3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &m_pRenderTagetView);  	//렌더 타겟 뷰 생성
		pBackBuffer->Release();

		g_pRenderTagetView = m_pRenderTagetView;

		return S_OK;
	}

	//뷰포트 세팅
	HRESULT	DxDevice::SetViewPort()
	{
		//스왑체인 정보를 가져옴.
		DXGI_SWAP_CHAIN_DESC Desc;
		m_pSwapChain->GetDesc(&Desc);

		//뷰포트의 시작 좌표
		m_d3dViewPort.TopLeftX = 0;
		m_d3dViewPort.TopLeftY = 0;

		//스왑체인값에서 뷰포트 크기를 가져옴
		m_d3dViewPort.Width = (FLOAT)Desc.BufferDesc.Width;
		m_d3dViewPort.Height = (FLOAT)Desc.BufferDesc.Height;

		//뷰포트의 깊이값은 0에서 1사이로 제한됨
		m_d3dViewPort.MinDepth = 0.0f;
		m_d3dViewPort.MaxDepth = 1.0f;

		//렌더타켓뷰 세팅
		m_pD3dContext->RSSetViewports(1, &m_d3dViewPort);

		g_d3dViewPort = m_d3dViewPort;

		return S_OK;
	}

	//전체 생성하기
	HRESULT DxDevice::InitDevice()
	{
		HRESULT hr;

		if (FAILED(hr = CreateDevice())) { return hr; }
		if (FAILED(hr = CreateGIFactory())) { return hr; }
		if (FAILED(hr = CreateSwapChain())) { return hr; }
		if (FAILED(hr = CreateDpethStencilView())) { return hr; }
		if (FAILED(hr = SetRenderTargetView())) { return hr; }
		if (FAILED(hr = SetViewPort())) { return hr; }

		//ALT+ENTER와 메시지큐 모니터링을 막는다.
		m_pGIFactory->MakeWindowAssociation(g_hWnd, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES);

		return hr;
	}
#pragma endregion

	//정리하기
	bool DxDevice::CreanupDevice()
	{
		//삭제는 생성의 역순.
		//세팅값을 복원시켜주고 삭제한다.
		if (m_pD3dContext) { m_pD3dContext->ClearState(); }
		if (m_pD3dContext) { m_pD3dContext->Release(); }
		m_pD3dContext = g_pD3dContext = nullptr;

		if (m_pDepthStencilView) { m_pDepthStencilView->Release(); }
		m_pDepthStencilView = g_pDepthStencilView = nullptr;

		if (m_pRenderTagetView) { m_pRenderTagetView->Release(); }
		m_pRenderTagetView = g_pRenderTagetView = nullptr;

		if (m_pSwapChain) { m_pSwapChain->Release(); }
		m_pSwapChain = g_pSwapChain = nullptr;

		if (m_pD3dDevice) { m_pD3dDevice->Release(); }
		m_pD3dDevice = g_pD3dDevice = nullptr;

		if (m_pGIFactory) { m_pGIFactory->Release(); }
		m_pGIFactory = nullptr;

		return true;
	}


	DxDevice::~DxDevice()
	{

	}

}

WinL.h

#pragma once
#include "DxDevice.h"

namespace Lypi
{
	class winL : public DxDevice
	{
	protected:
		WNDCLASSEX   m_wndC;               //윈도우 클래스
		LPCWSTR      m_lWndName;           //윈도우 이름

		HWND         m_hWnd;			   //생성된 윈도우의 핸들값
		RECT         m_rtWindow;		   //윈도우 영역
		RECT         m_rtClient;		   //클라이언트 영역 (작업영역)
		winL*        m_pWindow;            //현재 생성된 윈도우에 대한 포인터

	public:
		bool registWnd(LPCTSTR LWndName);   //윈도우 등록.
		LRESULT MsgProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);  //윈도우 프로시저
		virtual bool runWindow();   //윈도우 돌리기
		
		virtual LRESULT	MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //윈도우 메시지를 이용할 때 코어에서 호출

		void CenterWindow();       //윈도우를 중앙으로 옮기는 함수

	public:
		virtual bool gameInit() = 0;            //게임 전체의 초기화를 담당
		virtual bool gameRun() = 0;             //게임의 전 과정을 실행.
		virtual bool gameFrame() = 0;           //게임의 매 프레임 계산을 담당.
		virtual bool gamePreRender() = 0;       //게임의 매 프레임 렌더링 전 필요한 절차를 담당.
		virtual bool gameRender() = 0;          //게임의 매 프레임 렌더링을 담당.
		virtual bool gamePostRender() = 0;      //게임의 매 프레임 렌더링 후 필요한 절차를 담당.
		virtual bool gameRelease() = 0;         //게임 전체의 메모리 소멸 및 객체 해제를 담당.

		virtual bool ResetRT() = 0;

	public:
		winL(LPCTSTR LWndName);
		virtual ~winL();
	};
}

WinL.cpp

#pragma once
#include "WinL.h"

namespace Lypi
{
	//전역변수 선언
	HINSTANCE    g_hInst;              //윈도우의 인스턴스 핸들값

	HWND         g_hWnd;			   //생성된 윈도우의 핸들값
	winL*        g_pWindow;            //현재 생성된 윈도우에 대한 포인터
	RECT         g_rtWindow;		   //윈도우 영역
	RECT         g_rtClient;		   //클라이언트 영역 (작업영역)

	//전역함수 선언
	LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 	

	//-------------

	winL::winL(LPCTSTR LWndName)
	{
		m_pWindow = this;
		g_pWindow = this;

		registWnd(LWndName);
	}

	//윈도우 등록 및 생성
	bool winL::registWnd(LPCTSTR LWndName)
	{
		//Regist wndClass
		ZeroMemory(&m_wndC, sizeof(WNDCLASSEX));
		m_wndC.cbSize = sizeof(WNDCLASSEX);
		m_wndC.hInstance = g_hInst;
		m_wndC.lpfnWndProc = WndProc;
		m_wndC.lpszClassName = LWndName;
		m_wndC.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);

		if (!RegisterClassEx(&m_wndC)) {
			return false;
		}

		m_hWnd = CreateWindowEx(0,//WS_EX_TOPMOST,         // 윈도우 창 확장 스타일
			m_wndC.lpszClassName, m_wndC.lpszClassName,	   // 윈도우 클래스 이름(중요), 타이틀 바에 나타날 문자열.
			WS_SYSMENU | WS_BORDER | WS_VISIBLE,           // 생성될 윈도우 창의 스타일 지정 
			CW_USEDEFAULT, CW_USEDEFAULT,				   // 윈도우 X,Y 좌표
			1516, 789,	                 	               // 윈도우 수평, 수직 크기 (픽셀 단위) (x+16, y+39)
			NULL, NULL, g_hInst, 	 		               // 부모 윈도우의 핸들 지정, 메뉴 핸들 지정, 윈도우를 생성하는 인스턴스 핸들
			NULL);                                         // WM_CREATE메시지의 lParam으로 전달될 CREATESTRUCT구조체 포인터
													
		if (m_hWnd == NULL) {
			return false;
		}

		g_hWnd = m_hWnd;

		GetWindowRect(m_hWnd, &m_rtWindow);  	g_rtWindow = m_rtWindow;
		GetClientRect(m_hWnd, &m_rtClient);     g_rtClient = m_rtClient;

		return true;
	}

	//in-class Msg Proc
	LRESULT winL::MsgProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
	{
		assert(m_pWindow);

		MsgProcA(hWnd, iMsg, wParam, lParam);

		switch (iMsg) {
			
			case WM_CREATE: {
				//윈도우를 생성할 때 발생하는 메시지
			}break;

			case WM_SIZE: {
			}break;

			case WM_DESTROY: {
				//윈도우를 종료할 때 발생하는 메시지 (프로그램 종료와는 별도)
				PostQuitMessage(0); //프로그램 종료 명령
			}break;
		}

		return 1;
	}

	LRESULT	winL::MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		return 1;
	}

	//윈도우 돌리기
	bool winL::runWindow()
	{
		if (!gameInit()) { return false; }

		//Main message loop
		MSG msg;
		ZeroMemory(&msg, sizeof(MSG));

		while (true) {
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
				TranslateMessage(&msg);
				DispatchMessage(&msg);

				if (msg.message == WM_QUIT) {
					break;
				}
			}
			else {
				gameRun();
			}
		}

		if (!gameRelease()) { return false; }

		return true;
	}

	//윈도우를 중앙으로 옮기는 함수.
	void winL::CenterWindow()
	{
		// 화면 스크린의 해상도(넓이와 높이)을 얻는다.
		int iScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
		int iScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN);

		// 윈도우 클라이언트 중앙과 화면 스크린 중앙을 맞춘다.
		int iDestX = (iScreenWidth - m_rtClient.right) / 2;
		int iDestY = (iScreenHeight - m_rtClient.bottom) / 2;

		// 윈도우를 화면중앙으로 이동시킨다.
		MoveWindow(m_hWnd, iDestX, iDestY, m_rtClient.right, m_rtClient.bottom, true);
	}

	winL::~winL()
	{

	}
	
	//전역함수
	LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		assert(g_pWindow != NULL);

		g_pWindow->MsgProc(hWnd, msg, wParam, lParam);

		return DefWindowProc(hWnd, msg, wParam, lParam);
	}

}

zCore.h

#pragma once
#include "WinL.h"
#include "DxWrite.h"
#include "DxTimer.h"
#include "DxInput.h"

namespace Lypi
{
	class zCore : public winL
	{
	protected:

	public:
		bool ResetRT();

	public:
		//게임 전체적인 처리 순서에 대한 함수들. 게임에 관한 부분과 윈도우 생성에 관한 부분을 분리
		bool gameInit() override;
		bool gameRun() override;
		bool gameFrame() override;
		bool gamePreRender() override;
		bool gameRender() override;
		bool gamePostRender() override;
		bool gameRelease() override;

	public:
		//클래스 각각에 대한 처리 순서에 관한 함수들. 
		virtual bool Init() { return true; };
		virtual bool Frame() { return true; };
		virtual bool PreRender() { return true; };
		virtual bool Render() { return true; };
		virtual bool PostRender() { return true; };
		virtual bool Release() { return true; };

		LRESULT	MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

	public:
		zCore(LPCTSTR LWndName);
		virtual ~zCore();
	};

}

zCore.cpp

#include "zCore.h"

namespace Lypi
{

	zCore::zCore(LPCTSTR LWndName) : winL(LWndName)
	{
	}

	LRESULT	zCore::MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		return 1;
	}

	bool zCore::ResetRT()
	{
		IDXGISurface1* pBackBuffer = nullptr;
		HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(IDXGISurface), (void**)&pBackBuffer);

		if (pBackBuffer) {
			pBackBuffer->Release();
		}

		return true;
	}

	bool zCore::gameInit()
	{
		//디바이스 생성 작업 실행.
		InitDevice();
		ResetRT();
		g_pWindow->CenterWindow();

		Init();

		return true;
	}

	bool zCore::gameRun()
	{
		gameFrame();
		gamePreRender();
		gameRender();
		gamePostRender();
		return true;
	}

	bool zCore::gameFrame()
	{
		Frame();

		return true;
	}

	bool zCore::gamePreRender()
	{
		float ClearColor[4] = { 0.1f, 0.2f, 0.3f, 1.0f }; //r,g,b,a
		g_pD3dContext->ClearRenderTargetView(m_pRenderTagetView, ClearColor);
		g_pD3dContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
		g_pD3dContext->OMSetRenderTargets(1, &m_pRenderTagetView, m_pDepthStencilView);

		PreRender();

		return true;
	}

	bool zCore::gameRender()
	{
		Render();
		return true;
	}

	bool zCore::gamePostRender()
	{
		PostRender();

		//IDXGISwapChain 객체를 사용하여 시연(출력)한다.
		//모든 렌더링 작업들은 present앞에서 이뤄져야 한다.
		g_pSwapChain->Present(0, 0);
		return true;
	}

	bool zCore::gameRelease()
	{
		Release();

		if (!CreanupDevice()) { return false; }

		return true;
	}


	zCore::~zCore()
	{
	}

}


반응형