[펌] Message Map에 대한 재확인..^^

MFC에 처음 발을 들여 놓을 때 확실히 봤던 부분임에도-
완죤히! 다 까서 먹고는 왜 OnPaint는 virtual function이 아닐까 하면서 삽질생각하다가-
누군가에게 묻고 같이 삽질 생각하던 끝에-
귀찮아서 가만있으려는데-

누군가가 보내주어서 재확인된 답...^^



________________________________________________________________________
출처: http://cafe.naver.com/cnote.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=93
메시지멥(Message Map)에 대한 짧은 생각
-----------------------------------------------------


윈도우의 메시지를 처리할 때 예전에는 윈도우 프로시저에서
중첩된 if문과 switch 문을 사용했다.
C 언어를 사용하면 이런 방식을 사용할 수 밖에 없었다.

MFC 에서는 message map 을 사용하기 때문에 메지지를 처리하는 switch 문을 볼 수가 없다.

message map 은 메시지와 헨들러를 일대일로 연결시켜주는 테이블로 생각할 수가 있다.

구현하는 방식은 여러가지가 있겠지만,
흔히들 하는 이야기가 virtual function에 대한 이야기이다.

만약 message map을 virtual function으로 구현한다면
함수 하나당 4bytes 가 필요하다고 한다.

클래스에 함수가 하나만 있을리 만무하다.
작은 클래스라도 수십개정도가 필요하다.

프로그램을 만드는데 클래스를 하나만 사용할리가 만무하다.
작은 프로그램이라도 수십개의 클래스를 사용한다.

예를 들어 20개의 메시지헨들러를 가진 클래스를 20개 사용하는
프로그램이 있다면 vtable에만 1600bytes 를 사용하게된다.

메시지멥만을 구현하는데 메모리에 너무 큰 대가를 치르게된다.
그래서 virtual function을 사용하는 vtable 방식을 사용하지 않았다고 한다.

그런데 초보인 내가 보기에 MFC의 메시지멥은 암호와 같다.

클래스 선언부분에서 한줄 써주고

 DECLARE_MESSAGE_MAP()

정의 부분에서 딸랑 두 줄 뿐이다.

 BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
 END_MESSAGE_MAP()

무섭다.
이속에 엄청난 양의 if문과 switch 문이 있다는 말인가.

내가 이해 할 수 있는 C++ code는 배열, 변수, 함수.. 이런것 뿐이다.
예를 들면

 static const int mE[];

 const int mE[] = {0,1,2,3};

뭐 이런거다. 말하자면 쉬운코드.
내친김에 쫌 더써본다.

// 선언
class CMyApp : public CWinApp
{
public:
 static const int mE[];
 int mm;
 int GetMM();
}

//생성자
CMyApp::CMyApp()
{
 const int mE[] = {0,1,2,3};
}

//멤버함수
int CMyApp::GetMM()
{
 return mm;
}

정령 나의 수준으로는 메시지멥을 이해 할 수 없단 말인가.....!


그런데 Afxwin.h를 보면 DECLARE_MESSAGE_MAP()는
 다음과 같이 define되어 있다.

#define DECLARE_MESSAGE_MAP() \
private: \
 static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
 static AFX_DATA const AFX_MSGMAP messageMap; \
 static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); \
 virtual const AFX_MSGMAP* GetMessageMap() const; \

음.
_messageEntries[]라는 배열하나 선언해주고.
messageMap 라는 변수선언 하나.
Get으로 시작하는 함수 두개라..
별거아니네..

어라.
AFX_MSGMAP_ENTRY를 int로 바꾸면 배열선언은 내꺼랑 비슷한걸...

BEGIN_MESSAGE_MAP 과
END_MESSAGE_MAP 은
다음과 같이 define되어 있다.

