후크 개요

후크는 애플리케이션이 메시지, 마우스 작업 및 키 입력과 같은 이벤트를 가로챌 수 있는 메커니즘입니다. 특정 유형의 이벤트를 가로채는 함수를 후크 프로시저라고 합니다. 후크 프로시저는 수신하는 각 이벤트에 대해 작동한 다음 이벤트를 수정하거나 삭제할 수 있습니다.

다음 예제에서는 후크에 를 사용합니다.

  • 디버깅을 위해 메시지 모니터링
  • 매크로 기록 및 재생 지원 제공
  • 도움말 키 지원 제공(F1)
  • 마우스 및 키보드 입력 시뮬레이션
  • CBT(컴퓨터 기반 학습) 애플리케이션 구현

참고

후크는 시스템이 각 메시지에 대해 수행해야 하는 처리량을 늘리기 때문에 시스템 속도가 느려지는 경향이 있습니다. 필요한 경우에만 후크를 설치하고 가능한 한 빨리 제거해야 합니다.

 

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

후크 체인

시스템은 다양한 유형의 후크를 지원합니다. 각 형식은 메시지 처리 메커니즘의 다른 측면에 대한 액세스를 제공합니다. 예를 들어 애플리케이션은 WH_MOUSE 후크를 사용하여 마우스 메시지의 메시지 트래픽을 모니터링할 수 있습니다.

시스템은 각 후크 유형에 대해 별도의 후크 체인을 유지 관리합니다. 후크 체인후크 프로시저라는 특수 애플리케이션 정의 콜백 함수에 대한 포인터 목록입니다. 특정 유형의 후크와 연결된 메시지가 발생하면 시스템은 후크 체인에서 참조되는 각 후크 프로시저에 메시지를 하나씩 전달합니다. 후크 프로시저가 수행할 수 있는 작업은 관련된 후크 유형에 따라 달라집니다. 일부 후크 유형에 대한 후크 프로시저는 메시지만 모니터링할 수 있습니다. 다른 사용자는 메시지를 수정하거나 체인을 통해 진행 상황을 중지하여 다음 후크 프로시저 또는 대상 창에 도달하지 못하게 할 수 있습니다.

후크 프로시저

개발자는 특정 유형의 후크를 활용하기 위해 후크 프로시저를 제공하고 SetWindowsHookEx 함수를 사용하여 후크와 연결된 체인에 설치합니다. 후크 프로시저에는 다음 구문이 있어야 합니다.

LRESULT CALLBACK HookProc(
  int nCode, 
  WPARAM wParam, 
  LPARAM lParam
)
{
   // process event
   ...

   return CallNextHookEx(NULL, nCode, wParam, lParam);
}

HookProc 은 애플리케이션 정의 이름의 자리 표시자입니다.

nCode 매개 변수는 후크 프로시저가 수행할 작업을 결정하는 데 사용하는 후크 코드입니다. 후크 코드의 값은 후크의 형식에 따라 달라집니다. 각 형식에는 고유한 특성의 후크 코드 집합이 있습니다. wParamlParam 매개 변수의 값은 후크 코드에 따라 달라지지만 일반적으로 전송되거나 게시된 메시지에 대한 정보가 포함됩니다.

SetWindowsHookEx 함수는 항상 후크 체인의 시작 부분에 후크 프로시저를 설치합니다. 특정 유형의 후크에 의해 모니터링되는 이벤트가 발생하면 시스템은 후크와 연결된 후크 체인의 시작 부분에서 프로시저를 호출합니다. 체인의 각 후크 프로시저는 이벤트를 다음 프로시저에 전달할지 여부를 결정합니다. 후크 프로시저는 CallNextHookEx 함수를 호출하여 이벤트를 다음 프로시저로 전달합니다.

일부 후크 유형에 대한 후크 프로시저는 메시지만 모니터링할 수 있습니다. 시스템은 특정 프로시저가 CallNextHookEx를 호출하는지 여부에 관계없이 각 후크 프로시저에 메시지를 전달합니다.

