|
#1
|
|||
|
|||
И сново Хуки
Добрый день уважаемые форумчане и форумчанки.
Пишу безоконную апи программу, которая должна запоминать выкрутасы мышки(движения в основном) сохранять их в файл, что бы потом другая программа могла их воспроизводить. если интересно зачем нужно, расскажу, но не в этом суть. События мышки ловлю довольно просто, обычным хуком "WH_Mouse_LL", тут всё понятно. позже могу привести код. В оконном не апи приложении всё было легко и для примера все выкрутасы записывались в мемо. проблема оказалась в следующем... если программа делает ещё что либо кроме хуков, то каждый раз она ожидает все остальные задачи, а только потом работает с мышью, в итоге пока она выполняет остальные задачи, мышь не шевелится, решением я считал создание дополнительного потока, но был не прав дополнительный поток включает хук и завершается, а после завершения потока хук естественно не пашет. если в конце потока поставить бесконечный слип, то хук ждет окончания слипа и до тех пор держит мышь застывшей, ну то есть то же самое что и в предыдущий раз, вывод: я дурак, понятное дело что нужен второй поток, но не понятно как сделать так же как делает это оконное приложение, чтобы программа или поток не завершался выполнив все, а просто ждал с моря погоды, помогите с этим или подскажите другое решение, но естественно хук должен быть |
#2
|
||||
|
||||
завершай вызов LowLevelMouseProc callback function как можно быстрее
Пишу программы за еду. __________________ |
Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
reqyz (12.03.2014)
|
#3
|
||||
|
||||
Цитата:
Код:
var MouseHook: HHOOK; function LowLevelMouseProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall; var s: string; begin Result:= CallNextHookEx(MouseHook, nCode, WParam, LParam); case WParam of WM_LBUTTONDOWN: s:= 'LBUTTONDOWN'; WM_LBUTTONUP: s:= 'LBUTTONUP'; WM_LBUTTONDBLCLK: s:= 'LBUTTONDBLCLK'; WM_RBUTTONDOWN: s:= 'RBUTTONDOWN'; WM_RBUTTONUP: s:='RBUTTONUP'; WM_RBUTTONDBLCLK: s:= 'RBUTTONDBLCLK'; WM_MBUTTONDOWN: s:= 'MBUTTONDOWN'; WM_MBUTTONUP: s:= 'MBUTTONUP'; WM_MBUTTONDBLCLK: s:= 'MBUTTONDBLCLK'; WM_MOUSEMOVE: s:= 'MOUSEMOVE'; WM_MOUSEWHEEL: s:= 'MOUSEWHEEL'; end; Form1.Memo1.Lines.Add(s + ': ' + IntToStr(Mouse.CursorPos.X) + 'X' + IntToStr(Mouse.CursorPos.Y)); end; procedure TForm1.FormCreate(Sender: TObject); begin MouseHook:= SetWindowsHookEx(WH_MOUSE_LL {14}, @LowLevelMouseProc, HInstance, 0); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin UnhookWindowsHookEx(MouseHook); end; Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#4
|
||||
|
||||
Цитата:
Код:
Sleep(250); Пишу программы за еду. __________________ |
#5
|
||||
|
||||
Действительно, появились пропуски, не успевает "выхлоп" ловушки отработать, но возник вопрос - а зачем в этой процедуре что-то тяжёлое выполнять, она ведь для этого не предназначена, чисто вывод, в крайнем случае флажок какойнить изменить или метку подправить, в смысле кесарю кесарево
Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#6
|
||||
|
||||
Цитата:
|
#7
|
|||
|
|||
В итоге что мне делать? без окон не обойтись получается?
|
#8
|
||||
|
||||
создай очередь обработки, куда бы LowLevelMouseProc добавляла, а дочерний поток из нее обрабатывал. хотя трудно представить что должна быть за обработка действий мыши, чтобы занимала столь длительное время.
можно и без окна. только как программу закрывать будешь?) Пишу программы за еду. __________________ |
#9
|
|||
|
|||
Код:
program HookApi; USES WINDOWS; type WPARAM = Longint; LPARAM = Longint; LRESULT = Longint; DWORD = LongWord; PDWORD = ^DWORD; HHOOK = type LongWord; HWND = type LongWord; UINT = LongWord; BOOL = LongBool; TPoint = packed record X: Longint; Y: Longint; end; PMouseHookStruct = ^tagMOUSEHOOKSTRUCT; tagMOUSEHOOKSTRUCT = packed record pt: TPoint; hwnd: HWND; wHitTestCode: UINT; dwExtraInfo: DWORD; end; PSecurityAttributes = ^_SECURITY_ATTRIBUTES; _SECURITY_ATTRIBUTES = record nLength: DWORD; lpSecurityDescriptor: Pointer; bInheritHandle: BOOL; end; TFNHookProc = function (code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall; const HC_ACTION = 0; user32 = 'user32.dll'; kernel32 = 'kernel32.dll'; GENERIC_WRITE = $40000000; OPEN_ALWAYS = 4; function CallNextHookEx(hhk: HHOOK; nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; external user32 name 'CallNextHookEx'; function SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc; hmod: HINST; dwThreadId: DWORD): HHOOK; stdcall; external user32 name 'SetWindowsHookExA'; function UnhookWindowsHookEx(hhk: HHOOK): BOOL; stdcall; external user32 name 'UnhookWindowsHookEx'; function GetModuleFileName(hModule: HINST; lpFilename: PChar; nSize: DWORD): DWORD; stdcall; external kernel32 name 'GetModuleFileNameA'; function CreateFile(lpFileName: PChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; external kernel32 name 'CreateFileA'; function CreateThread(lpThreadAttributes: Pointer; dwStackSize: DWORD; lpStartAddress: Pointer; lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall; external kernel32 name 'CreateThread'; procedure Sleep(milliseconds: Cardinal); stdcall; external kernel32 name 'Sleep'; function IntToStr(const Value: Int64): String;overload; begin Str(Value, Result); end; var hHookMouse:THandle; function LowLevelMouseProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT stdcall; var Mouse:PMouseHookStruct; begin if nCode = HC_ACTION then Result := CallNextHookEx(hHookMouse, nCode, WParam, LParam); Mouse:=PMouseHookStruct(LParam); if(Wparam=512)then begin //записываем end; end; var LogFileName: array[0..264]of Char; HFile:THandle; id:THandle; s:integer; const WH_Mouse_LL = 14; begin hHookMouse := SetWindowsHookEx(WH_Mouse_LL, LowLevelMouseProc, hInstance, 0); sleep(cardinal(-1)); end. если поможите решить эту праблу, то с остальным разберусь. если ставить слип, как я и говорил, ждет окончания слипа и мышь застыла, если ничего не ставить, то выходит из программы, вопрос: что делать? оконные приложения же умеют не выходить из программы ничего не делая и при этом они точно не используют слип, а может как то иначе можно? задача была решена следующим образом: после регистрации хука добавлена строчка Код:
while GetMessage (Msg, 0, 0, 0) do begin endl; в итоге зависания нет, из потока так тоже не выйдет и всё записывается быстро и чётко) всем спасибо, но если знаете другое решение, отпишитесь) новая не смертельная, но неприятная прабла, на компе моём Авира стоит, и ругается когда компилю приложение с доп потоком. Кто нибудь сталкивался? знает как обойти? делаю так.. Код:
program HookApi; USES windows... function LowLevelMouseProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT stdcall; var Mouse:PMouseHookStruct; begin if nCode = HC_ACTION then Result := CallNextHookEx(hHookMouse, nCode, WParam, LParam); Mouse:=PMouseHookStruct(LParam); if(Wparam=512)then begin ... ... end; end; procedure GoHook({Param:Pointer}); stdcall; const WH_Mouse_LL = 14; var Msg: TagMsg; begin hHookMouse := SetWindowsHookEx(WH_Mouse_LL, LowLevelMouseProc, hInstance, 0); while GetMessage(Msg, 0, 0, 0) do begin end; end; begin CreateThread(nil,0,@GoHook,nil,0,id); ... //делает свои остальные дела ... end. авира матюгаться начинает, а если поток один, то молчит. Что ей не нравится? и как обойти? Последний раз редактировалось reqyz, 13.03.2014 в 14:15. |
#10
|
||||
|
||||
Цитата:
вот классика: Код:
var AMsg: TMsg; while GetMessage(AMsg, 0, 0, 0) do begin TranslateMessage(AMsg); DispatchMessage(AMsg); end; и как все-таки программу закрывать будешь? Пишу программы за еду. __________________ |
#11
|
|||
|
|||
Цитата:
в Код:
TranslateMessage(AMsg); DispatchMessage(AMsg); месадж луп не было, так как без окон нет и сообщений, над завершением программы пока не думал, но придумаю. горячие клавиши например, или хук определенной клавиши "Esc" например, тут ничего сложного не будет в принципе, сейчас с авирой праблы, но попытаюсь поменять функционал основного потока и хукного, может не будет тогда ворчать) а GetMessage в данном случае, как удачная альтернатива слипу, которая и из потока выйти не даст и работать потоку не мешает) |
#12
|
||||
|
||||
Цитата:
Код:
program Project1; uses Windows, Messages, SysUtils; var hMouseHook: HHOOK; AMsg: TMsg; const WH_MOUSE_LL = 14; function LowLevelMouseProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin Result:=CallNextHookEx(hMouseHook, nCode, wParam, lParam); if (PMouseHookStruct(lParam)^.pt.X<5) and (PMouseHookStruct(lParam)^.pt.Y<5) then PostQuitMessage(0); end; begin hMouseHook:=SetWindowsHookEx(WH_MOUSE_LL, @LowLevelMouseProc, HInstance, 0); while GetMessage(AMsg, 0, 0, 0) do begin TranslateMessage(AMsg); DispatchMessage(AMsg); end; UnhookWindowsHookEx(hMouseHook); Windows.Beep(1000, 500); end. Пишу программы за еду. __________________ |
#13
|
|||
|
|||
Да, запустил ваш пример, вы правы, видимо я немного неверно интерпретировал работу функции GetMessage
c авирой разобрался, тему можно закрывать) Последний раз редактировалось reqyz, 14.03.2014 в 13:28. |