[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 2편
mfc & winAPI
2015. 8. 19. 13:57
출처 : http://www.tipssoft.com/bulletin/tb.php/FAQ/65
4. MFC 프로그램에서 WM_NOTIFY 메시지 사용하기
일반적인 방식으로 생각한다면 WM_NOTIFY 메시지에 대한 핸들러는 OnNotify 일것입니다.
CWnd 클래스를 살펴보시면 아시겠지만 OnNotify라는 멤버함수가 있습니다. 하지만, 우리는
이 함수를 등록해서 사용하지는 않습니다. 왜냐하면 이 함수로는 모든 통보 메시지가
전달되기 때문에 OnNotify 함수에서 코드를 작성하면 C++적인 의미가 다소 줄어들수 있으므로
이 함수를 등록해서 사용하지 않고 개별적인 처리루틴을 사용하도록 권장하고 있습니다.
( OnNotify 함수를 등록하고 if문 또는 switch문을 사용해서 각 메시지를 분류하여 사용하기도
하는데, 이런 형식은 C 방식에서 많이 사용하는 방법입니다. )
CWnd 클래스를 살펴보시면 아시겠지만 OnNotify라는 멤버함수가 있습니다. 하지만, 우리는
이 함수를 등록해서 사용하지는 않습니다. 왜냐하면 이 함수로는 모든 통보 메시지가
전달되기 때문에 OnNotify 함수에서 코드를 작성하면 C++적인 의미가 다소 줄어들수 있으므로
이 함수를 등록해서 사용하지 않고 개별적인 처리루틴을 사용하도록 권장하고 있습니다.
( OnNotify 함수를 등록하고 if문 또는 switch문을 사용해서 각 메시지를 분류하여 사용하기도
하는데, 이런 형식은 C 방식에서 많이 사용하는 방법입니다. )
MFC에서는 기본적으로 메시지별로 핸들러 함수를 사용하도록 되어있습니다. 따라서 각
통보 메시지별로 핸들러를 등록할수 있는데, 메시지 맵에 아래와 같이 등록하시면 됩니다.
통보 메시지별로 핸들러를 등록할수 있는데, 메시지 맵에 아래와 같이 등록하시면 됩니다.
ON_NOTIFY( notify_code, control_id, HandlerFunction )
위와 같이 정의하면 control_id를 가진 컨트롤에서 발생된 통보 메시지 중에 세부 코드가
notify_code (NMHDR 구조체의 code 항목에 저장된 값) 인 경우, HandlerFunction 함수를
수행하겠다는 뜻이 됩니다.
notify_code (NMHDR 구조체의 code 항목에 저장된 값) 인 경우, HandlerFunction 함수를
수행하겠다는 뜻이 됩니다.
예를 들어, 리스트 뷰 컨트롤이 있고 키를 눌렀을때 OnMyListViewKeyDown 이라는 함수를
호출하고 싶다면 아래와 같이 사용하시면 됩니다.
호출하고 싶다면 아래와 같이 사용하시면 됩니다.
( 해당 리스트 뷰 컨트롤의 아이디 : IDC_MY_LIST_VIEW 로 가정 )
ON_NOTIFY( LVN_KEYDOWN, IDC_MY_LIST_VIEW, OnMyListViewKeyDown )
사실, 리스트 뷰, 트리 뷰 등과 같이 잘 알려진 컨트롤의 통보 메시지는 클래스위저드를
이용해서 등록가능하기 때문에 위 사항을 직접 입력하실 필요는 없습니다. ^^;; 하지만,
자신이 새롭게 만든 컨트롤인 경우에는 클래스위저드의 지원을 받을 수 없기 때문에
직접 메시지맵에 입력하셔야 합니다.
이용해서 등록가능하기 때문에 위 사항을 직접 입력하실 필요는 없습니다. ^^;; 하지만,
자신이 새롭게 만든 컨트롤인 경우에는 클래스위저드의 지원을 받을 수 없기 때문에
직접 메시지맵에 입력하셔야 합니다.
ON_NOTIFY 매크로의 3번째에 입력한 핸들러는 어떻게 구성되는지에 대해서 알아보겠습니다.
먼저 함수의 원형은 아래와 같습니다.
먼저 함수의 원형은 아래와 같습니다.
afx_msg void HandlerFunction( NMHDR * pNotifyStruct, LRESULT * result );
일반적으로 클래스위저드를 사용해서 등록하게 되면 위 코드가 해당 클래스의 헤더파일 내에
자동으로 추가됩니다. 그리고 아래와 같이 해당 클래스의 소스 파일에는 핸들러 코드가 추가됩니다.
자동으로 추가됩니다. 그리고 아래와 같이 해당 클래스의 소스 파일에는 핸들러 코드가 추가됩니다.
void 해당클래스::HandlerFunction( NMHDR * pNotifyStruct, LRESULT * result )
{
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
{
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
위에서 예를 든것처럼 리스트 뷰 컨트롤이 있고 키를 눌렀을때 OnMyListViewKeyDown 이라는 함수를
호출하고 싶다고 선택했다면 아래와 같이 핸들러 루틴이 추가될 것입니다.
( 클래스위저드가 자동으로 추가해 줍니다. )
호출하고 싶다고 선택했다면 아래와 같이 핸들러 루틴이 추가될 것입니다.
( 클래스위저드가 자동으로 추가해 줍니다. )
void 해당클래스::OnMyListViewKeyDown( NMHDR * pNotifyStruct, LRESULT * result )
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNotifyStruct;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNotifyStruct;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
위 코드에서 보시면 알수 있듯이 리스트 뷰 컨트롤의 LVN_KEYDOWN 통보 메시지는 NMHDR 구조체를
확장해서 LV_KEYDOWN 이라는 구조체를 사용하고 있기 때문에 클래스위저드가 자동으로 형변환까지
코드를 생성시켜 줍니다. 만약, 이 강좌의 1편에서처럼 자신이 만든 클래스에 통보 메시지를 보내는
코드를 보냈고 해당 통보 메시지가 MyNotifyData 라는 구조체를 사용했다면 형변환을 아래처럼 직접
하시면 됩니다.
확장해서 LV_KEYDOWN 이라는 구조체를 사용하고 있기 때문에 클래스위저드가 자동으로 형변환까지
코드를 생성시켜 줍니다. 만약, 이 강좌의 1편에서처럼 자신이 만든 클래스에 통보 메시지를 보내는
코드를 보냈고 해당 통보 메시지가 MyNotifyData 라는 구조체를 사용했다면 형변환을 아래처럼 직접
하시면 됩니다.
MyNotifyData *p_my_data = (MyNotifyData *)pNotifyStruct;
당연한 이야기겠지만 통보 메시지 데이터 자체가 NMHDR을 이용한다면 형변환 없이 pNotifyStruct 변수를
바로 사용하시면 됩니다.
바로 사용하시면 됩니다.
5. 동일한 통보 메시지를 일괄 처리하기
자신이 하나의 대화상자에 리스트 뷰 컨트롤을 3개를 만들고 각 아이디를 IDC_MY_LIST_VIEW1,
IDC_MY_LIST_VIEW2, IDC_MY_LIST_VIEW3로 부여했다고 합시다. ( 각 컨트롤의 번호는
resource.h 파일에서 확인했을 때, 순차적으로 배열되어있다고 가정하겠습니다. ) 대화상자에서
각 컨트롤의 LVN_KEYDOWN 통보 메시지를 일괄적으로 처리해야 하는 경우, 핸들러를 3개
등록하지 않고 1개만 등록해서 처리하는 방법에 대해서 알아보도록 하겠습니다.
IDC_MY_LIST_VIEW2, IDC_MY_LIST_VIEW3로 부여했다고 합시다. ( 각 컨트롤의 번호는
resource.h 파일에서 확인했을 때, 순차적으로 배열되어있다고 가정하겠습니다. ) 대화상자에서
각 컨트롤의 LVN_KEYDOWN 통보 메시지를 일괄적으로 처리해야 하는 경우, 핸들러를 3개
등록하지 않고 1개만 등록해서 처리하는 방법에 대해서 알아보도록 하겠습니다.
먼저 메시지 맵에 아래와 같은 메크로를 등록합니다.
ON_NOTIFY_RANGE( notify_code, start_control_id, end_control_id, HandlerFunction )
위 사항을 적용해서 등록한다면 아래와 같습니다.
ON_NOTIFY_RANGE( LVN_KEYDOWN, IDC_MY_LIST_VIEW1,
MY_LIST_VIEW3, OnMyListViewKeyDown)
MY_LIST_VIEW3, OnMyListViewKeyDown)
Range 관련 메크로는 클래스위저등의 지원을 받지 못하기 때문에 직접 입력하셔야 합니다.
해당 클래스의 헤더파일에 추가되는 OnMyListViewKeyDown 함수의 형식은 ON_NOTIFY 때와
약간의 차이가 생기는 아래와 같습니다.
약간의 차이가 생기는 아래와 같습니다.
afx_msg void HandlerFunction( UINT control_id, NMHDR * pNotifyStruct, LRESULT * result );
위와 같이 control_id라는 인자가 하나 추가되는데, 그 이유는 3개의 컨트롤에서 발생된
통보 메시지가 일괄적으로 이 함수를 사용하기 때문에 어떤 컨트롤에서 이 메시지가
전달되었는지 확인할수 있도록 통보 메시지를 발생시킨 컨트롤의 아이디가 추가된 것입니다.
통보 메시지가 일괄적으로 이 함수를 사용하기 때문에 어떤 컨트롤에서 이 메시지가
전달되었는지 확인할수 있도록 통보 메시지를 발생시킨 컨트롤의 아이디가 추가된 것입니다.
'mfc & winAPI' 카테고리의 다른 글
마우스 이벤트 중복 클릭 방지 함수 (0) | 2017.05.29 |
---|---|
[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편 (0) | 2015.08.19 |
#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때 (0) | 2014.04.11 |
BOOL PreTranslateMessage(MSG* pMsg) (0) | 2014.03.21 |
분할 윈도우 중 하나에 접근하는 방법 (0) | 2014.02.10 |