Keybd hook trouble

Тема в разделе "WASM.WIN32", создана пользователем SolidCode, 11 июн 2005.

  1. SolidCode

    SolidCode New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2002
    Сообщения:
    162
    Адрес:
    Kazakhstan
    Простите, знаю, что тема избитая.

    Но моего случая пока не нашёл.

    Я делаю слухатель клавы через глобальный выньдовый хук. Библиотечку-слухач прилагаю. Задача стандартная: отслеживать все нажатия клавиш.

    Но в основной проге нет окна. Лишь основной тред. Ему сообщения надо слать с помощью PostThreadMessage. В основной проге в цикле вытаскиваю сообщения:
    Код (Text):
    1.  
    2.     invoke  InstallHook,eax
    3.     invoke  CreateFile,offset szLogFile,GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,0,0
    4.         mov     hFile,eax
    5.     invoke  Listening,TRUE
    6.     .while TRUE
    7.         invoke GetMessage,addr msg,NULL,0,0
    8.         .break.if eax==0
    9.         .if msg.message==WM_KEYDOWN
    10.             invoke  MessageBox,0,CommandLine,offset AppName,MB_OK
    11. ;            mov     eax,msg.wParam
    12. ;            .if eax>=VK_A && eax<=VK_Z
    13. ;                invoke  WriteFile,hFile,addr msg.wParam,1,addr dwWritten,0
    14. ;            .endif
    15.         .endif
    16.     .endw
    17.     invoke  CloseHandle,hFile
    18.     invoke  UninstallHook
    19.  


    Но ни записи в файл ни даже Msb не получаю, а выходит замкнутый круг. Основная прога не получает сообщения WM_KEYDOWN, зато непрерывным потоком валятся какие-то левые сообщения и вся эта система виснет и круто тормозит машину. Не пойму в чём дело. Кто шлёт те сообщения?

    Номера сообщений: 184h и 18184h.

    [​IMG] 1876652513__KHL32.ZIP
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Гм, а если нет окна, то есть ли очередь сообщений?
     
  3. ProgramMan

    ProgramMan New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2004
    Сообщения:
    263
    так как окна нет, то и связь через сообщения невозможна
     
  4. Turkish

    Turkish New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2004
    Сообщения:
    80
    Адрес:
    Russia
    В исходниках BackOrifice 2000 используется цикл выборки сообщений без окна и все работает.
     
  5. Turkish

    Turkish New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2004
    Сообщения:
    80
    Адрес:
    Russia
    Код (Text):
    1.  
    2. KeyboardProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
    3.    
    4.     .if nCode&80000000h
    5.         invoke  CallNextHookEx,hHook,nCode,wParam,lParam
    6.         ret
    7.     .endif
    8.     invoke  CallNextHookEx,hHook,nCode,wParam,lParam
    9.     ; Зачем 1 раз вызывать по условию, а второй раз всегда?
    10.     ;убери первый кусок
    11.     ;а следующую часть надо вызывать когда у тебя nCode==HC_ACTION
    12.     .if boolListening!=FALSE
    13.         push    eax
    14.             ;here we do our part
    15. ;            .if !(lParam&KEY_PRESSED)
    16. ;                mov     edx,WM_KEYDOWN
    17. ;            .else
    18. ;                mov     edx,WM_KEYUP
    19. ;            .endif
    20.             mov     edx,lParam
    21.             shr     edx,15
    22.             add     edx,WM_KEYDOWN
    23.             ;Что здесь происходит я не понял
    24.             ;Но в edx у тебя не WM_KEYDOWN
    25.             invoke  PostThreadMessage,nOwnerThread,edx,wParam,lParam
    26.         pop     eax
    27.     .endif
    28. @ret:
    29.     xor     eax,eax
    30.     ret
    31.  
    32. KeyboardProc endp
    33.  
     
  6. SolidCode

    SolidCode New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2002
    Сообщения:
    162
    Адрес:
    Kazakhstan
    S_T_A_S_, ProgramMan

    Вообще-то в SDK говорится, что можно в треде насильно создать очередь сообщений с помощью процедур GetMessage или PeekMessage. Они создают очередь сообщений, если она отсутствует, а потом производят соответствующие действия с нею. А слать сообщения треду без окна можно как раз с помощью той процедуры PostThreadMessage, где вместо хэндла окна используется ID треда.



    Turkish
    Код (Text):
    1.             ;here we do our part
    2. ;            .if !(lParam&KEY_PRESSED)
    3. ;                mov     edx,WM_KEYDOWN
    4. ;            .else
    5. ;                mov     edx,WM_KEYUP
    6. ;            .endif
    7.             mov     edx,lParam
    8.             shr     edx,15
    9.             add     edx,WM_KEYDOWN
    10.             ;Что здесь происходит я не понял
    11.             ;Но в edx у тебя не WM_KEYDOWN
    12.             invoke  PostThreadMessage,nOwnerThread,edx,wParam,lParam


    Здесь я беру lParam, в котором дополнительная информация о событии нажатой клавиши. Самый верхний бит (31) утановлен, если клавиша нажата, и сброшен, если клавишу отпустили. Ой, а что это я двигаю биты на 15? Надо же на 31! Сейчас исправлю.



    Ура, заработала!!!

    В аттаче высылаю тем, кто хочет эту DLL. Полный масмовский проект. Она отслеживает все события клавы во всех процессах и шлёт сообщения своему хозяину. Вместо WM_KEYDOWN я использовал WM_USER+WM_KEYDOWN, чтобы различать внутри цикла выборки сообщений хозяина откуда пришло клавишное событие: в рамках собственного потока или от библиотечного хука. Для активации хука нужно из хозяина вызвать следующее из того потока, который будет обрабатывать приходящие сообщения:
    Код (Text):
    1. InstallHook(GetCurrentThreadId())


    Для снятия хука вызываем UninstallHook(). Но это можно делать в начале и в конце проги. А включать копию потока клавиатурных сочетаний себе можно с помощью
    Код (Text):
    1. Listening(TRUE)


    Для выключения соответственно высылаем в этой же функции FALSE.

    [​IMG] _1148334584__KHL32.ZIP