메시지 및 메시지 큐 정보

MS-DOS 기반 애플리케이션과 달리 Windows 기반 애플리케이션은 이벤트 기반입니다. 입력을 얻기 위해 명시적 함수 호출(예: C 런타임 라이브러리 호출)을 수행하지 않습니다. 대신 시스템이 입력을 전달할 때까지 기다립니다.

시스템은 애플리케이션의 모든 입력을 애플리케이션의 다양한 창에 전달합니다. 각 창에는 창에 대한 입력이 있을 때마다 시스템에서 호출하는 창 프로시저라는 함수가 있습니다. 창 프로시저는 입력을 처리하고 컨트롤을 시스템에 반환합니다. 창 프로시저에 대한 자세한 내용은 창 프로시저를 참조하세요.

최상위 창이 몇 초 이상 메시지에 응답하지 않는 경우 시스템은 창이 응답하지 않는 것으로 간주합니다. 이 경우 시스템은 창을 숨기고 Z 순서, 위치, 크기 및 시각적 특성이 동일한 고스트 창으로 바꿉니다. 이렇게 하면 사용자가 이동하거나 크기를 조정하거나 애플리케이션을 닫을 수 있습니다. 그러나 애플리케이션이 실제로 응답하지 않기 때문에 이러한 작업만 사용할 수 있습니다. 디버거 모드에서 시스템은 고스트 창을 생성하지 않습니다.

이 섹션에서는 다음 항목에 대해 설명합니다.

Windows 메시지

시스템은 메시지 형식의 창 프로시저에 입력을 전달합니다. 메시지는 시스템과 애플리케이션 모두에서 생성됩니다. 시스템은 사용자가 입력하거나 마우스를 이동하거나 스크롤 막대와 같은 컨트롤을 클릭할 때와 같이 각 입력 이벤트에서 메시지를 생성합니다. 또한 시스템은 애플리케이션이 시스템 글꼴 리소스 풀을 변경하거나 창 중 하나의 크기를 조정하는 경우와 같이 애플리케이션에서 가져온 시스템의 변경에 대한 응답으로 메시지를 생성합니다. 애플리케이션은 작업을 수행하거나 다른 애플리케이션의 창과 통신하도록 자체 창을 지시하는 메시지를 생성할 수 있습니다.

시스템은 창 핸들, 메시지 식별자 및 메시지 매개 변수라는 두 개의 값의 네 가지 매개 변수 집합이 있는 창 프로시저에 메시지를 보냅니다. 창 핸들은 메시지가 의도된 창을 식별합니다. 시스템은 이를 사용하여 메시지를 수신해야 하는 창 프로시저를 결정합니다.

메시지 식별자는 메시지의 용도를 식별하는 명명된 상수입니다. 창 프로시저는 메시지를 받으면 메시지 식별자를 사용하여 메시지를 처리하는 방법을 결정합니다. 예를 들어 메시지 식별자 WM_PAINT 창의 클라이언트 영역이 변경되었으며 다시 그려야 한다는 것을 창 프로시저에 알립니다.

메시지 매개 변수는 메시지를 처리할 때 창 프로시저에서 사용되는 데이터 또는 데이터의 위치를 지정합니다. 메시지 매개 변수의 의미와 값은 메시지에 따라 달라집니다. 메시지 매개 변수에는 정수, 압축된 비트 플래그, 추가 데이터가 포함된 구조체에 대한 포인터 등이 포함될 수 있습니다. 메시지가 메시지 매개 변수를 사용하지 않는 경우 일반적으로 NULL로 설정됩니다. 창 프로시저는 메시지 식별자를 검사 메시지 매개 변수를 해석하는 방법을 결정해야 합니다.

메시지 유형

이 섹션에서는 두 가지 유형의 메시지에 대해 설명합니다.

System-Defined 메시지

시스템은 애플리케이션과 통신할 때 시스템 정의 메시지를 보내거나 게시합니다. 이러한 메시지를 사용하여 애플리케이션의 작업을 제어하고 애플리케이션이 처리할 입력 및 기타 정보를 제공합니다. 애플리케이션은 시스템 정의 메시지를 보내거나 게시할 수도 있습니다. 애플리케이션은 일반적으로 이러한 메시지를 사용하여 미리 등록된 창 클래스를 사용하여 만든 제어 창의 작업을 제어합니다.

