Windows 메시지 관리자는 애플리케이션이 제어된 메시지 흐름에 액세스할 수 있는 기능을 제공합니다.
'c4'의 소위 후크(HOOK) 메커니즘입니다. 다양한 종류의 후크가 있으며, 각 후크는 특정 유형이나 메시지 범위를 캡처하는 데 사용됩니다. 예: 키보드 메시지, 마우스 메시지 등 여기서는 키보드 후크를 예로 들어 DELPHI에서 DLL 프로그램을 작성하는 방법과 자신의 프로그램에 키보드 후크 기능을 설치하고 사용하는 방법에 대해 설명합니다. 또한 여러 프로그램이 동일한 DLL 파일을 사용할 때 데이터를 공유하는 방법도 설명합니다. .
1. 후크 필터 함수 작성 지침
후크 필터 기능은 독립된 모듈에 있어야 하므로 먼저 DLL 프레임워크를 생성한 다음 여기에 후크 기능 코드 및 기타 관련 기능 코드를 추가해야 합니다. 여기서는 키보드 후크 필터 기능 작성을 예로 들어 설명하겠습니다. 구체적인 단계는 다음과 같습니다:
1. 먼저 DLL 바구니를 생성합니다. 2
2. 나만의 키보드 후크 필터 기능 작성
후크 필터 함수는 콜백 함수여야 하며 해당 함수의 모양은 다음과 같습니다.
기능KeyHookPROc(
iCode:정수;
wParam:WPARAM;
lParam:LPARAM ): LRESULT;표준 호출;내보내기;
키보드 메시지를 처리하려면 생성된 DLL 프레임워크에 사용자 고유의 키보드 후크 처리 기능을 추가하세요.
코드는 다음과 같습니다:…
if(iCode>=0) 다음 시작
결과:=0; //초기화 반환 값
//여기에 자신만의 코드를 추가하세요.
다른 끝
시작하다
결과:=CallNextHook(hOldKeyHook,iCode,wParam,lParam);
//hOldKeyHook은 저장된 원본 키보드 필터 기능인가요?
끝;
3. 키보드 후크 필터 기능 설치
후크를 설치하려면 _fd 필터 함수가 SetWindowsHookEx 함수를 호출해야 합니다(Windows 3.0용 SetWindowsHook 후크 설치 함수는 이제 더 이상 사용되지 않습니다). 이 함수의 프로토타입은 다음과 같습니다.
HHOOK SetWindowsHookEx(
int idHook, // 설치됨?_b3 하위 유형
HOOKPROC lpfn, //후크 필터??f 번호 주소
HINSTANCE hMod, //태스크 핸들
DWord dwThreadId // 후크의 목적
);
?_a8은 종종 MakeProcInstance 함수를 호출하여 출력 함수 프리앰블의 항목 주소를 얻은 다음 이 주소를 SetWindowsHookEx의 두 번째 매개 변수 lpfn으로 사용해야 합니다. 하지만 델파이에서는 "스마트 콜백"을 제공하기 때문에 MakeProcInstance를 생략하고 Hook Filter 함수명을 바로 항목 주소로 사용할 수 있습니다.
이러한 방식으로 애플리케이션의 _c3GetMessage 또는 PeekMessage 함수가 메시지 큐에서 메시지를 읽거나 처리할 키 메시지(WM_KEYDOWN 또는 WM_KEYUP)가 있는 경우 시스템은 후크 필터 함수 KeyHookProc를 호출하여 키보드 메시지를 처리합니다.
4. 후크 필터 기능을 제거합니다.
후크 기능이 더 이상 필요하지 않은 경우 UnHookWindowsHookProc를 호출하여 설치된 후크를 제거하여 시스템 리소스를 해제해야 합니다.
전체 프로그램 목록은 다음과 같습니다.?_ba
도서관 열쇠고리;
Windows를 사용합니다.
const BUFFER_SIZE=16*1024;
const HOOK_MEM_FILENAME='샘플 KEY_HOOK_MEM_FILE';
const HOOK_MUTEX_NAME ='샘플 KEY_HOOK_MUTEX_NAME';
유형
TShared=기록
키: Char의 배열[0..BUFFER_SIZE];
KeyCount : 정수;
끝;
PShared=^TShared;
var
MemFile,HookMutex: THandle;
hOldKeyHook: HHook;
ProcSaveExit: 포인터;
공유: PShared;
//키보드 후크 필터 기능
함수 KeyHookProc(iCode: 정수; wParam: WPARAM ; lParam: LPARAM):LRESULT
;표준 호출;
const KeyPressMask = $80000000;
시작하다
iCode < 0이면
결과 := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam)
그렇지 않으면 시작하다
if ((lParam and KeyPressMask)= 0) then // 키가 눌림
시작하다
Shared^.Keys[Shared^.KeyCount]:=Char(wParam 및 $00ff);
Inc(공유^.KeyCount);
Shared^.KeyCount>=BUFFER_SIZE-1인 경우 Shared^.KeyCount:=0;
끝;
아이코드:=-1;
결과 := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam);
끝;
끝;
//후크 필터 기능 설정
기능 EnableKeyHook: BOOL;
시작하다
Shared^.KeyCount:=0; //키보드 포인터 초기화
hOldKeyHook=0이면 시작합니다.
hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD,
KeyHookProc,
H인스턴스,
0);
끝;
결과 := (hOldKeyHook <> 0);
끝;
//훅 필터 기능 실행 취소
기능 비활성화KeyHook: BOOL;
시작하다
hOldKeyHook<> 0이면
시작하다
UnHookWindowsHookEx(hOldKeyHook); // 키보드 후크 해제
hOldKeyHook:= 0;
공유^.KeyCount:=0;
끝;
결과 := (hOldKeyHook = 0);
끝;
//키보드 버퍼의 키 입력 횟수를 가져옵니다.
함수 GetKeyCount :정수 내보내기;
시작하다
결과:=공유^.KeyCount;
끝;
//키보드 버퍼의 키를 가져옵니다.
function GetKey(index:Integer) : Char ;
시작하다
결과:=공유^.Keys[색인];
끝;
//키보드 버퍼를 지웁니다.
절차 ClearKeyString;
시작하다
공유^.KeyCount:=0;
끝;
//DLL 종료 처리 프로세스
절차 KeyHookExit;
시작하다
hOldKeyHook <> 0이면 비활성화KeyHook;
UnMapViewOfFile(Shared); // 메모리 이미지 파일을 해제합니다.
CloseHandle(MemFile); // 이미지 파일을 닫습니다.
ExitProc := ProcSaveExit;
끝;
내보내기 // 출력 함수 정의
KeyHook 활성화,
비활성화KeyHook,
키카운트 가져오기,
클리어키스트링,
키 얻기;
시작하다
//DLL 초기화 부분
HookMutex:=CreateMutex(nil,True,HOOK_MUTEX_NAME);
// 메모리 이미지 파일을 생성하여 메모리를 공유합니다.
MemFile:=OpenFileMapping(FILE_MAP_WRITE,False,
HOOK_MEM_FILENAME);
MemFile=0이면
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
SizeOf(TShared) ,HOOK_MEM_FILENAME);
Shared:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
ReleaseMutex(HookMutex);
CloseHandle(HookMutex);
ProcSaveExit := ExitProc; // DLL의 ExitProc를 저장합니다.
ExitProc := @KeyHookExit; // DLL의 새 ExitProc를 설정합니다.
끝.
//소스코드 끝
2. 준비된 키보드 후크 필터 기능을 자신의 프로그램에서 사용하십시오.
후크 함수가 컴파일된 후 실제로 사용하는 것은 매우 간단합니다. 먼저 SetWindowsHookEx를 호출하여 자체 후크 필터 함수를 설치하고 동시에 원래 후크 필터 함수 주소를 저장합니다. 이때 후크 기능이 작동하며 요구 사항에 따라 키보드 메시지를 처리합니다. 프로그램 실행이 완료되거나 키보드 메시지를 더 이상 모니터링할 필요가 없으면 UnHookWindowsHookProc 함수를 호출하여 설치된 후크 기능을 제거하고 원래 후크 필터 기능 주소를 복원합니다.
다음은 위에서 컴파일한 Hook 함수를 사용한 예입니다.
단위 Unit1;
인터페이스
용도
Windows, 메시지, SysUtils, 클래스, 그래픽, 컨트롤, 양식, 대화 상자,
StdCtrls, ExtCtrls;
유형
TForm1 = 클래스(TForm)
메모1: TMemo;
패널1: T패널;
bSetHook: TButton;
bCancelHook: TButton;
bReadKeys: TButton;
bClearKeys: TButton;
패널2: T패널;
절차 bSetHookClick(Sender: TObject);
절차 bCancelHookClick(Sender: TObject);
절차 bReadKeysClick(Sender: TObject);
절차 bClearKeysClick(Sender: TObject);
끝;
var Form1: TForm1;
구현
{$R *.DFM}
함수 EnableKeyHook : BOOL ; 외부 'KEYHOOK.DLL';
기능 비활성화KeyHook : BOOL ; 외부 'KEYHOOK.DLL';
함수 GetKeyCount : 정수 ; 외부 'KEYHOOK.DLL';
function GetKey(idx:Integer) : Char ; 외부 'KEYHOOK.DLL';
절차 ClearKeyString; 외부 'KEYHOOK.DLL';
절차 TForm1.bSetHookClick(Sender: TObject) // 키보드 후크 설정 7
시작하다
EnableKeyHook;
bSetHook.Enabled :=거짓;
bCancelHook.Enabled:=True;
bReadKeys.Enabled :=True;
bClearKeys.Enabled :=True;
Panel2.Caption:='키보드 후크가 설정되었습니다';
끝;
절차 TForm1.bCancelHookClick(Sender: TObject) // 키보드 후크 제거
시작하다
비활성화KeyHook;
bSetHook.Enabled :=True;
bCancelHook.Enabled:=거짓;
bReadKeys.Enabled :=False;
bClearKeys.Enabled :=거짓;
Panel2.Caption:='키보드 후크가 설정되지 않았습니다';
끝;
절차 TForm1.bReadKeysClick(Sender: TObject); // 키 입력 기록 가져오기
var i:정수;
시작하다
Memo1.Lines.Clear; // Memo1의 키 입력 기록을 표시합니다.
i:=0에서 GetKeyCount-1로 수행
Memo1.Text:=Memo1.Text+GetKey(i);
끝;
절차 TForm1.bClearKeysClick(Sender: TObject); // 키 입력 기록 지우기
시작하다
메모1.지우기;
ClearKeyString;
끝;
끝.
//소스코드 끝
3. Windows95에서 DLL로 공유 메모리 구현
위의 Hook 함수가 위치한 DLL 파일에서는 공유 메모리를 사용해야 합니다. 즉, 모든 키 입력 기록이 동일한 데이터 세그먼트에 저장됩니다. 우리는 왜 이런 일을 하는가? 이는 Windows95의 DLL 호출 방식이 Windows3.X의 DLL 호출 방식과 다르기 때문입니다. 각 스레드가 동적 링크 라이브러리에 로그인하면 새 인스턴스 핸들(즉, DLL 데이터 세그먼트의 핸들)을 동적 링크 라이브러리에 전달합니다. 이를 통해 다양한 DLL 인스턴스가 서로 간섭하지 않도록 할 수 있지만 모든 DLL 인스턴스가 변수 세트를 공유하는 경우에는 몇 가지 어려움이 발생합니다. 이 문제를 해결하기 위해 여기서는 메모리 매핑 파일을 생성하여 해결합니다. 즉, Windows의 OpenFileMapping, CreateFileMapping 및
MapViewOfFile은 세 가지 기능을 달성합니다. 그것을 사용하는 방법:
…
MemFile은 THandle 유형이고, Shared는 포인터 유형이며, HOOK_MEM_FILENAME은 상수 문자열입니다.
…
MemFile:=OpenFileMapping(FILE_MAP_WRITE,False,
HOOK_MEM_FILENAME); //메모리 매핑 파일 열기
if MemFile=0 then //열기가 실패하면?_c2 메모리 매핑 파일을 생성합니다.
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
SizeOf(TShared) ,HOOK_MEM_FILENAME);
//파일을 변수에 매핑
Shared:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
지금까지 Delphi에서 후크 함수를 컴파일하는 것이 얼마나 쉬운지 이미 알고 계셨습니다. 마지막으로 여러분께 상기시켜 드리고 싶은 점은 Hook 기능이 상대적으로 강력하기는 하지만 부적절하게 사용하면 시스템 효율성에 심각한 영향을 미칠 수 있으므로 시스템 Hook 사용을 피하는 것이 좋습니다. 사용해야 할 경우 시스템 작동에 최소한의 영향을 미치도록 각별히 주의해야 합니다.
[전문 끝]