4. 사용자 정의 메시지
윈도우즈에서의 사용자의 입력은 이벤트를 발생시키고 그 때마다 이벤트 통지 메시지가 메시지 큐로 들어가고 이벤트가 발생한 응용 프로그램에 메시지가 전달된다. 이런 윈도우즈 메시지 외에도 모든 차일드 콘트롤들도 각각의 상태에 따라 고유한 Notification 메시지를 발생시키고 부모 윈도우에 그 메시지가 전달된다. 그래서 윈도우즈는 이벤트와 메시지 중심의 운영체제라고 부르는 것이다.
윈도우에서 발생할 수 있는 사건들이 워낙 다양하다보니 각 사건들에 할당된 메시지의 수도 많을 수 밖에 없다. 모든 메시지는 컴퓨터가 인식할 수 있는 상수로 정의된 고유 ID를 가지고 있으며 윈도우즈는 이들 메시지 ID 상수의 범위를 체계적으로 구별해 놓고 있다. 다음은 메시지 ID로 사용되는 상수들의 범위이다.
| 메시지 범위 |
#define WM_USER 0x0400 // 사용자 정의 메시지 0 ~ WM_USER - 1 윈도우즈에서 사용하기 위해 예약된 메시지들 |
위에서 보면 윈도우즈에서 사용되고 있는 메시지와 장차 사용하기 위해 예약해둔 메시지들이 포함되는 범위와 겹치지 않게 사용자가 자신을 위한 메시지를 만들어 사용할 수 있도록 일정 범위를 비워두고 있으며 그 범위는 0x0400 ~ 0x7FFF까지 임을 알 수 있다.
사용자 정의 메시지는 보통 응용 프로그램에서 다음 형태로 정의하게 되는데 'X'는 정수값이다.
#define WM_MYMESSAGE WM_USER + X
사용자 정의 메시지의 범위가 0x0400 ~ 0x7FFF이므로 'X'는 0 ~ 31743 까지 가능한데 이 얘기는 곧 사용자 정의 메시지를 3만개 이상 만들 수 있다는 뜻이 된다. (참고: 0x7FFF - 0x0400 = 31743 )
사용자 메시지는 응용 프로그램에서 공식적인 윈도우즈 메시지 외에 사적인 용도로 메시지를 사용키 위해 정의하게 되는데 윈도우즈 시스템과 응용 프로그램 또는 응용 프로그램과 응용 프로그램 간에 메시지를 주고 받아야 할 필요가 있을 때 사용한다.
ECR TRAY에서는 NOTIFYICONDATA 구조체를 설명할 때도 잠깐 언급했듯이 트레이 아이콘에서 마우스 클릭 이벤트가 발생했을 때 윈도우즈 시스템이 이를 ECR TRAY에 알려 주기 위해 이 메시지를 사용하게 된다.
| ※ 질문?: WM_LBUTTONUP등과 같은 마우스 클릭 메시지를 사용하면 안되는가? |
| 궁극적으로 이 질문은 사용자 정의 메시지의 필요성을 더욱 확실하게 만든다. 물론 윈도우즈는 작업표시줄로부터 마우스 클릭 메시지를 받을 것이다. 이때 클릭 위치를 판단하여 특정 트레이 아이콘 영역 위라면 그 아이콘을 추가한 응용 프로그램에 메시지를 보내 주어야 하는데 만약 WM_LBUTTONUP 메시지를 그대로 보냈다고 한다면 응용 프로그램은 혼란에 빠진다. 자, 왼쪽 마우스 버튼이 눌렸다 놓였는데 이 메시지가 응용 프로그램의 창 내부에서 발생한 것인지 트레이 아이콘에서 발생한 것인지 어떻게 알 것인가? 따라서 사용자 정의 메시지를 새로 만들어 윈도우즈로 하여금 사건이 발생하면 그 메시지를 보내게 하고 응용 프로그램은 그 메시지를 처리하는 핸들러에서 관련 작업을 처리하면 간단해 지는 것이다. |
트레이 아이콘에서 마우스 클릭 이벤트가 발생했을 때 미리 약속한 사용자 정의 메시지를 보내는 것은 윈도우즈가 알아서 할 일이다. 응용 프로그램에서는 단지 그 메시지 핸들러를 작성해 두고 핸들러가 호출되기만을 기다리면 된다.
그럼 사용자 정의 메시지 핸들러는 어떻게 추가할 것인가? 무작정 클래스위저드를 실행한다면 이내 실망하게 될 것이다. 사용자 정의 메시지란 윈도우즈 입장에서 보면 임의의 메시지이기 때문에 클래스위저드의 메시지 목록엔 나타나지 않는다.
MFC에는 몇가지 형태의 사용자 정의 핸들러를 만들 수 있는 매크로가 있는데 그 중 WM_USER ~ 0x7FFF 범위의 사용자 정의 메시지를 처리하기 위한 핸들러를 메시지 맵 안에서 정의하는 매크로가 ON_MESSAGE 이다. 이 매크로와 매크로에서 정의하는 핸들러 함수의 원형은 다음과 같다.
| ON_MESSAGE 매크로와 사용자 정의 메시지 핸들러의 원형 |
ON_MESSAGE( message, memberFxn )message : 사용자 정의 메시지 ID afx_msg LONG memberFxn( UINT, LONG ); |
메시지 맵에 이 매크로를 추가하는 일은 여러분이 직접 해야 하며 핸들러를 추가할 클래스의 소스파일을 약간 수정하면 된다. 수정하는 방법은 다음과 같다.
먼저 사용자 정의 메시지를 define 한다. 여기서는 메시지 id WM_TRAYNOTIFY를 'WM_USER + 100'으로 정의했다. '+100'의 정수는 겹치지 않고 범위내에만 든다면 어떤 값을 써도 좋다. 그리고 나서 핸들러를 추가할 클래스의 메시지 맵 내부에 아래처럼 매크로를 작성한다. 의미는 이미 알고 있듯이 WM_TRAYNOTIFY 메시지가 발생했을 때 OnTrayNotification() 핸들러가 호출되도록 한다는 것이다.
| ON_MESSAGE 매크로 작성 (1) - cpp 파일의 메시지 맵 수정 |
#define WM_TRAYNOTIFY WM_USER + 100 // 사용자 정의 메시지 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) |
메시지 정의와 매크로 작성이 끝났으면 헤더 파일에 핸들러의 원형을 추가해 준다. 이 원형은 위에서 ON_MESSAGE 매크로 설명시 그대로이며 단지 함수 이름만 메시지 맵에서 지정했던 이름으로 바꾸면 된다.
| ON_MESSAGE 매크로 작성 (2) - 헤더파일의 수정 |
class CMainFrame : public CFrameWnd |
마지막으로 핸들러 함수만 작성하면 된다. 위에서는 CMainFrame 클래스를 선택했으니 같은 클래스에 클래스위저드가 만들어 주는 핸들러 형태대로 직접 만들면 된다. 이렇게...
LRESULT CMainFrame::OnTrayNotification( WPARAM wParam, LPARAM lParam )
{ ...
// 여기에 코드 작성
}
| 번호 | 제목 | 닉네임 | 조회 | 등록일 |
|---|---|---|---|---|
| 171 |
[MFC] 단축키 설정 방법
|
![]() |
176 | 2011-11-18 |
| 170 | [MFC] 다중 시리얼 포트 제어 | ![]() |
151 | 2011-11-17 |
| 169 | MFC EditBOX 자동스크롤 하기(세로스크롤) | ![]() |
168 | 2011-11-17 |
![]() |
ON_MESSAGE | ![]() |
141 | 2011-11-17 |
| 167 |
MFC로 시리얼 통신 프로그램 만들기
|
![]() |
1096 | 2011-07-21 |
| 166 |
자작로또프로그램(미완성)
|
![]() |
1629 | 2010-10-21 |
| 165 | API로 테트리스 만들기(미완성) | 재여리 |
1218 | 2009-08-21 |
| 164 | DestroyWindow 와 PostQuitMessage의 차이 | 재여리 |
2247 | 2009-08-17 |
| 163 | lstrlen 과 strlen에서 'l"의 차이는 무엇인가? | 재여리 |
2079 | 2009-08-13 |
| 162 | C언어 고급 문제 사이트 [1] | 재여리 |
2073 | 2009-08-12 |
| 161 | Linked list (array & pointer) | 재여리 |
995 | 2006-05-08 |
| 160 |
[영상처리C++] 이미지 Edge Detection 프로그램
|
재여리 |
1753 | 2009-08-12 |
| 159 |
[영상처리C++] 이미지 뼈대 추출하기
|
재여리 |
1637 | 2009-08-12 |
| 158 |
[영상처리C++]관련 이미지 추출하기
|
재여리 |
1797 | 2009-08-12 |
| 157 |
Batch_shell 명령어 정리
|
재여리 |
1061 | 2009-07-20 |


