Game Programming/Rendering

DX 9 :: 윈도우 생성

VallistA2016. 2. 16. 09:26

DX 관련 글


기본 윈도우 생성 : 클릭

윈도우 생성 : 클릭

리얼타임 메시지 루프 : 클릭

Direct3D 시작 : 클릭




혹시 기본 윈도우 생성 및 설정 글을 보지 않았다면 위의 링크에 가서 보도록 하자

이번 글은 새로운 윈도우 창을 만들어서 띄워볼 것이다.




윈도우 생성


게임 프로그래밍을 할 때, Windows API 코드를 사용하여 기본적인 창을 생성을 한 후 그 위에 렌더러를 올린다.
우리는 기본 윈도우 생성 글에서 팝업창을 띄웟었는데, 이번에는 하나의 Application Window를 만들어보도록 한다


소스코드는 위와 같은데, 여기서 우리가 중요시 봐야할 것은 아래와 같다.



이 구문들은 윈도우를 제작하는데 핵심적으로 필요한 구문들이다.

그렇다면 간단하게 이 구문들을 알아보고 가도록 한다.




윈도우 클래스 등록


윈도우 클래스는 안의 속성과 다양한 윈도우의 작업을 처리하기 위한 Windows에서 사용되는 기본적인 구조이다.

그 윈도우 클래스를 사용하기 위해서는 우리가 등록을 해줘야 할 필요성이 있는데, 그 과정이 RegisterClassEx 라는 함수를 사용하여 이뤄지게 된다.


그 과정으로 우리는 아래와 같은 소스코드를 타이핑했다.



그렇다면, 해당 코드에 들어간 내용들에 대해서 알아보도록 하자.


1. WNDCLASSEX wc;


 이 클래스는 윈도우의 정보가 들어가 있는 템플릿 클래스 이며

 이 안에 들어가있는 정보는 윈도우의 커서정보, 스타일, 사이즈, 뒷배경 색, 윈도우 이름 등이 들어가 있다.

 wc라고 변수를 선언해서 윈도우를 설정한 후 Registerclass 함수에서 등록을 해준다.


2. ZeroMemory(&wc, sizeof(WNDCLASSEX));


 ZeroMemory 함수는 메모리의 전체 블록을 NULL로 초기화 하는 함수다.

 처음 시작시 첫 번째 매개 변수에 제공된 주소를 설정하며, 두 번째 매개 변수는 블록의 사이즈를 나타낸다.

 우리는 WNDCLASSEX 인 wc를 대상으로 메모리 블록을 초기화 하는 과정을 담을 것 이기 때문에 WNDCLASSEX의 사이즈를 가져왔다.


3. wc.cbSize = sizeof(WNDCLASSEX);


 이름 그대로 윈도우의 크기를 할당하는 변수이다.


4. wc.style = CS_HREDRAW | CS_VREDRAW;


 이 변수는 윈도우의 스타일을 저장하는데, 삽입할 수 있는 값은 많지만 게임 프로그래밍에서는 위와 같이 한개밖에 사용하지 않는다.

 그 이유는, 다른 옵션의 경우 메뉴 탭이나 다른 옵션을 선택 할 수 있지만 그럴 경우 윈도우 창이 협소해지기 때문에 잘 사용하지 않는다.

 CS_VREDRAW와 CS_HREDRAW 의 경우 논리적 OR을 사용한다.

 두 가지를 둘다 포함을 해야하는 이유는 수평이나 수직으로 이동하면 다시 그려줘야 하기 때문이다.

 전체 화면에 대해서는 다시 설정해줘야 한다.