전역 후크는 호출 스레드와 동일한 데스크톱의 모든 스레드에 대한 메시지를 모니터링합니다. 스레드별 후크는 개별 스레드에 대해서만 메시지를 모니터링합니다. 호출 스레드와 동일한 데스크톱에 있는 모든 애플리케이션의 컨텍스트에서 전역 후크 프로시저를 호출할 수 있으므로 프로시저는 별도의 DLL 모듈에 있어야 합니다. 스레드별 후크 프로시저는 연결된 스레드의 컨텍스트에서만 호출됩니다. 애플리케이션이 자체 스레드 중 하나에 대한 후크 프로시저를 설치하는 경우 후크 프로시저는 애플리케이션의 나머지 코드와 동일한 모듈 또는 DLL에 있을 수 있습니다. 애플리케이션이 다른 애플리케이션의 스레드에 대한 후크 프로시저를 설치하는 경우 프로시저는 DLL에 있어야 합니다. 자세한 내용은 Dynamic-Link 라이브러리를 참조하세요.

참고

전역 후크는 디버깅 목적으로만 사용해야 합니다. 그렇지 않으면 피해야 합니다. 전역 후크는 시스템 성능을 저하시키고 동일한 유형의 전역 후크를 구현하는 다른 애플리케이션과 충돌을 일으킵니다.

 

후크 형식

각 후크 유형을 사용하면 애플리케이션이 시스템의 메시지 처리 메커니즘의 다른 측면을 모니터링할 수 있습니다. 다음 섹션에서는 사용 가능한 후크에 대해 설명합니다.

WH_CALLWNDPROC 및 WH_CALLWNDPROCRET

WH_CALLWNDPROCWH_CALLWNDPROCRET 후크를 사용하면 창 프로시저로 전송된 메시지를 모니터링할 수 있습니다. 시스템은 수신 창 프로시저에 메시지를 전달하기 전에 WH_CALLWNDPROC 후크 프로시저를 호출하고 창 프로시저가 메시지를 처리한 후 WH_CALLWNDPROCRET 후크 프로시저를 호출합니다.

WH_CALLWNDPROCRET 후크는 CWPRETSTRUCT 구조체에 대한 포인터를 후크 프로시저에 전달합니다. 구조체에는 메시지를 처리한 창 프로시저의 반환 값과 메시지와 연결된 메시지 매개 변수가 포함됩니다. 프로세스 간에 설정된 메시지에는 창을 서브클래싱하는 것이 작동하지 않습니다.

자세한 내용은 CallWndProcCallWndRetProc 콜백 함수를 참조하세요.

WH_CBT

시스템은 창을 활성화, 생성, 파괴, 최소화, 최대화, 이동 또는 크기 조정하기 전에 WH_CBT 후크 프로시저를 호출합니다. 시스템 명령을 완료하기 전에 시스템 메시지 큐에서 마우스 또는 키보드 이벤트를 제거하기 전에 입력 포커스를 설정하기 전에 또는 시스템 메시지 큐와 동기화하기 전에 후크 프로시저가 반환하는 값은 시스템에서 이러한 작업 중 하나를 허용하거나 방지하는지 여부를 결정합니다. WH_CBT 후크는 주로 CBT(컴퓨터 기반 학습) 애플리케이션을 위한 것입니다.

자세한 내용은 CBTProc 콜백 함수를 참조하세요.

자세한 내용은 WinEvents를 참조하세요.

WH_DEBUG

시스템은 시스템의 다른 크와 연결된 후크 프로시저를 호출하기 전에 WH_DEBUG 후크 프로시저를 호출합니다. 이 후크를 사용하여 시스템이 다른 유형의 후크와 연결된 후크 프로시저를 호출하도록 허용할지 여부를 결정할 수 있습니다.

자세한 내용은 DebugProc 콜백 함수를 참조하세요.

WH_FOREGROUNDIDLE

