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 이니까... 다양하게 이용할 수 있을지도 모르겠다.
자동으로 생성되는 것 보면 편해보이기 까지한다.
이를 수동적으로 생성하는 방법을 알아보자.
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