midas+son의 크리에이티브(creative) 이야기

API 함수 를 WndProc에서 사용 할때

마우스 이벤트를 받아오는 것 중 많이 사용하는 것은 아래과 같습니다.


#define WM_MOUSEFIRST                   0x0200

#define WM_MOUSEMOVE                   0x0200

#define WM_LBUTTONDOWN                0x0201

#define WM_LBUTTONUP                    0x0202

#define WM_LBUTTONDBLCLK              0x0203

#define WM_RBUTTONDOWN                0x0204

#define WM_RBUTTONUP                    0x0205

#define WM_RBUTTONDBLCLK              0x0206

#define WM_MBUTTONDOWN                0x0207

#define WM_MBUTTONUP                    0x0208

#define WM_MBUTTONDBLCLK              0x0209


WM_MOUSEFIRST와 WM_MOUSEMOVE는 각각 마우스이벤트의 첫 시작과 

마우스가 움직일 때를 의미하는데 값이 같으므로 동일한 이벤트라고 생각하시면 됩니다.  


그 다음으로

LBUTTON으로 시작하는 것은 마우스 왼쪽 버튼,

RBUTTON으로 시작하는 것은 마우스 오른쪽 버튼, 

MBUTTON으로 시작하는 것은 중앙 버튼입니다.(마우스 기종 중에 중앙 버튼이 따로 있는 기종이 있긴 하지만 보통 마우스에서는 휠을 클릭했을 때 반응)


그 뒤에 나오는 DOWN은 마우스를 눌렀을 때,

UP은 마우스를 눌렀다가 땠을 때,

DBLCLK은 더블 클릭을 나타내는 이벤트 메세지 입니다.



콘솔로 프로그래밍 건드리는 중에

데코(?)라고해서 글자들 쓰기 위한 커서의 위치를 조정하는 함수나

색상을 주는 함수를 자주 사용하는데 

매번 새로운 프로젝트 생성 시 마다

계속 복사 붙여넣기를 하다보니

좀 번거로운 감이 없지 않아 있었다.


그래서 공통 해더로 만들어서 

#include하여 쓰자!! 라고 생각했는데

애매한 에러 때문에 1시간 30분 넘게 시간을 잡아 먹어 버렸다.


그 유의사항을 공유하도록 하겠다.


class가 하니라 header에 함수를 넣어 놓고 사용을 할 것이므로

아래와 같이 지정을 했었다.


다른 헤더에서 참조하여 써도 

그 당시에는 에러가 발생 하지 않는다.

잘 참조 한다는 것이다.


하지만 빌드를 하면 아래와 같은 에러를 보게 될 것이다.


LNK2005 에러...

구글링 해보니까 별에별 설명이 다 되어있는데

납득이 안되는 얘기들이 좀 많았다.

Visual Studio 어디 가서 설정해라... MFC어쩌구 CRT어쩌구... 


그래서 더 찾아 보았다.

msdn 정식 사이트에서 원하는 답을 찾을 수 있었다.

https://msdn.microsoft.com/ko-kr/library/72zdcz6f(v=vs.80).aspx 

(위에 주소 링크)


뭐 다 떠나서 해결은 "static 변수를 선언합니다." 만 봤다.

void 앞에 static만 추가 시켰다.


잘된다 (눈물의 1시간 반)

그냥 메모리에 공간좀 차지 한다고 해도 쓰자.

시간은 오래 걸렸지만 쉽게 해결 됐다.


만든 header파일은 아래 처럼 include해야지 header안에 만들어놓은 함수 사용에 지장이 없다.

참고로 #include 다음에 <>로 되어있는 것은 

시스템에 이미 만들어져 있는(내장되어 있는) 헤더이고 

""로 되어있는 것은 내가 만들어서 추가한 헤더이다.

그러므로 common.h라는 이름의 헤더를 내가 만들어 썼다는 얘기이다.


//=======================================================================================

추가 2015. 10.12

