24/03/20
21화. Win32API Resource (1)
Resource 클래스 생성 :
Resource 클래스는 Texture, Sound 클래스 등으로 파생되어 사용될 것이다.
리소스의 이름과 리소스를 읽어올 경로(상대경로)를 멤버 변수로 가진다.
리소스의 경로가 상대경로인 이유는 실행파일의 위치에 따라 절대경로는 바뀐다. 때문에 절대경로로 가지고 있어도 의미가 없다.
CTexture 클래스 :
Resource 클래스를 상속하는 Texture 클래스 생성
멤버로 DC 와 BITMAP 객체를 가진다.
Texture 파일을 Load 하여 BITMAP에 저장해두면, DC에 해당 BITMAP 을 연결하여 메인 윈도우의 DC와 더블 버퍼링을 진행중인 memDC의 BITMAP 객체에 Load한 이미지를 그려준다.
22화. Win32API Path Manager
Texture::Load() 함수 구현 :
Window 에서 제공해주는 "LoadImage()" 함수 활용
HANDLE LoadImageA(
[in, optional] HINSTANCE hInst, // 로드할 이미지가 포함된 dll,exe 파일의 핸들
[in] LPCSTR name, // 상대 경로
[in] UINT type, // 로드할 이미지의 타입
[in] int cx, // 너비
[in] int cy, // 높이
[in] UINT fuLoad // 로드 옵션
);
첫번째 인자의 경우 미리 정의된 이미지를 사용할 경우 NULL 로 설정해주면 된다.
4,5번째 인자는 로드할 이미지의 너비와 높이를 의미하는데 '0'을 넣어주면 이미지 전체를 읽어온다.
경로 :
LoadImage 함수에 들어가야하는 경로는 Load 할 이미지가 존재하는 절대경로를 의미한다.
출력 디렉터리는 "컴파일 + 빌드"의 결과물이 생성될 폴더의 위치를 나타낸다.
- $(SolutionDir) : 솔루션 파일이 위치하는 경로
- $(Platform) : 환경 (x64 / x84)
- $(Configuration) : 구성 속성 (Debug / Release)
경로 수정 :
Path Manger 클래스 추가전에 환경 설정을 해준다.
1. 출력 디렉터리 수정
Configuration : Debug
Output Dir : $(SolutionDir)Output\bin_debug
Configuration : Release
Output Dir : $(SolutionDir)Output\bin
2. 리소스 파일이 위치할 폴더("content") 생성
궁극적으로 우리가 제작하여 배포하려는 버전은 Relese 버전이다.
때문에 Release 버전의 실행파일이 리소스를 참조할 수 있도록 Release 폴더 안에 리소스 폴더를 위치시켜준다.
content 폴더 안에는 리소스의 종류에 해당하는 폴더들을 생성해준다. (sound, texture, etc ...)
결국 Release 버전이든 Debug 버전이든 실행시킬 때, content 폴더의 위치경로를 알아와야한다.
작업 디렉터리 설정 (Working Directory) :
PathMgr 클래스를 생성하기에 앞서 작업디렉터리 설정을 해줘야한다.
Windows에서 제공해주는 GetCurrentDirectory() 함수를 통해 현재 위치(=실행 파일의 위치)를 얻어올 수 있다.
디버그 모드에서 빌드후 얻어낸 실행파일을 실행하면 이전에 설정해준 출력 디렉터리가 현재 위치로 잡히는걸 확인할 수 있다.
하지만, VS에서 실행시키면 엉뚱한 경로가 현재위치로 출력됨을 확인 할 수 있다.
해당 경로는 프로젝트 파일이 위치한 경로이다.
이유 : 자체적으로 실행된게 아니라 Visual Studio 라는 프로그램을 통해 실행되기에 해당 결과가 나온다.
프로젝트 속성에서 디버깅의 "작업디렉터리" 경로를 수정해주면 Visual Studio로 실행했을 때의 현재 위치 경로를 수정할 수 있다.
기본적으로 "$(ProjectDir)" 로 설정되어 있기때문에 GetCurrentDirectory() 의 결과가 프로젝트 파일의 경로로 나왔던 것이다.
해당 설정값의 경로도 출력 디렉터리와 동일하게 "$(SolutionDir)Output\bin" 으로 수정한다.
PathMgr 클래스 생성 :
리소스들이 모여 있는 파일 content 는 Release 모드 디버그 폴더인 "..\Game\Output\bin\content" 경로에 들어있다.
디버그 모드 실행파일, 릴리즈 모드 실행파일, VS를 통한 실행 이 모든 경우에도 문제 없이 content 폴더의 경로를 성공적으로 찾아 들어가기 위해선 GetCurrentDirectory() 함수를 통해 얻어온 경로에서 상위폴더로 한번 이동한 후 bin\content 경로로 타고 들어가면 된다.
즉, "..\Game\Output\" + "bin\content\" 를 한다는 의미이다.
23화. Win32API Resource (2)
Player 클래스에 CTexture 객체 멤버로 추가 :
CPlayer 클래스는 Texture 이미지를 memDC와 연결된 Bitmap 이미지에 그려주기 위해서 render(HDC _dc) 함수를 override 한다.
BitBlt()으로 CPlayer 클래스에 존재하는 CTexture의 이미지를 복사해주기 위해선 render 의 인자로 들어오는 dc(목적지, memDC)를 알아야 하기 때문이다.
참고로 memDC는 CSceneMgr 클래스의 render() 함수를 타고 들어와서 전달된다.
GetObject() :
로드한 Bitmap에 대한 정보는 GetObject() 함수를 사용하면 얻을 수 있다.
int GetObject(
[in] HANDLE h, // 정보를 알고자 하는 그래픽 객체의 핸들
[in] int c, // 데이터가 쓰여질 구조체의 사이즈, 버퍼의 사이즈
[out] LPVOID pv // 버퍼의 주소값
);
첫번째 인자로는 정보를 얻고자 하는 그래픽 객체의 핸들을 넣어주면 된다.
지금은 Bitmap에 대한 정보를 얻고자 하기에 이미지 파일을 Load 하여 생성한 Bitmpa 객체의 핸들을 넣어주면 된다.
(실습) 이미지 출력 :
TransparentBlt() :
캐릭터 이미지의 주변에 같이 출력되는 배경을 없애는 방법을 알아보자
BitBlt() 함수 말고도 Bitmap 파일을 복사해주는 함수가 있는데 TransparentBlt() 함수다.
해당 함수는 BitBlt()와 마찬가지로 Bitmap 정보를 복사하는데 특정 색상을 선택하여 무시할수 있다.
TransparentBlt() 사용법 :
해당 함수를 그냥 사용하려고 하면 링크에러가 발생한다.
MSDN을 보면 요구사항에 "wingdi.h" 에 선언되어 있지만 Windows.h 에 포함되어 있기에 굳이 wingdi.h 를 따로 포함시켜줄 필요는 없다.
구현부인 Library를 보면 "Msimg32.lib"에 구현부가 들어있음을 알 수 있다.
TransparentBlt function (wingdi.h) - Win32 apps
The TransparentBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
learn.microsoft.com
아래의 코드를 작성해주면 lib 를 포함시킬 수 있다.
#pragma comment(lib, "Msimg32.lib")
정상적으로 빌드가 진행되고 코드를 다시 실행시켜보면 동일한 이미지를 사용했음에도 배경이 출력되지 않았다.
24화. Win32API Resource Manager
문제점 :
현재 Player 객체에 추가된 CTexture 객체는 Player의 생성자에서 생성된다.
리소스는 사용하는 곳에서 직접 로딩하여 사용하는게 아니라 매니저를 통해 받아서 사용하도록 해야한다.
해당 문제를 해결해보자
Resource Manager 생성 (CResMgr.h/cp) :
로드한 이미지들을 관리하기 위해 map 컨테이너에 로드한 Texture 객체들을 저장
Texture 를 로드하는 기능을 가진 LoadTexture() 함수와 컨테이너에서 해당 ID 값을 가진 Texture가 이미 존재하는지 찾아주는 FindTexture() 함수가 존재한다.
CTexture 클래스 생성자 막아주기 :
CTexture 클래스의 생성자를 private 범위 지정자로 선언하여 외부에서 CTexture 클래스를 생성하지 못하도록 한다.
대신 CResMgr 클래스는 friend 로 선언하여 private 범위에 접근할 수 있도록 해준다.
CRes 클래스 상속 하는 CTexture 클래스 :
Resource를 의미하는 CRes 클래스는 멤버 변수로 자신의 ID 와 상대경로를 가지고 있다.
이러한 이유 때문에 Rescource Manager 에서 Texture 를 로드해줄때, 로드한 Texture 객체에 ID 값과 상대경로를 기록해준다.
메모리 릭 발생여부 체크 :
CRT 라이브러리로 메모리 누수 찾기
C/C++ 디버거 및 CRT(C 런타임 라이브러리)를 통해 메모리 누수를 찾는 방법을 알아봅니다. 포함되는 기술로는 메모리 누수 보고서와 메모리 스냅샷 비교가 있습니다.
learn.microsoft.com
해당 코드를 main 함수의 시작 부분에 넣어준다.
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//_CrtSetBreakAlloc(/*num*/);
Next Note
Win32API_StudyNote_5
24/03/22
coder-qussong.tistory.com
'Win32API' 카테고리의 다른 글
Win32API_StudyNote_6 (0) | 2024.03.24 |
---|---|
Win32API_StudyNote_5 (0) | 2024.03.22 |
Win32API_StudyNote_3 (0) | 2024.03.19 |
Win32API_StudyNote_2 (0) | 2024.03.17 |
Win32API_StudyNote_1 (0) | 2024.03.13 |