WM_ 으로 시작하는 윈도우 메시지를 만들었을때, MFC에서 제공하는 On_ 으로 처리되는 함수들이
자동으로 생성되는 것 보면 편해보이기 까지한다.
이를 수동적으로 생성하는 방법을 알아보자.

WM_USERDEFINE 이라는 메시지가 있다고 하자.
사용자가 만든 메시지여서, 실제 MFC Wizard로 만들수 없다.
게다가, MessageMap 매크로 안에 넣으려해도, afxmsg OnUserDefine 을 만들려고 하면
그 함수와 Message와 연결 할 방법이 없다.
이를 처리하려면, MessageMap 안에서 함수와 Message를 연결해주는 무언가를 만들어 줘야 한다.
그리고, 각 함수를 살펴보면, 윈도우 메시지를 그냥 받는 것이 아니고 각 유형 별로 파라미터로 받는 경우가 있다.
예를 들자면 OnLButtonDown(UINT nFlags, CPoint point) 같은 것은 nFlags 나 point를 받는다.
하지만, 현재는 파라미터가 없는 버젼만을 생각하여 만들도록 하자.

WM_USERDEFINE을 가지고 한번 만들어 보자.

.H 을 열어 보면,
   //{{AFX_MSG(CUserDefine)
   //}}AFX_MSG
   DECLARE_MESSAGE_MAP()
이라는 부분이 있다.
실제로 "//{{AFX_MSG(CUserDefine)",  "//}}AFX_MSG" 이 두 문장은 단순히 클래스 위자드에서 사용하기 위해
만들어진 내용이므로 삭제해도 무방하다. 단 클래스 위자드에 의존하는 분들은 이 부분을 지우게 되면 새로운 메시지
처리를 추가/삭제/수정이 절대 불가능하니, 조심한다.
일단, "//}}AFX_MSG" 아래에다 자신이 만든 메시지 핸들러 함수를 선언한다.
afx_msg 를 맨 앞에 붙이고 그 뒤에 함수 선언을 한다. On 이라는 이름이 붙은 형태의 함수를 만든다.
   afx_msg OnUserDefine()
그러면 .H에서 다 기록한 것이다.

.CPP를 열어보면,
   BEGIN_MESSAGE_MAP(CUserDefine,CWnd )
           //{{AFX_MSG_MAP(CUserDefine)
           ON_WM_PAINT()        
           //}}AFX_MSG_MAP
   END_MESSAGE_MAP()
가 보일 것이다. 이 안이 바로 Message와 함수를 연결해주는 부분이다. 그러나 그 안에 보면 단순히
ON_WM_PAINT()와 같은 단순 무식한 한줄의 함수만 보인다. 그렇다면 이를 어떻게 해야 하는 것인가?
간단하다. ON_WM..  시리즈를 직접 만드는 것이다.
   #define ON_WM_USERDEFINE()
   { WM_USERDEFINE, 0, 0, 0, AfxSig_vv,
   (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(void))&OnUserDefine },
위의 세줄을 넣어준다.  이 부분이 바로 ON_WM 시리즈의 실체가 된다.
실제 사용되는 WM_ 메시지를 넣고 맨 뒤의 On.. 시리즈 함수를 대체해서 만들어 주면 된다.
위의 예제는 WM_USERDEFINE을 기준으로 넣었다. 그러면 BEGIN_... 안에다 자신이 만든것을 넣어 주면 된다.
   BEGIN_MESSAGE_MAP(CUserDefine,CWnd )
           //{{AFX_MSG_MAP(CUserDefine)
           ON_WM_PAINT()        
           //}}AFX_MSG_MAP
                ON_WM_USERDEFINE()
   END_MESSAGE_MAP()
이렇게 하면 모든것이 해결!