WH_FOREGROUNDIDLE 후크를 사용하면 포그라운드 스레드가 유휴 상태일 때 우선 순위가 낮은 작업을 수행할 수 있습니다. 시스템은 애플리케이션의 포그라운드 스레드가 유휴 상태가 될 때 WH_FOREGROUNDIDLE 후크 프로시저를 호출합니다.

자세한 내용은 ForegroundIdleProc 콜백 함수를 참조하세요.

WH_GETMESSAGE

WH_GETMESSAGE 후크를 사용하면 애플리케이션이 GetMessage 또는 PeekMessage 함수에서 반환될 메시지를 모니터링할 수 있습니다. WH_GETMESSAGE 후크를 사용하여 마우스 및 키보드 입력 및 메시지 큐에 게시된 기타 메시지를 모니터링할 수 있습니다.

자세한 내용은 GetMsgProc 콜백 함수를 참조하세요.

WH_JOURNALPLAYBACK

경고

저널링 후크 API는 Windows 11 시작해서 지원되지 않으며 향후 릴리스에서 제거될 예정입니다. 따라서 대신 SendInput TextInput API를 호출하는 것이 좋습니다.

WH_JOURNALPLAYBACK 후크를 사용하면 애플리케이션이 시스템 메시지 큐에 메시지를 삽입할 수 있습니다. 이 후크를 사용하여 WH_JOURNALRECORD 사용하여 이전에 기록된 일련의 마우스 및 키보드 이벤트를 재생할 수 있습니다. WH_JOURNALPLAYBACK 후크가 설치되어 있으면 일반 마우스 및 키보드 입력이 비활성화됩니다. WH_JOURNALPLAYBACK 후크는 전역 후크이며 스레드별 후크로 사용할 수 없습니다.

WH_JOURNALPLAYBACK 후크는 제한 시간 값을 반환합니다. 이 값은 재생 후크에서 현재 메시지를 처리하기 전에 대기할 시간(밀리초)을 시스템에 알려줍니다. 이렇게 하면 후크가 재생되는 이벤트의 타이밍을 제어할 수 있습니다.

자세한 내용은 JournalPlaybackProc 콜백 함수를 참조하세요.

WH_JOURNALRECORD

경고

저널링 후크 API는 Windows 11 시작해서 지원되지 않으며 향후 릴리스에서 제거될 예정입니다. 따라서 대신 SendInput TextInput API를 호출하는 것이 좋습니다.

WH_JOURNALRECORD 후크를 사용하면 입력 이벤트를 모니터링하고 기록할 수 있습니다. 일반적으로 이 후크를 사용하여 WH_JOURNALPLAYBACK 사용하여 나중에 재생할 마우스 및 키보드 이벤트 시퀀스를 기록합니다. WH_JOURNALRECORD 후크는 전역 후크이며 스레드별 후크로 사용할 수 없습니다.

자세한 내용은 JournalRecordProc 콜백 함수를 참조하세요.

WH_KEYBOARD_LL

WH_KEYBOARD_LL 후크를 사용하면 스레드 입력 큐에 게시될 키보드 입력 이벤트를 모니터링할 수 있습니다.

자세한 내용은 LowLevelKeyboardProc 콜백 함수를 참조하세요.

WH_KEYBOARD

WH_KEYBOARD 후크를 사용하면 애플리케이션이 GetMessage 또는 PeekMessage 함수에서 반환될 WM_KEYDOWN WM_KEYUP 메시지에 대한 메시지 트래픽을 모니터링할 수 있습니다. WH_KEYBOARD 후크를 사용하여 메시지 큐에 게시된 키보드 입력을 모니터링할 수 있습니다.

자세한 내용은 KeyboardProc 콜백 함수를 참조하세요.

WH_MOUSE_LL

WH_MOUSE_LL 후크를 사용하면 스레드 입력 큐에 게시될 마우스 입력 이벤트를 모니터링할 수 있습니다.

자세한 내용은 LowLevelMouseProc 콜백 함수를 참조하세요.

WH_MOUSE