각 시스템 정의 메시지에는 고유한 메시지 식별자와 메시지의 목적을 나타내는 해당 기호 상수(SDK(소프트웨어 개발 키트) 헤더 파일에 정의됨)가 있습니다. 예를 들어 WM_PAINT 상수는 창이 내용을 그리는 것을 요청합니다.

심볼 상수는 시스템 정의 메시지가 속하는 범주를 지정합니다. 상수의 접두사는 메시지를 해석하고 처리할 수 있는 창 유형을 식별합니다. 접두사 및 관련 메시지 범주는 다음과 같습니다.

접두사 메시지 범주 설명서
ABMABN 애플리케이션 데스크톱 도구 모음 셸 메시지 및 알림
ACMACN 애니메이션 컨트롤 애니메이션 컨트롤 메시지애니메이션 컨트롤 알림
BCM, BCN, BMBN Button 컨트롤 단추 컨트롤 메시지단추 컨트롤 알림
CBCBN ComboBox 컨트롤 ComboBox 컨트롤 메시지ComboBox 컨트롤 알림
CBEMCBEN ComboBoxEx 컨트롤 ComboBoxEx 메시지ComboBoxEx 알림
Ccm 일반 제어 컨트롤 메시지
CDM 일반 대화 상자 일반 대화 상자 메시지
Dfm 기본 상황에 맞는 메뉴 셸 메시지 및 알림
Dl 목록 상자 끌기 목록 상자 알림 끌기
DM 기본 푸시 단추 컨트롤 대화 상자 메시지
DTMDTN 날짜 및 시간 선택기 컨트롤 날짜 및 시간 선택기 메시지날짜 및 시간 선택 알림
EMEN 편집 컨트롤 컨트롤 메시지 편집, 컨트롤 알림 편집, 서식 있는 편집 메시지리치 편집 알림
HDMHDN 헤더 컨트롤 헤더 컨트롤 메시지헤더 컨트롤 알림
HKM 핫 키 컨트롤 바로 가기 키 컨트롤 메시지
IPMIPN IP 주소 컨트롤 IP 주소 메시지IP 주소 알림
LBLBN 목록 상자 컨트롤 목록 상자 메시지목록 상자 알림
LM SysLink 컨트롤 SysLink 컨트롤 메시지
LVMLVN 목록 보기 컨트롤 목록 보기 메시지목록 보기 알림
MCMMCN 월 달력 컨트롤 월 일정 메시지월 일정 알림
PBM 진행률 표시줄 진행률 표시줄 메시지
PGMPGN 호출기 컨트롤 호출기 컨트롤 메시지호출기 컨트롤 알림
PSMPSN 속성 시트 속성 시트 메시지속성 시트 알림
RBRBN Rebar 컨트롤 Rebar 제어 메시지Rebar 컨트롤 알림
SBSBN 상태 표시줄 창 상태 표시줄 메시지상태 표시줄 알림
Sbm 스크롤 막대 컨트롤 스크롤 막대 메시지
Smc 셸 메뉴 셸 메시지 및 알림
STMSTN 정적 제어 정적 제어 메시지정적 제어 알림
TBTBN Toolbar 도구 모음 컨트롤 메시지도구 모음 컨트롤 알림
TBMTRBN 트랙바 컨트롤 트랙바 컨트롤 메시지트랙바 컨트롤 알림
TCMTCN 탭 컨트롤 탭 컨트롤 메시지탭 컨트롤 알림
TDMTDN 작업 대화 상자 작업 대화 상자 메시지작업 대화 상자 알림
TTMTTN 도구 설명 컨트롤 도구 설명 컨트롤 메시지도구 설명 컨트롤 알림
TVMTVN 트리 뷰 컨트롤 트리 뷰 메시지트리 뷰 알림
UDMUDN 위쪽 제어 업다운 메시지업다운 알림
Wm 일반
클립보드 메시지
클립보드 알림
일반 대화 상자 알림
커서 알림
데이터 복사 메시지
데스크톱 창 관리자 메시지
장치 관리 메시지
대화 상자 알림
동적 데이터 교환 메시지
동적 데이터 교환 알림
후크 알림
키보드 가속기 메시지
키보드 가속기 알림
키보드 입력 메시지
키보드 입력 알림
메뉴 알림
마우스 입력 알림
여러 문서 인터페이스 메시지
원시 입력 알림
스크롤 막대 알림
타이머 알림
창 메시지
창 알림

일반 창 메시지는 마우스 및 키보드 입력, 메뉴 및 대화 상자 입력, 창 만들기 및 관리, DDE(동적 데이터 교환)에 대한 메시지를 포함하여 다양한 정보와 요청을 다룹니다.

