Перехват клавиш

Тема в разделе "WASM.WIN32", создана пользователем Eagle712, 12 сен 2008.

  1. Eagle712

    Eagle712 New Member

    Публикаций:
    0
    Регистрация:
    12 сен 2008
    Сообщения:
    1
    есть хук:
    Код (Text):
    1. unit Unit1;
    2.  
    3. interface
    4.  
    5. uses
    6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
    7.   Dialogs, StdCtrls;
    8.  
    9. type
    10.   TForm1 = class(TForm)
    11.     Memo1: TMemo;
    12.     procedure FormCreate(Sender: TObject);
    13.     procedure FormDestroy(Sender: TObject);
    14.   end;
    15.  
    16. var
    17.   Form1: TForm1;
    18.  
    19. implementation
    20.  
    21. var
    22.   hHook: THandle;
    23.  
    24. {$R *.dfm}
    25.  
    26. function LowLevelKeyboardProc(nCode: Integer;
    27.   WParam: WPARAM; LParam: LPARAM): LRESULT stdcall;
    28.  
    29. type
    30.   PKbdDllHookStrukt = ^TKbdDllHookStrukt;
    31.   _KBDLLHOOKSTRUCT = record
    32.     vkCode: DWORD;
    33.     scanCode: DWORD;
    34.     flags: DWORD;
    35.     time: DWORD;
    36.     dwExtraInfo: PDWORD;
    37.   end;
    38.   TKbdDllHookStrukt = _KBDLLHOOKSTRUCT;
    39.  
    40. const
    41.   RPT_WPARAM_DATA = 'Keyboard message = %s ';
    42.   RPT_LPARAM_DATA = 'scan code = %s [%d]';
    43.  
    44. var
    45.   StrResult: String;
    46. begin
    47.   StrResult := '';
    48.   if nCode = HC_ACTION then
    49.     Result := CallNextHookEx(hHook, nCode, WParam, LParam);
    50.   case WParam of
    51.     WM_KEYDOWN: StrResult := Format(RPT_WPARAM_DATA, ['WM_KEYDOWN']);
    52.     WM_KEYUP: StrResult := Format(RPT_WPARAM_DATA, ['WM_KEYUP']);
    53.     WM_SYSKEYDOWN: StrResult := Format(RPT_WPARAM_DATA, ['WM_SYSKEYDOWN']);
    54.     WM_SYSKEYUP: StrResult := Format(RPT_WPARAM_DATA, ['WM_SYSKEYUP']);
    55.   end;
    56.   StrResult := StrResult + Format(RPT_LPARAM_DATA, [
    57.     Chr(PKbdDllHookStrukt(LParam)^.vkCode), PKbdDllHookStrukt(LParam)^.vkCode]);
    58.   Form1.Memo1.Lines.Add(StrResult);
    59. end;
    60.  
    61. procedure TForm1.FormCreate(Sender: TObject);
    62. const
    63.   WH_KEYBOARD_LL = 13;
    64. begin
    65.   hHook := SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
    66.   if hHook = 0 then RaiseLastOSError;
    67. end;
    68.  
    69. procedure TForm1.FormDestroy(Sender: TObject);
    70. begin
    71.   if not UnhookWindowsHookEx(hHook) then RaiseLastOSError;
    72. end;
    73.  
    74. end.
    и вот я не могу найти можно ли здесь перехватываемые коды клавиш менять на другие и посылать винде дальше?
    например в чужом приложении нажали A, а этому приложению пришло B.и еще вопрос: многие советуют глобальные хуки делать в dll. зачем это нужно и стоит ли переделывать этот в dll?
     
  2. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Нет нельзя. Можно только блокировать дальнейшую обработку клавиши (не вызывать следующий хук и вернуть TRUE), и сгенерировать нужнуй код с помощью kbd_event.

    Более правильно - фильтр драйвер на клавиатуру.
     
  3. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    При использовании WH_KEYBOARD_LL делать процедуру-обработчик хуков в dll совсем не обязательно - обработчик хуков вызывается в контексте установившего хук процесса (msdn говорит, что вызов происходит посылкой оконного сообщения установившему потоку - т.е. поток должен иметь цикл обработки сообщений). katrus говорит, что менять код клавиши нельзя - видимо, копия структуры KBDLLHOOKSTRUCT в адресном пространство процесса, установившего хук, после использования просто отбрасывается.

    А вот, например, вызов SetWindowsHookEx с параметром WH_GETMESSAGE подразумевает загрузку кода хук-процедуры в адресное пространство других процессов. Именно поэтому в таком случае хук-процедура должна находится в dll - windows не будет грузить в процессы exe-файл. И, кстати, при использовании WH_GETMESSAGE данные можно подменять:
    Код (Text):
    1. LRESULT CALLBACK HookProc(int code, WPARAM wp, LPARAM lp)
    2. {
    3.     static const wchar_t ValidText [] = L" desu";
    4.     static const wchar_t* pText = ValidText;
    5.  
    6.     if (code < 0  ||  wp == PM_NOREMOVE  ||  ((MSG*)lp)->message != WM_CHAR)
    7.         return CallNextHookEx(NULL, code, wp, lp);
    8.  
    9.     ((MSG*)lp)->wParam = (WPARAM)*pText++;
    10.     if (!*pText)
    11.         pText = ValidText;
    12.     return CallNextHookEx(NULL, code, wp, lp);
    13. }