#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
 const AFX_MSGMAP* PASCAL theClass::_GetBaseMessageMap() \
  {
   return &baseClass::messageMap;
  } \
 const AFX_MSGMAP* theClass::GetMessageMap() const \
  {
   return &theClass::messageMap;
  } \
 AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \
 { &theClass::_GetBaseMessageMap, &theClass::_messageEntries[0] }; \
 AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \
 { \
#define END_MESSAGE_MAP() \
  {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
 };


음...
_GetBaseMessageMap()함수는 messageMap을 리턴하는구나.
GetMessageMap()함수도 messageMap을 리턴하는 구나.
내가 쓴 GetMM()함수랑 똑같네.

messageMap이라는 변수를 초기화 시켜주고..
음.
END_MESSAGE_MAP()은 배열에 뭘하나 집어 넣고 배열을 닫는구나.
아마 0 이 네개씩이나 되고 AfxSig_end에 end라는 글자를 보니
배열의 끝을 표시하는것 같군....

그럼 이렇게 써주면

BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
 ON_WM_PAINT()
END_MESSAGE_MAP()

ON_WM_PAINT()가 배열원소를 하나 넣어준다는 얘기가 되는것인가.
어디보자. ON_WM_PAINT()를 Find in Files...명령으로 찾아보면...
Afxmsg_.h에 이렇게 define되어 있군.

#define ON_WM_PAINT()
 { WM_PAINT, 0, 0, 0, AfxSig_vv,
 (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(void))&OnPaint },

뭔지 모르지만 괄호로 묶여있는걸보니 배열의 원소가 틀림없다. 
요소가 여러개인걸 보니 struct 인가보군.
분명히 AFX_MSGMAP_ENTRY 타입일거야.
배열 _messageEntries[]가 AFX_MSGMAP_ENTRY 타입이니까.

음..
메시지멥..
메시지와 헨들러 함수를 연결시켜 준다더니..
WM_PAINT 는 윈도우 메시지가 틀림없고...
OnPaint 는 함수인것 같군..

그런데 뜯어보면 별거 아닌데,

DECLARE_MESSAGE_MAP()
BEGIN_MESSAGE_MAP
END_MESSAGE_MAP()

의 소스코드가 이렇게 어지럽게 보이는 이유는 무엇이란 말인가.
아마도 이런이유가 아닐까.

1. 배열의 크기
_messageEntries[] 배열의 크기를 고정하지 않고 있다.
크기를 가변적으로 조정할 수 있는것이다.

2. 구조체의 사용
         AFX_MSGMAP_ENTRY
         AFX_MSGMAP
         AFX_PMSG
  생전 처음보는 이런 struct가 어지럽게 한다.


3. 초보에게 생소한 keyword 사용
static
const
PASCAL
AFX_COMDAT  == __declspec(selectany)

4. line-continuation character ('\') 사용
  #define 문은 한줄에 다써야 한다.
   그래서 줄연결문자('\')를 사용했다. 그래서 어지럽다.

   초보인 내가 생각하는 메시지멥은 구조체를 집어넣는 배열이다.
-----------------------------------------------------------


 

  

이 글과 관련있는 글을 자동검색한 결과입니다 [?]

by 울트라건맨 | 2007/03/20 18:40 | 개발 툴/언어/기타 비평 | 트랙백(1) | 덧글(3)

트랙백 주소 : http://gunman.egloos.com/tb/1531036
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from Alones's world at 2007/03/26 13:26

제목 : [펌][펌] Message Map에 대한 재확인..^^
우리는 가끔 원리를 알아할 필요가 있다. ^^;은닉이라는 이름으로 무작정 쓰기에는 만든이들의 effort와 technique들이 너무 아깝다.http://gunman.egloos.com/1531036...more

Commented by alones at 2007/03/26 13:22
hi요. 서두만 읽었는데 암튼 까만책에 나오는 내용을 거의 그대로 쓴 듯 하군요.
암튼.~

inside들이 우리 같이 (조잡한) fw을 만들 땐 많은 참조가 되는 것 같습니다.

Commented by 울트라건맨 at 2007/03/27 00:05
아..들렀다 가셨네요...^^~
Commented by alones at 2007/03/29 08:42
흐흐흐 rss로 구독하고 있숩니다~

:         :

:

비공개 덧글

◀ 이전 페이지다음 페이지 ▶