Hook(훅) SetWindowsHookEx
SetWindowsHookEx 함수는 Windows 운영 체제에서
훅(Hook)을 설치하기 위해 사용되는 함수입니다.
훅은 시스템 내에서 발생하는 이벤트를 감지하고
해당 이벤트에 대한 처리를 수행하는 데 사용됩니다.
예를 들어, 키보드 이벤트, 마우스 이벤트, 윈도우 메시지 등을 감지하고
원하는 동작을 수행할 수 있습니다.
SetWindowsHookEx 함수는 다음과 같은 매개변수를 가지고 있습니다
idHook: 설치할 훅의 유형을 지정하는 매개변수로, 훅의 종류에 따라 다른 상수 값을 사용합니다.
예를 들어, WH_KEYBOARD는 키보드 이벤트를 감지하는 훅을 설치하는 상수입니다.
lpfn: 훅 프로시저(Hook Procedure)로서 호출될 함수의 포인터입니다.
훅 이벤트가 발생할 때마다 해당 함수가 호출됩니다.
hMod: 훅 프로시저가 포함된 DLL의 핸들입니다.
일반적으로 자신의 DLL을 만들고 해당 DLL의 핸들을 전달합니다.
그러나 현재 프로세스 내에서 훅을 설치하는 경우 NULL 값을 사용할 수도 있습니다.
dwThreadId: 훅 프로시저를 연결할 스레드의 식별자입니다.
0을 전달하면 시스템 전체에 대해 훅을 설치합니다.
SetWindowsHookEx 함수는 설치된 훅에 대한 핸들을 반환하며,
이 핸들은 후속 작업에서 훅을 제거할 때 사용됩니다.
다음은 Delphi에서 SetWindowsHookEx 함수를 사용하여
키보드 이벤트를 감지하는 예제 코드입니다
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FHookHandle: HHOOK;
procedure KeyboardHookProc(var Msg: TMessage);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function HookCallback(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if nCode = HC_ACTION then
begin
// 키보드 이벤트 처리
// wParam: 이벤트 유형 (WM_KEYDOWN, WM_KEYUP 등)
// lParam: 이벤트 정보 (키 코드 등)
// 원하는 동작을 수행하면 됩니다.
end;
Result := CallNextHookEx(0, nCode, wParam, lParam);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FHookHandle := SetWindowsHookEx(WH_KEYBOARD, @HookCallback, HInstance, 0);
if FHookHandle = 0 then ShowMessage('Hook installation failed.');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if FHookHandle <> 0 then UnhookWindowsHookEx(FHookHandle);
end;
end.
이 예제는 Delphi 폼 애플리케이션에서 키보드 이벤트를 감지하기 위해
SetWindowsHookEx 함수를 사용하는 방법을 보여줍니다.
FormCreate 이벤트 핸들러에서 훅을 설치하고,
FormDestroy 이벤트 핸들러에서 훅을 제거합니다.
KeyboardHookProc 함수는 훅 이벤트가 발생할 때 호출되며,
원하는 동작을 수행하는 코드를 해당 함수 내에 작성하면 됩니다.
-----추가내용----
후킹의 강력함을 모두 이용하려면 시스템에 있는 모든 윈도우에 대해서
훅을 걸어서 써야겠지만 간혹 자신의 윈도우 안에서만
후킹을 해야 할 경우가 있습니다.
( 'KeyPreView := true'로는 해결이 안되고 모든 키에 대해서
처리를 해야 할 경우라든지, 폼위에서(Caption이나 Menu위에서) 움직이는
마우스의 모든상태를 처리해야 한다든지 하는 경우이겠지요.. )
두 경우의 차이라면 시스템 전반에 훅을 걸 경우에는 DLL에서 걸어야 하지만
후자의 경우에는 DLL이 필요없이 프로젝트 내에서
간단하게 훅을 설치할수 있다는 것입니다.
이때 SetWindowsHookEx에 넣어주어야 할 매개변수가 달라지게 되지요..
가령 후자의 경우에는 ( 내 윈도우 안에만 훅을 설치할때 )
hMouseHook := SetWindowsHookEx( WH_MOUSE, @MouseHookProc, 0, <--GetCurrentThreadID <-);
세번째 인자와 네번째 인자가 DLL에서와 달라지게 됩니다.
위의 경우는 마우스 훅을 걸때의 상황이지요..
가령 키보드 훅을 걸어야 할경우에는
WH_MOUSE대신 WH_KEYBOARD이 들어가게 되구 물론 키보드 훅용 콜백함수를 쓰셔야 할겁니다.
SetWindowsHookEx의 두번째 인자로 들어가는 콜백함수의 형태는 어떤 후킹이든 동일합니다.
즉 한가지 후킹에 성공하셨다면 다른 종류의 훅도 얼마든지 설치할 수 있습니다.
다만 사용하려는 훅에대해 완전히 알고 있어야 사용할 수 있다는게 문제이지만...
대부분의 문제는 lParam을 어떻게 이용하느냐 하는것인데,
windows.pas를 보시면 어느정도 감이 잡힐것 같습니다.
11495 line부터 각종 훅에 대한 lParam의 구조체 타입이 나와있습니다.
물론 각각의 쓰임새는 공부를 하셔야 겠지요 DLL내부에서
즉 시스템 전역에 훅을 설치하실때는 세번째와 네번째 인자를
hMouseHook := SetWindowsHookEx( WH_MOUSE, @MouseHookProc, HInstance, <-0 <--);
로 바꾸고 DLL로 컴파일 하면 됩니다.
결국 내 어플리케이션 안에서 후킹을 걸어서 성공했다면
그 소스를 그대로 DLL로 컴파일 하면 시스템 전반에 걸쳐서
훅을 설치하는 것은 쉽게 이루어 진다는 얘깁니다.
다음은 하나의 윈도우(폼)에 마우스 훅을 걸어서 그 결과를 Caption에 표시하는 예제입니다.
정말로 간단하지요?
다른 훅의 이용도 크게 다르지 않답니다.
다만 헬프가 넘 어렵게 되어있구, 주위에서 참고로 할 자료를 찾기가 쉽지 않고,
* 참고로 MSDN에서 Hooking으로 검색을 하면
목록의 제목만 하나씩 보는데만도 2시간이 넘게 걸릴만큼
Hooking에 대한 자료가 많더군요 Hooking이라는 것에 대한
내면 깊숙한 곳에서 우러나오는 일종의 공포심이 결합하여 시도하기도 전에 포기하는 것 같습니다.
Message Hooking은 윈도우 프로그래밍에서 가장 강력한 테크닉 중하나입니다.
그러나 Hooking의 구현은 전혀 어렵지 않습니다.
여담으로 API Hooking이라는 테크닉이 있죠..
Message-Hooking이 시스템에 떠도는 메시지들을 가로채는 것이라면
API-Hooking은 시스템에서 어떤 API함수가 불려지면 그걸 가로채는 것이랍니다.
요즘 영한사전류에서 마우스만 갖다대도 글자를 인식하는데
쓰이는고급기법이죠 API-Hooking의 강력함에 비하면
Message-Hooking은 새발의피라고 할 정도입니다.
unit unit1 .......
.......
implementation
{$R *.DFM}
var
hMouseHook : integer = -1;
function MouseHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): Longint; stdcall;
Begin
If (Code >= 0) Then
Begin
with PMouseHookStruct( lParam )^ do
Form1.Caption := Format( '[X : %d, Y : %d] [HitTestCode : %d]', [ pt.x, pt.y, wHitTestCode ] );
Form1.Caption := Form1.Caption + Format( ' [ wParam : %d]', [ wParam ] );
End;
Result := CallNextHookEx(hMouseHook, Code, wParam, lParam);
End;
procedure SetMouseHook( flag : boolean );
Begin
if not flag then begin
if hMouseHook < 0 then
exit;
UnHookWindowsHookEx(hMouseHook);
hMouseHook := -1;
end
else
hMouseHook := SetWindowsHookEx( WH_Mouse, @MouseHookProc,0,GetCurrentThreadID);
End;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetMouseHook( hMouseHook < 0 );
end;
end.
'Delphi > 프로시저-함수' 카테고리의 다른 글
태스크바 (taskbar) 에서 숨기기 (0) | 2023.08.01 |
---|---|
시스템 날짜바꾸기 (0) | 2023.07.27 |
메모(TMemo) 팁 (0) | 2023.06.14 |
StringGrid의 Cell에 입력 값 제한 (0) | 2023.06.02 |
초를 시간 분 초 형식으로 리턴 (0) | 2021.07.22 |
댓글