Prepare hook functions under Windows 95 with Delphi
The Windows Message Administration provides a so-called hook (hook) mechanism that enables application access control message flow μ''c4. There are a variety of hooks to capture a particular type or a range of messages. Such as: Keyboard message, mouse message, etc. We only use the keyboard hook as an example, discuss how to write a DLL program under Delphi and how to install the use of keyboard hook functions in its own procedure, and discuss how different programs use the same DLL file how to share data. First, the writing of the hook filtering function This means that the hook filtering function must be in a separate module, that is, we must first generate a DLL frame, and then add the hook function code and other related function code. We will be described as an example with the writing of keyboard hook filtering function. The specific steps are as follows: 1. Mr. 2, 2, 2, writing its own keyboard hook filter function hook filter function must be a callback function, its function 4 Stable Ofunction KeyhookProc (icode: integer; wparam: wparam; lparam : Lparam: LRESULT; stdcall; export; add its own keyboard hook handler to process the keyboard message in the generated DLL frame. The code is as follows: ... if (icode> = 0) Then BeginResult: = 0; // Initialization Return value // Add your own code END ELSE BEGINRESULT: = CallNexthook (Holdkeyhook, icode, wparam, lparam); // HoldKeyhook is Save the original key disk filter function 5 刂 · END; 3, mounting keyboard hook filter function To install a hook 筥 FD filter function should call SETWINDOWSHOKEX functions (SetWindowsHook hook installation function for Windows 3.0 is now discarded). The original shape of this function is as follows: hHOOK SETWINDOWSHOKEX (Int IDHOK, // Installed 筥 B3 subtype hookproc lpfn, // hook filter 籂 F number address Hinstance HMOD, // Task handle DWORD DWTHREADID / / Hook for purposes); Description: 蚠 A8 often calls the MakeProcinstance function to get the entry address of the preamble of the preamble, and then this address is the second parameter LPFN of SETWINDOWSHOKEX. However, because Delphi provides "smart callback", MakeProcAnstance can save the hook filter function as an entry address. This way when the application 觃 c3getMessage or PeekMessage function reads a message or a button message (WM_KEYDOWN or WM_KEYUP) from the message queue, the system will call the hook filter function KeyhookProc to process the keyboard message. 4, unload the hook filter function. When the hook function is no longer needed, you should call UNHOOKWINDOWSHOKPROC to uninstall the installed hook to release system resources.
Complete program listing follows baLibrary KEYHOOK; uses Windows; const BUFFER_SIZE = 16 * 1024; const HOOK_MEM_FILENAME = 'SAMPLE KEY_HOOK_MEM_FILE'; const HOOK_MUTEX_NAME = 'SAMPLE KEY_HOOK_MUTEX_NAME'; typeTShared = recordKeys: array [0..BUFFER_SIZE] of Char; KeyCount : Integer; end; pShared = ^ TShared; varMemFile, HookMutex: THandle; hOldKeyHook: HHook; ProcSaveExit: Pointer; Shared: pShared; // filter function keyboard hook function KeyHookProc (iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; export; const KeyPressMask = $ 80000000; beginif iCode <0 thenResult: = CallNextHookEx (hOldKeyHook, iCode, wParam, lParam) else beginif ((lParam and KeyPressMask) = 0) then // key pressed beginShared ^ .Keys [ Shared ^ .keycount]: = char (WParam and $ 00ff); inc (shared ^ .keycount); if Shared ^ .Keycount> = Buffer_size-1 the shared ^ .Keycount: = 0; End; iCode: = - 1; Result: = CallNextHookEx (hOldKeyHook, iCode, wParam, lParam); end; end; // set the filter function hook function EnableKeyHook: BOOL; export; beginShared ^ .KeyCount: = 0; // initialize keyboard pointer if hOldKeyHook = 0 then beginhOldKeyHook : = SETWINDOWSHOKEX (White _KEYBOARD, KeyHookProc, HInstance, 0); end; Result: = (hOldKeyHook <> 0); end; // undo filter function hook function DisableKeyHook: BOOL; export; beginif hOldKeyHook <> 0 thenbeginUnHookWindowsHookEx (hOldKeyHook); // release Keyboard HookholdKeyhook: = 0; Shared ^ .keycount: = 0; End; Result: = (HoldKeyHOK = 0); END; // Number of function getKeycount: integer; export; beginResult: = shared ^ . KeyCount; End; Objective getKey (index: integer): char; export; beginResult: = shared ^ .keys [index]; end; // Empty keyboard buffer procedure clearkeystring; export; beginshared ^ .KeyCount: = 0; End; // DLL Exit Process Procedure KeyhooKexit; FAR; Beginif Holdkeyhook <>
0 then DisableKeyHook; UnMapViewOfFile (Shared); // release the memory image file CloseHandle (MemFile); // Close image file ExitProc: = ProcSaveExit; end; exports // output functions defined EnableKeyHook, DisableKeyHook, GetKeyCount, ClearKeyString, GetKey; begin // DLL initialization section HookMutex: = CreateMutex (nil, True, HOOK_MUTEX_NAME); // by creating the memory image file to the shared memory memFile: = OpenFileMapping (FILE_MAP_WRITE, False, HOOK_MEM_FILENAME); if memFile = 0 thenMemFile: = 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; // Save the DLL's exitProceXitProc: = @keyhookexit; // Set the DLL new EXITPROCEND. // Source code ends, use the prepared keyboard hook filter function in your own program. After the hook function is prepared, it is actually very simple: first call SETWINDOWSHOKEX to install your hook filter function while saving the original hook filter function address. At this time, the hook function starts to work, it will handle the keyboard message according to your requirements. When the program is running or no longer need to monitor the keyboard message, call the UnHookWindowsHookProc function to uninstall the installed hook function while restoring the original hook filtering function address.
The following is the use of hook function above preparation examples: unit Unit1; interfaceusesWindows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; typeTForm1 = class (TForm) Memo1: TMemo; Panel1: TPanel; bSetHook : TButton; bCancelHook: TButton; bReadKeys: TButton; bClearKeys: TButton; Panel2: TPanel; procedure bSetHookClick (Sender: TObject); procedure bCancelHookClick (Sender: TObject); procedure bReadKeysClick (Sender: TObject); procedure bClearKeysClick (Sender: TObject) ; end; var Form1: TForm1; implementation {$ R * .DFM} function EnableKeyHook: BOOL; external 'KEYHOOK.DLL'; function DisableKeyHook: BOOL; external 'KEYHOOK.DLL'; function GetKeyCount: Integer; external 'KEYHOOK.DLL '; function GetKey (idx: Integer): Char; external' KEYHOOK.DLL '; procedure ClearKeyString; external' KEYHOOK.DLL '; procedure TForm1.bSetHookClick (Sender: TObject); // set the keyboard hook 7óbeginEnableKeyHook; bSetHook.Enabled: = False; bcancelhook.enabled: = true; breakkeys.enabled: = true; bclearkeys.enable: = true; panel2.caption: = 'keyboard hook has set'; end; procedure t Form1.bCancelHookClick (Sender: TObject); // unloading keyboard hook beginDisableKeyHook; bSetHook.Enabled: = True; bCancelHook.Enabled: = False; bReadKeys.Enabled: = False; bClearKeys.Enabled: = False; Panel2.Caption: = ' Keyboard hooks are not set '; end; procedure tform1.breadKeysClick (sender: TOBJECT); // History of hitting history VAR i: integer; beginMemo1.Lines.clear; // In MEMO1 Display History for i: = 0 to getKeycount-1 Domemo1.text: = MEMO1.TEXT GETKEY (i); end; procedure tform1.bclearkeysclick (sender: TOBJECT); // Clear key history beginMemo1.clear; clearkeystring; end; end; / Source End Third, Windows95 implements the DLL file where the shared memory is implemented in the DLL in the DLL, you need to use shared memory, ie, all records of all keystrokes are stored in the same data segment.
Why do you do this? This is because the Windows 95 DLL call method is different from the WINDOWS3.x method. Each into a dynamic connection library will enter a new instance handle (ie the handle of the DLL data segment) when logging in to a dynamic connection library. This makes the DLL of each instance that does not interfere with each other, but this brings some difficulties to all DLL instances. In order to solve this problem, we solve this by establishing a memory mapping file here. That is, the three functions of Windows OpenFileMapping, CreateFileMapping, and MapViewOffile are implemented. The method is as follows: ... Memfile is the THANDLE type, Shared is a pointer type, hook_mem_filename is a constant string ... Memfile: = OpenFileMapping (file_map_write, false, hook_map_filename); // Open memory map If Memfile = 0 THEN / / Open failure c2 built memory-mapped file memFile: = CreateFileMapping ($ FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf (TShared), HOOK_MEM_FILENAME); // variable mapping file to Shared: = MapViewOfFile (memFile, File_MAP_WRITE, 0,0,0); to So far you already know how easy it is to prepare a hook function with Delphi. Finally, I have to remind everyone: Although the hook function is more functional, if the use of improper use will seriously affect the efficiency of the system, try to avoid using the system hook. It should be careful not to use it, should be careful, which should make it impact on the operation of the system as small as possible. [Applause] Author: Adrian Source: No author email: No author's website: No