Application-Defined 메시지

애플리케이션은 자체 창에서 사용하거나 다른 프로세스에서 창과 통신하는 데 사용할 메시지를 만들 수 있습니다. 애플리케이션이 자체 메시지를 만드는 경우 메시지를 수신하는 창 프로시저는 메시지를 해석하고 적절한 처리를 제공해야 합니다.

메시지 식별자 값은 다음과 같이 사용됩니다.

  • 시스템은 시스템 정의 메시지에 대해 0x03FF(WM_USER – 1 값)을 통해 0x0000 범위의 메시지 식별자 값을 예약합니다. 애플리케이션은 프라이빗 메시지에 이러한 값을 사용할 수 없습니다.
  • 0x7FFF 0x0400 범위의 값( WM_USER 값)은 프라이빗 창 클래스의 메시지 식별자에 사용할 수 있습니다.
  • 애플리케이션이 버전 4.0으로 표시된 경우 개인 메시지에 대한 0xBFFF 통해 범위 0x8000(WM_APP)의 메시지 식별자 값을 사용할 수 있습니다.
  • 시스템에서는 애플리케이션이 RegisterWindowMessage 함수를 호출하여 메시지를 등록할 때 0xFFFF 0xC000 범위의 메시지 식별자를 반환합니다. 이 함수에서 반환된 메시지 식별자는 시스템 전체에서 고유하도록 보장됩니다. 이 함수를 사용하면 다른 애플리케이션에서 다른 용도로 동일한 메시지 식별자를 사용하는 경우 발생할 수 있는 충돌을 방지할 수 있습니다.

메시지 라우팅

시스템은 메시지를 창 프로시저로 라우팅하는 두 가지 방법을 사용합니다. 즉, 메시지 큐라는 선입선출 큐에 메시지를 게시하고, 일시적으로 메시지를 저장하는 시스템 정의 메모리 개체를 사용하고, 창 프로시저에 직접 메시지를 보냅니다.

메시지 큐에 게시되는 메시지를 큐에 대기 중인 메시지라고 합니다. 이는 주로 마우스 또는 키보드(예: WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWNWM_CHAR 메시지)를 통해 입력한 사용자 입력의 결과입니다. 큐에 대기된 다른 메시지에는 타이머, 그리기 및 종료 메시지( WM_TIMER, WM_PAINTWM_QUIT)가 포함됩니다. 창 프로시저로 직접 전송되는 대부분의 다른 메시지를 큐에 추가되지 않은 메시지라고 합니다.

큐에 대기된 메시지

시스템은 한 번에 임의의 수의 창을 표시할 수 있습니다. 마우스 및 키보드 입력을 적절한 창으로 라우팅하기 위해 시스템은 메시지 큐를 사용합니다.

시스템은 각 GUI 스레드에 대해 단일 시스템 메시지 큐와 하나의 스레드별 메시지 큐를 유지 관리합니다. 비-GUI 스레드에 대한 메시지 큐를 만드는 오버헤드를 방지하기 위해 모든 스레드는 처음에 메시지 큐 없이 만들어집니다. 시스템은 스레드가 특정 사용자 함수 중 하나에 대한 첫 번째 호출을 할 때만 스레드별 메시지 큐를 만듭니다. GUI 함수를 호출하지 않을 경우 메시지 큐가 생성됩니다.

사용자가 마우스를 이동하거나 마우스 단추를 클릭하거나 키보드에서 유형을 입력할 때마다 마우스 또는 키보드용 디바이스 드라이버가 입력을 메시지로 변환하여 시스템 메시지 큐에 배치합니다. 시스템은 시스템 메시지 큐에서 메시지를 한 번에 하나씩 제거하고 대상 창을 확인하도록 검사한 다음 대상 창을 만든 스레드의 메시지 큐에 게시합니다. 스레드의 메시지 큐는 스레드에서 만든 창에 대한 모든 마우스 및 키보드 메시지를 받습니다. 스레드는 큐에서 메시지를 제거하고 시스템에서 처리를 위한 적절한 창 프로시저로 보내도록 지시합니다.