파라미터가 있다면 그 뒤에 다시 생각해보도록한다.
참고로 AfxSig_xxx 라는 값을 이용하면 다양한 형태로 구성할 수 있는 데, 이는 정해진 내용만 적용가능하다.
        AfxSig_bD,      // BOOL (CDC*)
        AfxSig_bb,      // BOOL (BOOL)
        AfxSig_bWww,    // BOOL (CWnd*, UINT, UINT)
        AfxSig_hDWw,    // HBRUSH (CDC*, CWnd*, UINT)
        AfxSig_hDw,     // HBRUSH (CDC*, UINT)
        AfxSig_iwWw,    // int (UINT, CWnd*, UINT)
        AfxSig_iww,     // int (UINT, UINT)
        AfxSig_iWww,    // int (CWnd*, UINT, UINT)
        AfxSig_is,      // int (LPTSTR)
        AfxSig_lwl,     // LRESULT (WPARAM, LPARAM)
        AfxSig_lwwM,    // LRESULT (UINT, UINT, CMenu*)
        AfxSig_vv,      // void (void)

        AfxSig_vw,      // void (UINT)
        AfxSig_vww,     // void (UINT, UINT)
        AfxSig_vvii,    // void (int, int) // wParam is ignored
        AfxSig_vwww,    // void (UINT, UINT, UINT)
        AfxSig_vwii,    // void (UINT, int, int)
        AfxSig_vwl,     // void (UINT, LPARAM)
        AfxSig_vbWW,    // void (BOOL, CWnd*, CWnd*)
        AfxSig_vD,      // void (CDC*)
        AfxSig_vM,      // void (CMenu*)
        AfxSig_vMwb,    // void (CMenu*, UINT, BOOL)

        AfxSig_vW,      // void (CWnd*)
        AfxSig_vWww,    // void (CWnd*, UINT, UINT)
        AfxSig_vWp,     // void (CWnd*, CPoint)
        AfxSig_vWh,     // void (CWnd*, HANDLE)
        AfxSig_vwW,     // void (UINT, CWnd*)
        AfxSig_vwWb,    // void (UINT, CWnd*, BOOL)
        AfxSig_vwwW,    // void (UINT, UINT, CWnd*)
        AfxSig_vwwx,    // void (UINT, UINT)
        AfxSig_vs,      // void (LPTSTR)
        AfxSig_vOWNER,  // void (int, LPTSTR), force return TRUE
        AfxSig_iis,     // int (int, LPTSTR)
        AfxSig_wp,      // UINT (CPoint)
        AfxSig_wv,      // UINT (void)
        AfxSig_vPOS,    // void (WINDOWPOS*)
        AfxSig_vCALC,   // void (BOOL, NCCALCSIZE_PARAMS*)
        AfxSig_vNMHDRpl,    // void (NMHDR*, LRESULT*)
        AfxSig_bNMHDRpl,    // BOOL (NMHDR*, LRESULT*)
        AfxSig_vwNMHDRpl,   // void (UINT, NMHDR*, LRESULT*)
        AfxSig_bwNMHDRpl,   // BOOL (UINT, NMHDR*, LRESULT*)
        AfxSig_bHELPINFO,   // BOOL (HELPINFO*)
        AfxSig_vwSIZING,    // void (UINT, LPRECT) -- return TRUE

        // signatures specific to CCmdTarget
        AfxSig_cmdui,   // void (CCmdUI*)
        AfxSig_cmduiw,  // void (CCmdUI*, UINT)
        AfxSig_vpv,     // void (void*)
        AfxSig_bpv,     // BOOL (void*)

        // Other aliases (based on implementation)
        AfxSig_vwwh,                // void (UINT, UINT, HANDLE)
        AfxSig_vwp,                 // void (UINT, CPoint)
        AfxSig_bw = AfxSig_bb,      // BOOL (UINT)
        AfxSig_bh = AfxSig_bb,      // BOOL (HANDLE)
        AfxSig_iw = AfxSig_bb,      // int (UINT)
        AfxSig_ww = AfxSig_bb,      // UINT (UINT)
        AfxSig_bv = AfxSig_wv,      // BOOL (void)
        AfxSig_hv = AfxSig_wv,      // HANDLE (void)
        AfxSig_vb = AfxSig_vw,      // void (BOOL)
        AfxSig_vbh = AfxSig_vww,    // void (BOOL, HANDLE)
        AfxSig_vbw = AfxSig_vww,    // void (BOOL, UINT)
        AfxSig_vhh = AfxSig_vww,    // void (HANDLE, HANDLE)
        AfxSig_vh = AfxSig_vw,      // void (HANDLE)
        AfxSig_viSS = AfxSig_vwl,   // void (int, STYLESTRUCT*)
        AfxSig_bwl = AfxSig_lwl,
        AfxSig_vwMOVING = AfxSig_vwSIZING,  // void (UINT, LPRECT) -- return TRUE

        AfxSig_vW2,                 // void (CWnd*) (CWnd* comes from lParam)
        AfxSig_bWCDS,               // BOOL (CWnd*, COPYDATASTRUCT*)
        AfxSig_bwsp,                // BOOL (UINT, short, CPoint)
위에서 보듯이 딱 정해진 기능만 하므로... 그 외의 것이라면 다시 생각해보도록 한다.

PS. 혹여 AfxSig_lwl 를 사용하면 WPARAM, LPARAM 이니까... 다양하게 이용할 수 있을지도 모르겠다.

728x90

+ Recent posts