5. wc.lpfnWndProc = WindowProc;


 이 변수는 윈도우 메시지를 가져오는 함수이[다.

 윈도우 메시지가 무엇이냐 하면, 키보드, 마우스등의 행동을 가져오는 CALLBACK 함수이다.

 위의 풀 소스를 보면 WindowProc을 선언 해 준것을 볼 수 있다.


6. wc.hInstance = hInstance;

 

 HINSTANCE 를 가져오는 변수다.

 hInstance에 대해서는 저번에 언급했었다. 궁금하면 전 글을 복습하길 권장한다.


7. wc.hCursor = LoadCursor (NULL, IDC_ARROW);


 이 변수는 기본적인 마우스 커서값을 변경할 때 사용된다.

 기본적으로 IDC_ARROW는 윈도우 기본 화살표를 말한다.


8. wc.hbrBackground = (HBRUSH)COLOR_WINDOW;


 이 변수는 윈도우의 뒷 배경 색을 지정한다.

 

9. wc.lpszClassName = "Window";


 윈도우의 창의 이름을 설정하는 변수이다.




윈도우 생성


지금까지 윈도우를 메모리에 등록을 해주는 과정을 마쳤다.

이젠 윈도우를 화면상에 출력을 해주도록 유도를 해야한다.

해당 소스는 아래와 같다.


사용된 소스 :


함수 원형 :



소스코드는 비교적 간단하게 한줄로 되어있으며, 잘 보이기 위해서 인자마다 개행을 해주었다.

변수가 상당히 많은데, 하나하나 알아보도록 하자.


1. DWORD dwExStyle


 RegisterClass 가 Ex 가 붙어 업그레이드 될 때 첫번째 매개변수가 확장되었는데, 네번째 매개변수 dwStyle의 확장이며 단순히 창 스타일에 대한 더 많은 옵션을 추가할 수 있다.


2. LPCTSTR lpClassName


 윈도우 클래스의 이름을 나타낸다.


3. LPCTSTR lpWindowName 


 윈도우 클래스의 타이틀명을 나타낸다.


4. DWORD dwStyle


  윈도우의 모든 종류의 옵션을 정의 할 수 있는 곳이다.

  크기조정, 최소 최대화 버튼, 스크롤, 등등의 작업을 수행 할 수 있다.

  다시 말하지만 이러한 CreateWindowEx 함수는 MSDN 라이브러리에서 볼 수 있다.

  기본적으로 표준 값인 WS_OVERLAPPEDWINDOW를 사용한다.


5. int x


 윈도우가 생성될 때의 윈도우 위치 x 값이다.


6. int y

 

 윈도우가 생성될 때의 윈도우 위치 y 값.


7. int nWidth


 윈도우의 가로 값이다.


8. int nHeight


 윈도우의 세로 값이다.


9. HWND hWndParent


 지금 만들고 있는 창을 만들어 상위 윈도우에 알려주는 매개변수이다.

 프로그램에 있는 상위 창을 가지고 있지 않지만, 같은 창에서 여러 윈도우를 열 수 있도록 지원한다.

 우리는 사용하지 않기 때문에 NULL을 썻다.


10. HMENU hMenu


 메뉴 바의 핸들인데, 우리는 사용하지 않는다.


11. HINSTANCE hInstance


 우리가 사용하던 hInstance 를 넣으면 된다.


12. LPVOID lpParam

 

 여러개의 윈도우를 만들때 사용하는데, 우리는 사용하지 않으므로 NULL


13. Return Value


 hWnd 를 Return 하는데, 이 값은 윈도우 핸들 값이다.




윈도우 보이기


 먼저 함수 원형을 보도록 하자.



1. HWND hWnd

 위에서 윈도우를 생성할 때 유도된 윈도우 핸들을 넣는다.

2. int nCmdShow
 
 WinMain의 패러미터에 nCmdShow가 있었을 것이다. 바로 그것을 넣어주면된다. 전체화면시에 쓰인다.



이 과정까지 끝내면 윈도우가 생성될 것이다. 하지만 윈도우가 생성되도 제대로 돌아가는 것이 아니다.
키 입력들을 받아야 제대로 된 윈도우가 될 것이 아닌가?

윈도우 핸들링 이벤트와 메시지


윈도우를 만들면 이제 뭘 해야하겠는가?
윈도우를 만들고 나서부터는 우리가 원하는 입력을 이용하여 키를 입력받아 캐릭터를 움직이고, 이벤트를 줘야할 것 아닌가?

현재 우리가 만들어놓은 창이 유지되는 이유는, while 문으로 계속 내부를 순환하고 있기 때문이다.
그러므로 순환되는 동안 우리는 키 이벤트를 줄 수 있다. 하지만 순환이 끝나면 윈도우 창은 꺼지고, 그 꺼지는 이벤트에 대해서 키로 입력을 받게끔 할 수도 있다.

윈도우 프로그래밍은 이벤트를 기반으로 만들어져 있기 때문에, 우리가 키 이벤트를 주면 동일하게 윈도우 프로그래밍에 이벤트를 보내야 한다는 것이 된다. 윈도우는 우리가 키 이벤트를 줄때까지 계속 유휴상태에서 대기하고 있으며, 키를 입력을 주면 재빠르게 받고, 이벤트에 대해서 CALLBACK을 보내준 후 다시 유휴상태에 빠진다.

윈도우는 우리에게 모든 메시지를 전달하지 않는다. 몇 가지 매시지는 즉시 발생하게 되는데, 이 메시지는 이벤트 큐에 담아져있는다.
우리는 GetMessage() 함수를 사용해서 큐에 있는 메시지를 검색하여, TranslateMessage() 함수를 사용해서 어떤 핸들 메시지 포멧을 찾고
DispatchMessage를 사용하여 WindowProc() 함수에 사용 메시지의 결과로서 실행된다.

이벤트 처리는 두 부분으로 나뉜다.

1. 메인 루프
2. WindowProc() 함수

메인 루프는 GetMessage() 함수, TranslateMessage() 와 DispatchMessage() 함수로 구성되어 있고
WindowProc() 함수는 특정 메시지가 전송 될 때 실행 코드로 구성되어 있다.
이것은 이외로 간단한데, 설명은 아래와 같다.




1. 메인 루프


메인 루프틑 세 가지 기능으로 나뉘어져 있는데, 먼저 소스부터 보자.



MSG msg;


 MSG는 하나의 이벤트 메시지에 관한 모든 데이터를 포함하는 구조이며 일반적으로 구조체에 접근 할 필요가 없다.


while(GetMessage(&msg, nullptr, 0, 0))


 GetMessage() 는 키 메시지를 큐 메시지에서 검색하는 역할을 하며, MSG 구조체에서 검색을 할 수 있는 기능이다.

 항상 FALSE를 반환하며 키값이 있으면 TRUE를 반환한다.


 아래는 GetMessage 함수의 원형이다.



 LPMSG lpMsg,

 

  이 패러미터는 메시지 구조체에 대한 포인터이며, 여기에 구조체 주소를 넣는다.

  

 HWND hWnd,


  이 메시지는 윈도우 핸들이다. 하지만 위의 소스는 여기에 NULL이 넣어져 있는 것을 볼 수 있는데, 

  NULL의 의미는 다음 메시지를 윈도우에 띄운다는 것이다.


 UINT wMsgFilterMin, UINT wMsgFilterMax


  이 패러미터는 메시지 큐를 검색하는 메시지 유형을 제한할 수 있는 메시지이다.

  WM_MOUSRFIRST 및 WM_MOUSELAST 마우스 메시지에 메시지 유형을 제한한다.


TranslateMessage(&msg)


 이 함수는 특정 키 프레스 형식을 적절하게 변환하는 기능이다.


DispatchMessage(&msg)


 기본적으로 사용되지 않으나 이 메시지를 WindowProc 함수에 전달한다.  




2. WindowProc() 함수


메인 루프를 적용했으니 이제 WindowProc 함수에 대해 알아보도록 하자.

GetMessage 함수는 메시지를 가져오고, DispatchMessage 함수를 사용하여 전달한다.

DispatchMessage 함수는 해당 WindowProc() 함수를 호출한다. 

WindowProc 함수가 없으면 문제가 되었지만 우리는 WindowProc 함수가 있으므로 그 WindowProc 함수가 호출이 된다.


메시지가 WindowProc을 들어오면 그것이 무엇인지 메시지를 확인하기 위해 패러미터를 사용할 수 있다. 많은 프로그래머들이 메시지를 결정하는 스위치 문을 사용한다. 다음은 이 메시지를 루프 시키는 방법이다.



스위치 문 내부에는 WM_DESTROY가 보이는데 이 메시지는 창을 닫을때 메시지가 전송이 된다.

응용프로그램을 정리할 때 여기에 구문을 적으면 호출되게 된다.

메시지가 들어왔을 때 메모리등을 정리해주면 되겠다. 



PostQuitMessage() 함수는 0의 정수 값을 갖으며 WM_QUIT 메시지를 전송한다.

메인루프를 다시 호출하면 프로그램이 종료하려고 할 때 GetMessage 함수는 FALSE 반환을 기억한다. 

WM_QUIT가 좀 더 구체적으로 FALSE를 반환한다. 



'Game Programming > Rendering' 카테고리의 다른 글

DX 9 :: 전체화면  (0) 2016.02.19
DX 9 :: Direct3D 시작  (0) 2016.02.17
DX 9 :: 리얼타임 메시지 루프  (0) 2016.02.16
DX 9 :: 기본 윈도우 생성  (0) 2016.02.12
Direct 11 :: 'main' entry point not found  (0) 2015.03.30

댓글

VallistA

병특이 끝나서 게임에서 웹으로 스위칭한 프로그래머.
프로그래밍 정보등을 공유합니다.
현재는 이 블로그를 운영하지 않습니다.
vallista.kr 로 와주시면 감사하겠습니다!

자고 싶습니다. ㅠㅠ

Github      :: 링크

궁금한점 문의 주시면 답변드리도록 하겠습니다

VISITED

Today :

Total :

SNS

  • 페이스북아이콘
  • 카카오톡아이콘
  • 트위터아이콘

Lately Post

Lately Comment