WM_PAINT 메시지, WM_TIMER 메시지 및 WM_QUIT 메시지를 제외하고 시스템은 항상 메시지 큐 끝에 메시지를 게시합니다. 이렇게 하면 창이 FIFO(첫 번째, 첫 번째) 시퀀스에서 적절한 입력 메시지를 받습니다. 그러나 WM_PAINT 메시지, WM_TIMER 메시지 및 WM_QUIT 메시지는 큐에 유지되며 큐에 다른 메시지가 없는 경우에만 창 프로시저로 전달됩니다. 또한 동일한 창에 대한 여러 WM_PAINT 메시지가 단일 WM_PAINT 메시지로 결합되어 클라이언트 영역의 모든 잘못된 부분을 단일 영역으로 통합합니다. WM_PAINT 메시지를 결합하면 창이 클라이언트 영역의 내용을 다시 그려야 하는 횟수가 줄어듭니다.

시스템은 MSG 구조를 채운 다음 메시지 큐에 복사하여 스레드의 메시지 큐에 메시지를 게시합니다. MSG의 정보에는 메시지가 의도된 창의 핸들, 메시지 식별자, 두 개의 메시지 매개 변수, 메시지가 게시된 시간 및 마우스 커서 위치가 포함됩니다. 스레드는 PostMessage 또는 PostThreadMessage 함수를 사용하여 메시지를 자체 메시지 큐 또는 다른 스레드의 큐에 게시 할 수 있습니다 .

애플리케이션은 GetMessage 함수를 사용하여 큐에서 메시지를 제거할 수 있습니다. 메시지를 큐에서 제거하지 않고 검사하려면 애플리케이션에서 PeekMessage 함수를 사용할 수 있습니다. 이 함수는 메시지에 대한 정보로 MSG 를 채웁니다.

큐에서 메시지를 제거한 후 애플리케이션은 DispatchMessage 함수를 사용하여 시스템에서 메시지를 처리할 창 프로시저로 보내도록 지시할 수 있습니다. DispatchMessageGetMessage 또는 PeekMessage 함수에 대한 이전 호출로 채워진 MSG에 대한 포인터 사용합니다. DispatchMessage 는 창 핸들, 메시지 식별자 및 두 메시지 매개 변수를 창 프로시저에 전달하지만 메시지가 게시된 시간이나 마우스 커서 위치를 전달하지는 않습니다. 애플리케이션은 메시지를 처리하는 동안 GetMessageTimeGetMessagePos 함수를 호출하여 이 정보를 검색할 수 있습니다.

스레드는 메시지 큐에 메시지가 없는 경우 WaitMessage 함수를 사용하여 다른 스레드에 대한 제어를 생성할 수 있습니다. 함수는 스레드를 일시 중단하고 새 메시지가 스레드의 메시지 큐에 배치될 때까지 반환되지 않습니다.

SetMessageExtraInfo 함수를 호출하여 값을 현재 스레드의 메시지 큐와 연결할 수 있습니다. 그런 다음 GetMessageExtraInfo 함수를 호출하여 GetMessage 또는 PeekMessage 함수에서 검색한 마지막 메시지와 연결된 값을 가져옵니다.

큐에 없는 메시지

큐에 추가되지 않은 메시지는 시스템 메시지 큐 및 스레드 메시지 큐를 우회하여 대상 창 프로시저로 즉시 전송됩니다. 시스템은 일반적으로 큐에 추가되지 않은 메시지를 보내 영향을 주는 이벤트 창을 알립니다. 예를 들어 사용자가 새 애플리케이션 창을 활성화하면 시스템은 창에 WM_ACTIVATE, WM_SETFOCUSWM_SETCURSOR 포함한 일련의 메시지를 보냅니다. 이러한 메시지는 활성화되었고, 키보드 입력이 창으로 전달되고 있으며, 마우스 커서가 창 테두리 내에서 이동되었음을 창에 알립니다. 큐에 추가되지 않은 메시지는 애플리케이션이 특정 시스템 함수를 호출할 때 발생할 수도 있습니다. 예를 들어 시스템은 애플리케이션이 SetWindowPos 함수를 사용하여 창을 이동한 후 WM_WINDOWPOSCHANGED 메시지를 보냅니다.

큐에 추가되지 않은 메시지를 보내는 일부 함수는 BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeoutSendNotifyMessage입니다.

메시지 처리

애플리케이션은 스레드의 메시지 큐에 게시된 메시지를 제거하고 처리해야 합니다. 단일 스레드 애플리케이션은 일반적으로 WinMain 함수의 메시지 루프를 사용하여 메시지를 제거하고 처리를 위한 적절한 창 프로시저로 보냅니다. 여러 스레드가 있는 애플리케이션은 창을 만드는 각 스레드에 메시지 루프를 포함할 수 있습니다. 다음 섹션에서는 메시지 루프의 작동 방식을 설명하고 창 프로시저의 역할을 설명합니다.