WH_MOUSE 후크를 사용하면 GetMessage 또는 PeekMessage 함수에서 반환될 마우스 메시지를 모니터링할 수 있습니다. WH_MOUSE 후크를 사용하여 메시지 큐에 게시된 마우스 입력을 모니터링할 수 있습니다.

자세한 내용은 MouseProc 콜백 함수를 참조하세요.

WH_MSGFILTER 및 WH_SYSMSGFILTER

WH_MSGFILTERWH_SYSMSGFILTER 후크를 사용하면 메뉴, 스크롤 막대, 메시지 상자 또는 대화 상자에서 처리될 메시지를 모니터링하고 사용자가 ALT+TAB 또는 Alt+ESC 키 조합을 누른 결과로 다른 창이 활성화될 시기를 감지할 수 있습니다. WH_MSGFILTER 후크는 후크 프로시저를 설치한 애플리케이션에서 만든 메뉴, 스크롤 막대, 메시지 상자 또는 대화 상자에 전달된 메시지만 모니터링할 수 있습니다. WH_SYSMSGFILTER 후크는 모든 애플리케이션에 대해 이러한 메시지를 모니터링합니다.

WH_MSGFILTER 및 WH_SYSMSGFILTER 후크를 사용하면 기본 메시지 루프에서 수행된 필터링과 동일한 모달 루프 중에 메시지 필터링을 수행할 수 있습니다. 예를 들어 애플리케이션은 큐에서 메시지를 검색하는 시간과 메시지를 디스패치하는 시간 사이의 기본 루프에서 새 메시지를 검사하여 적절하게 특수한 처리를 수행하는 경우가 많습니다. 그러나 모달 루프 중에 시스템은 애플리케이션이 기본 메시지 루프에서 메시지를 필터링할 기회를 허용하지 않고 메시지를 검색하고 디스패치합니다. 애플리케이션이 WH_MSGFILTER 또는 WH_SYSMSGFILTER 후크 프로시저를 설치하는 경우 시스템은 모달 루프 중에 프로시저를 호출합니다.

애플리케이션은 CallMsgFilter 함수를 호출하여 WH_MSGFILTER 후크를 직접 호출할 수 있습니다. 이 함수를 사용하면 애플리케이션이 기본 메시지 루프에서 사용하는 것과 동일한 코드를 사용하여 모달 루프 중에 메시지를 필터링할 수 있습니다. 이렇게 하려면 WH_MSGFILTER 후크 프로시저에서 필터링 작업을 캡슐화하고 GetMessageDispatchMessage 함수에 대한 호출 간에 CallMsgFilter를 호출합니다.

while (GetMessage(&msg, (HWND) NULL, 0, 0)) 
{ 
    if (!CallMsgFilter(&qmsg, 0)) 
        DispatchMessage(&qmsg); 
} 

CallMsgFilter의 마지막 인수는 단순히 후크 프로시저에 전달됩니다. 모든 값을 입력할 수 있습니다. 후크 프로시저는 MSGF_MAINLOOP 같은 상수를 정의하여 이 값을 사용하여 프로시저가 호출된 위치를 확인할 수 있습니다.

자세한 내용은 MessageProcSysMsgProc 콜백 함수를 참조하세요.

WH_SHELL

셸 애플리케이션은 WH_SHELL 후크를 사용하여 중요한 알림을 받을 수 있습니다. 시스템은 셸 애플리케이션이 활성화 될 때와 최상위 창을 만들거나 소멸할 때 WH_SHELL 후크 프로시저를 호출합니다.

사용자 지정 셸 애플리케이션은 WH_SHELL 메시지를 받지 않습니다. 따라서 자신을 기본 셸로 등록하는 모든 애플리케이션은 SystemParametersInfo 함수를 호출해야만 (또는 다른 애플리케이션) WH_SHELL 메시지를 받을 수 있습니다. 이 함수는 SPI_SETMINIMIZEDMETRICSMINIMIZEDMETRICS 구조체를 사용하여 호출해야 합니다. 이 구조체의 iArrange 멤버를 ARW_HIDE 설정합니다.

자세한 내용은 ShellProc 콜백 함수를 참조하세요.