위의 방법보다 더 효율적인 방법을 알게 되어 추가 한다.

위와 같이 inline을 사용하는 것이다.


inline으로 만든 함수는 호출하게 되면

실행시 호출하는 그 자리에 

함수가 통째로 복사가 되어 돌아가게 된다고 한다.


복잡하고 무거운 함수로 하면

자원 소모가 크겠지만

간단한 함수를 자주 사용하게 된다고 하면

inline이 효율이 좋은 것 같다.


당연한 얘기지만 

다른 class에서 사용하려고 하면

저 함수를 제작한 헤더를 

#include해주어야 한다.

C++의 class에서 다른 class를 사용하는 변수를 지정할 때

보통 포인터 변수로 지정하는데 

포인터 변수로 선언했을 떄와 그냥 class 명으로만 선언했을 때 차이가 있다.


class명 만으로 변수를 만들게 되면 

해당 변수에 그 객체의 전체

모든게 들어 있다고 생각하면 된다.

그래서 만들자마자 생성자가 실행이 되어버린다.


class명 뒤에 *을 붙여서 변수를 만들면

해당 class에 대한 주소만을 변수에 담을 수 있다고 생각하자.

일단 더미 값이 들어가 있을 텐데

이 변수에 'new class명' 하게 되면

이것이 바로 동적 할당이다.

damagochi라는 class가 있고

헤더에 damagochi.h를 include하여

'damagochi* dam;' 라고 변수 선언 해주고

생성자에서 'dam = new damagochi;' 라 해주면

이때 damagochi 클래스의 생성자가 실행이 된다.

포인터 변수로의 접근은 'dam->함수나 변수'로 가능해진다.

(일반 변수라면 'dam.함수나 변수')


생성자, 소멸자 실행 차이를 확인해보자.

main이 되는 class에서 참조할 class의 이름 헤더와

이름의 변수를 그냥 참조 했을 시 어떻게 되는지 같이 확인하겠다.


mainGame이라는 class에서 damagochi라는 class를 가져다 쓰고자 한다.


차이를 파악하기 위해

mainGame과 damagochi의 생성자, 소멸자에 cout으로 표시를 해두었다.


포인터 변수 없이 class 사용법은 아래와 같다.



damagochi 클래스를 받아오는데 포인터 없이 선언하였다.

위와 같이 선언된 것들은 보통 사용할 때에는 dam. 처럼 

변수명 뒤에 점을 붙이면 damagochi class에 public 으로 

선언해둔 함수 리스트 들이 보인다.


하지만 실행했을 때 차이를 확인해볼 수 있다.



main이 되는 class는 mainGame인데

damagochi class가 먼저 생성되고 소멸자도 mainGame보다 늦게 된다.

이는 나중에 문제가 될 여지가 있을 수 있다고 생각되어진다.

(가능성의 얘기지 실제 문제가 된 것을 본것은 아니다. 

공부 중이므로 잘못된것은 알려주길 바란다.)


그럼 포인터로 하면 어떻게 될까?

아래처럼 class명 뒤에 *를 붙여 보았다.



결과는 

damagochi class에 대한 생성자와 소멸자가 나타나지 않는다.


new 로 동적 할당 하지 않는 이상 damagochi의 생성자가 나오지 않고

delete dam;을 하지 않으면 소멸자가 나타나지 않는다.


동적할당 하지 않아도

dam 변수명에 -> 로 접근하면 

damagochi class의 함수들이 나타나기는하지만

보통 초기화가 되지 않은 변수를 참조하게 되므로

안전하게 동적할당을 해주고 

생성자에서 변수들을 초기화 하거나

별도의 init()함수를 만들어서 init()을 먼저 호출한 뒤

사용해주기로 하자.


-------------------------------------

이 글은 정리 겸 차이를 적어 기억하고자 하는 글입니다.

틀린부분이 있으면 알려주시기 바랍니다. 

근거와 출처가 존재하는 가르침은 환영합니다. 감사합니다.