메시지 루프

간단한 메시지 루프는 GetMessage, TranslateMessage 및 DispatchMessage라는 세 가지 함수 각각에 대한 하나의 함수 호출 구성 됩니다. 오류가 있는 경우 GetMessage 는 –1을 반환하므로 특수 테스트가 필요합니다.

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

GetMessage 함수는 큐에서 메시지를 검색하여 MSG 형식의 구조로 복사합니다. WM_QUIT 메시지가 발생하지 않는 한 0이 아닌 값을 반환합니다. 이 경우 FALSE를 반환하고 루프를 종료합니다. 단일 스레드 애플리케이션에서 메시지 루프를 종료하는 것이 애플리케이션을 닫는 첫 번째 단계인 경우가 많습니다. 애플리케이션은 일반적으로 애플리케이션의 기본 창의 창 프로시저에서 WM_DESTROY 메시지에 대한 응답으로 PostQuitMessage 함수를 사용하여 자체 루프를 종료할 수 있습니다.

창 핸들을 GetMessage의 두 번째 매개 변수로 지정하면 지정된 창에 대한 메시지만 큐에서 검색됩니다. GetMessage 는 큐의 메시지를 필터링하여 지정된 범위에 속하는 메시지만 검색할 수 있습니다. 메시지 필터링에 대한 자세한 내용은 메시지 필터링을 참조하세요.

스레드가 키보드에서 문자 입력을 수신하려면 스레드의 메시지 루프에 TranslateMessage 가 포함되어야 합니다. 시스템은 사용자가 키를 누를 때마다 가상 키 메시지(WM_KEYDOWNWM_KEYUP)를 생성합니다. 가상 키 메시지에는 누른 키를 식별하는 가상 키 코드가 포함되어 있지만 문자 값은 식별하지 않습니다. 이 값을 검색하려면 메시지 루프에 가상 키 메시지를 문자 메시지(WM_CHAR)로 변환하고 애플리케이션 메시지 큐에 다시 배치하는 TranslateMessage가 포함되어야 합니다. 그런 다음 메시지 루프의 후속 반복 시 문자 메시지를 제거하고 창 프로시저로 디스패치할 수 있습니다.

DispatchMessage 함수는 MSG 구조에 지정된 창 핸들과 연결된 창 프로시저에 메시지를 보냅니다. 창 핸들이 HWND_TOPMOST 경우 DispatchMessage 는 시스템의 모든 최상위 창의 창 프로시저로 메시지를 보냅니다. 창 핸들이 NULL이면 DispatchMessage 는 메시지와 아무 작업도 수행하지 않습니다.

애플리케이션의 기본 스레드는 애플리케이션을 초기화하고 하나 이상의 창을 만든 후 메시지 루프를 시작합니다. 시작 후 메시지 루프는 스레드의 메시지 큐에서 메시지를 계속 검색하고 적절한 창으로 디스패치합니다. GetMessage 함수가 메시지 큐에서 WM_QUIT 메시지를 제거하면 메시지 루프가 종료됩니다.

애플리케이션에 많은 창이 포함되어 있더라도 메시지 큐에는 하나의 메시지 루프만 필요합니다. DispatchMessage 는 항상 메시지를 적절한 창으로 디스패치합니다. 큐의 각 메시지는 메시지가 속한 창의 핸들을 포함하는 MSG 구조이기 때문입니다.

다양한 방법으로 메시지 루프를 수정할 수 있습니다. 예를 들어 창에 메시지를 디스패치하지 않고 큐에서 메시지를 검색할 수 있습니다. 이는 창을 지정하지 않는 메시지를 게시하는 애플리케이션에 유용합니다. GetMessage가 특정 메시지를 검색하도록 지시하여 다른 메시지를 큐에 남겨 두면 됩니다. 이는 메시지 큐의 일반적인 FIFO 순서를 일시적으로 무시해야 하는 경우에 유용합니다.

가속기 키를 사용하는 애플리케이션은 키보드 메시지를 명령 메시지로 변환할 수 있어야 합니다. 이렇게 하려면 애플리케이션의 메시지 루프에 TranslateAccelerator 함수에 대한 호출이 포함되어야 합니다. 가속기 키에 대한 자세한 내용은 키보드 가속기를 참조하세요.

스레드가 모덜리스 대화 상자를 사용하는 경우 대화 상자가 키보드 입력을 받을 수 있도록 메시지 루프에 IsDialogMessage 함수가 포함되어야 합니다.

창 프로시저

창 프로시저는 창에 전송된 모든 메시지를 수신하고 처리하는 함수입니다. 모든 창 클래스에는 창 프로시저가 있으며, 해당 클래스를 사용하여 만든 모든 창은 동일한 창 프로시저를 사용하여 메시지에 응답합니다.

시스템은 메시지 데이터를 프로시저에 인수로 전달하여 창 프로시저에 메시지를 보냅니다. 창 프로시저는 메시지에 대해 적절한 작업을 수행합니다. 메시지 식별자를 확인하고 메시지를 처리하는 동안 메시지 매개 변수에 지정된 정보를 사용합니다.

창 프로시저는 일반적으로 메시지를 무시하지 않습니다. 메시지를 처리하지 않는 경우 기본 처리를 위해 메시지를 시스템으로 다시 보내야 합니다. 창 프로시저는 기본 작업을 수행하고 메시지 결과를 반환하는 DefWindowProc 함수를 호출하여 이 작업을 수행합니다. 창 프로시저는 이 값을 자체 메시지 결과로 반환해야 합니다. 대부분의 창 프로시저는 몇 개의 메시지만 처리하고 DefWindowProc을 호출하여 다른 메시지를 시스템에 전달합니다.

창 프로시저는 동일한 클래스에 속하는 모든 창에서 공유되므로 여러 창에 대한 메시지를 처리할 수 있습니다. 메시지의 영향을 받는 특정 창을 식별하기 위해 창 프로시저는 메시지와 함께 전달된 창 핸들을 검사할 수 있습니다. 창 프로시저에 대한 자세한 내용은 창 프로시저를 참조하세요.

메시지 필터링

애플리케이션은 GetMessage 또는 PeekMessage 함수를 사용하여 메시지 필터를 지정하여 메시지 큐에서 검색할 특정 메시지를 선택할 수 있습니다(다른 메시지를 무시함). 필터는 메시지 식별자 범위(첫 번째 및 마지막 식별자), 창 핸들 또는 둘 다로 지정됩니다. GetMessagePeekMessage 는 메시지 필터를 사용하여 큐에서 검색할 메시지를 선택합니다. 메시지 필터링은 애플리케이션이 메시지 큐에서 나중에 큐에 도착한 메시지를 검색해야 하는 경우에 유용합니다. 또한 애플리케이션이 게시된 메시지를 처리하기 전에 입력(하드웨어) 메시지를 처리해야 하는 경우에도 유용합니다.

WM_KEYFIRSTWM_KEYLAST 상수를 필터 값으로 사용하여 모든 키보드 메시지를 검색할 수 있습니다. WM_MOUSEFIRSTWM_MOUSELAST 상수를 사용하여 모든 마우스 메시지를 검색할 수 있습니다.

메시지를 필터링하는 모든 애플리케이션은 메시지 필터를 충족하는 메시지를 게시할 수 있도록 해야 합니다. 예를 들어 애플리케이션이 키보드 입력을 받지 않는 창에서 WM_CHAR 메시지를 필터링하는 경우 GetMessage 함수는 반환되지 않습니다. 이렇게 하면 애플리케이션이 효과적으로 "중단"됩니다.

메시지 게시 및 보내기

모든 애플리케이션은 메시지를 게시하고 보낼 수 있습니다. 시스템과 마찬가지로 애플리케이션은 메시지를 메시지 큐에 복사하여 게시하고 메시지 데이터를 창 프로시저에 인수로 전달하여 메시지를 보냅니다. 메시지를 게시하기 위해 애플리케이션은 PostMessage 함수를 사용합니다. 애플리케이션은 SendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage 또는 SendDlgItemMessage 함수를 호출하여 메시지를 보낼 수 있습니다.

메시지 게시

애플리케이션은 일반적으로 특정 창에 작업을 수행하도록 알리는 메시지를 게시합니다. PostMessage 는 메시지에 대한 MSG 구조를 만들고 메시지를 메시지 큐에 복사합니다. 애플리케이션의 메시지 루프는 결국 메시지를 검색하고 적절한 창 프로시저로 디스패치합니다.

애플리케이션은 창을 지정하지 않고 메시지를 게시할 수 있습니다. PostMessage를 호출할 때 애플리케이션이 NULL 창 핸들을 제공하는 경우 메시지는 현재 스레드와 연결된 큐에 게시됩니다. 창 핸들이 지정되지 않으므로 애플리케이션은 메시지 루프에서 메시지를 처리해야 합니다. 이는 특정 창 대신 전체 애플리케이션에 적용되는 메시지를 만드는 한 가지 방법입니다.

경우에 따라 시스템의 모든 최상위 창에 메시지를 게시할 수 있습니다. 애플리케이션은 PostMessage를 호출하고 hwnd 매개 변수에 HWND_TOPMOST 지정하여 모든 최상위 창에 메시지를 게시할 수 있습니다.

일반적인 프로그래밍 오류는 PostMessage 함수가 항상 메시지를 게시한다고 가정하는 것입니다. 메시지 큐가 가득 찼을 때는 그렇지 않습니다. 애플리케이션은 PostMessage 함수의 반환 값을 검사 메시지가 게시되었는지 여부와 메시지가 게시되지 않은 경우 다시 게시해야 합니다.

메시지 보내기

애플리케이션은 일반적으로 즉시 작업을 수행하도록 창 프로시저에 알리는 메시지를 보냅니다. SendMessage 함수는 지정된 창에 해당하는 창 프로시저로 메시지를 보냅니다. 함수는 창 프로시저가 처리를 완료할 때까지 기다린 다음 메시지 결과를 반환합니다. 부모 창과 자식 창은 서로 메시지를 보내 통신하는 경우가 많습니다. 예를 들어 편집 컨트롤이 자식 창인 부모 창은 메시지를 보내 컨트롤의 텍스트를 설정할 수 있습니다. 컨트롤은 부모 창에 메시지를 다시 부모로 전송하여 사용자가 수행하는 텍스트에 대한 변경 내용을 알릴 수 있습니다.

SendMessageCallback 함수는 지정된 창에 해당하는 창 프로시저에 메시지를 보냅니다. 그러나 이 함수는 즉시 반환됩니다. 창 프로시저가 메시지를 처리한 후 시스템은 지정된 콜백 함수를 호출합니다. 콜백 함수에 대한 자세한 내용은 SendAsyncProc 함수를 참조하세요.

경우에 따라 시스템의 모든 최상위 창에 메시지를 보낼 수 있습니다. 예를 들어 애플리케이션이 시스템 시간을 변경하는 경우 WM_TIMECHANGE 메시지를 보내 변경 내용을 모든 최상위 창에 알려야 합니다. 애플리케이션은 SendMessage를 호출하고 hwnd 매개 변수에 HWND_TOPMOST 지정하여 모든 최상위 창에 메시지를 보낼 수 있습니다. BroadcastSystemMessage 함수를 호출하고 lpdwRecipients 매개 변수에 BSM_APPLICATIONS 지정하여 모든 애플리케이션에 메시지를 브로드캐스트할 수도 있습니다.

InSendMessage 또는 InSendMessageEx 함수를 사용하면 창 프로시저가 다른 스레드에서 보낸 메시지를 처리하고 있는지 여부를 확인할 수 있습니다. 이 기능은 메시지 처리가 메시지의 원본에 따라 달라지는 경우에 유용합니다.

메시지 교착 상태

SendMessage 함수를 호출하여 메시지를 다른 스레드로 보내는 스레드는 메시지를 받는 창 프로시저가 반환될 때까지 계속 실행할 수 없습니다. 메시지를 처리하는 동안 수신 스레드가 제어를 생성하는 경우 SendMessage 가 반환될 때까지 대기 중이므로 송신 스레드가 계속 실행될 수 없습니다. 수신 스레드가 발신자와 동일한 큐에 연결된 경우 애플리케이션 교착 상태가 발생할 수 있습니다. 저널 후크는 스레드를 동일한 큐에 연결합니다.

수신 스레드는 컨트롤을 명시적으로 생성할 필요가 없습니다. 다음 함수를 호출하면 스레드가 암시적으로 컨트롤을 생성할 수 있습니다.

애플리케이션의 잠재적 교착 상태를 방지하려면 SendNotifyMessage 또는 SendMessageTimeout 함수를 사용하는 것이 좋습니다. 그렇지 않으면 창 프로시저는 InSendMessage 또는 InSendMessageEx 함수를 호출하여 받은 메시지가 다른 스레드 에서 전송되었는지 여부를 확인할 수 있습니다. 메시지를 처리하는 동안 이전 목록의 함수를 호출하기 전에 창 프로시저는 먼저 InSendMessage 또는 InSendMessageEx 호출해야 합니다. 이 함수가 TRUE를 반환하는 경우 창 프로시저는 스레드가 제어를 생성하도록 하는 함수 앞에 ReplyMessage 함수를 호출해야 합니다.

메시지 브로드캐스트

각 메시지는 메시지 식별자와 wParamlParam이라는 두 개의 매개 변수로 구성됩니다. 메시지 식별자는 메시지 용도를 지정하는 고유한 값입니다. 매개 변수는 메시지별 추가 정보를 제공하지만 wParam 매개 변수는 일반적으로 메시지에 대한 자세한 정보를 제공하는 형식 값입니다.

메시지 브로드캐스트는 단순히 시스템의 여러 받는 사람에게 메시지를 보내는 것입니다. 애플리케이션에서 메시지를 브로드캐스트하려면 BroadcastSystemMessage 함수를 사용하여 메시지의 받는 사람을 지정합니다. 개별 받는 사람을 지정하는 대신 하나 이상의 받는 사람 유형을 지정해야 합니다. 이러한 유형은 애플리케이션, 설치 가능한 드라이버, 네트워크 드라이버 및 시스템 수준 디바이스 드라이버입니다. 시스템은 지정된 각 형식의 모든 멤버에게 브로드캐스트 메시지를 보냅니다.

시스템은 일반적으로 시스템 수준 디바이스 드라이버 또는 관련 구성 요소 내에서 발생하는 변경 내용에 대한 응답으로 메시지를 브로드캐스트합니다. 드라이버 또는 관련 구성 요소는 애플리케이션 및 기타 구성 요소에 메시지를 브로드캐스트하여 변경 사항을 알립니다. 예를 들어 디스크 드라이브를 담당하는 구성 요소는 플로피 디스크 드라이브의 디바이스 드라이버가 사용자가 드라이브에 디스크를 삽입할 때와 같은 미디어 변경을 감지할 때마다 메시지를 브로드캐스트합니다.

시스템은 시스템 수준 디바이스 드라이버, 네트워크 드라이버, 설치 가능한 드라이버 및 애플리케이션과 같은 순서로 받는 사람에게 메시지를 브로드캐스트합니다. 즉, 수신자로 선택된 시스템 수준 디바이스 드라이버는 항상 메시지에 응답할 수 있는 첫 번째 기회를 얻습니다. 지정된 받는 사람 유형 내에서는 드라이버가 다른 드라이버 앞에 지정된 메시지를 수신하도록 보장되지 않습니다. 즉, 특정 드라이버용 메시지에는 전역적으로 고유한 메시지 식별자가 있어야 다른 드라이버가 의도치 않게 처리하지 않습니다.

SendMessage, SendMessageCallback, SendMessageTimeout 또는 SendNotifyMessage 함수에서 HWND_BROADCAST 지정하여 모든 최상위 창에 메시지를 브로드캐스트할 수도 있습니다.

애플리케이션은 최상위 창의 창 프로시저를 통해 메시지를 받습니다. 메시지는 자식 창으로 전송되지 않습니다. 서비스는 창 프로시저 또는 해당 서비스 제어 처리기를 통해 메시지를 받을 수 있습니다.

참고

시스템 수준 디바이스 드라이버는 관련 시스템 수준 함수를 사용하여 시스템 메시지를 브로드캐스트합니다.

쿼리 메시지

사용자 고유의 사용자 지정 메시지를 만들고 이를 사용하여 애플리케이션과 시스템의 다른 구성 요소 간의 활동을 조정할 수 있습니다. 이는 설치 가능한 드라이버 또는 시스템 수준 디바이스 드라이버를 직접 만든 경우에 특히 유용합니다. 사용자 지정 메시지는 드라이버를 사용하는 드라이버 및 애플리케이션과 정보를 전달할 수 있습니다.

지정된 작업을 수행할 수 있는 권한을 받는 사람을 폴링하려면 쿼리 메시지를 사용합니다. BroadcastSystemMessage를 호출할 때 dwFlags 매개 변수에서 BSF_QUERY 값을 설정하여 고유한 쿼리 메시지를 생성할 수 있습니다. 쿼리 메시지의 각 수신자는 함수가 메시지를 다음 받는 사람에게 보내려면 TRUE 를 반환해야 합니다. 받는 사람이 BROADCAST_QUERY_DENY 반환하면 브로드캐스트가 즉시 종료되고 함수는 0을 반환합니다.