-
Суть проблемы в следующем: ловушка на щелчки мыши, встроенная в тело исполняемой пр-мы(не dll), полностью перестает обрабатывать сообщения стоит только отправить машину в ждущий, спящий режимы. То есть она просто остается болтаться в процессах, не выполняя никакой полезной работы. Ошибка в результате внесенных мною в код изменений исключается, т.к. пробовал запускать чистый hook с единственной сигнализацией в виде диалог. сообщения - итог тот же. Можно ли исправить это поведение программы? Буду благодарен ответившим.
-
> inkognito (28.01.13 21:58) The hook procedure should process a message in less time than the data entry specified in the LowLevelHooksTimeout value in the following registry key: HKEY_CURRENT_USER\Control Panel\Desktop The value is in milliseconds. If the hook procedure times out, the system passes the message to the next hook. However, on Windows 7 and later, the hook is silently removed without being called. There is no way for the application to know whether the hook is removed.http://msdn.microsoft.com/en-us/library/windows/desktop/ms644986(v=vs.85).aspx
-
Спасибо, нашел выход перекинув hook в обычную dll, но все же странно как-то..
-
> inkognito (29.01.13 21:43) [2]
> перекинув hook в обычную dll
у этого способа куча недостатков.
-
Согласен, замучился с отловом ошибок.. В особенности в момент выгрузки библиотеки, интересная закономерность: если закрываю все подопытные программы(то есть те в которых эти хук сообщения принимались) раньше чем выгружаю длл - видимых проблем нет, но стоит это сделать после и ошибки начинают сыпаться веером, включая и все остальные процессы, даже explorer.. :( По правде сказать, так и не нашел этому решения, в длл мало что смыслю..
-
> inkognito (30.01.13 05:18) [4]
поэтому не надо лезть с хуками в dll, особенно если не понимаешь как оно работает, используй LL hooks, в обработчике не выполняй длительные блокирующие операции.
-
> но стоит это сделать после и ошибки начинают сыпаться веером, > включая и все остальные процессы, даже explorer.. :(
Финализация значит не верная.
-
Вот, собственно, сам модуль dll. Не знаю какая финализация здесь требуется, кроме разве что высвобождения popupmenu.. library lib2;
uses
forms,
menus,
windows,
dialogs,
messages,
controls,
Unit1 in 'Unit1.pas' ;
type
TFm = class(TForm)
procedure x1Click(Sender: TObject);
end;
var
pt : TPoint;
theHook : THandle;
fm:TFm;
popupmenu1:tpopupmenu;
procedure TFm.x1Click(Sender: TObject);
begin
showmessage('#')
end;
procedure DLLProc_(Reason: Integer);
var i:integer;
begin
if Reason = DLL_PROCESS_DETACH then
end;
function MouseHook(nCode, wParam, lParam : integer) : Lresult; stdcall;
Begin
case wParam of
WM_RBUTTONUP :
begin
popupmenu1 := tpopupmenu.create(application);
with popupmenu1.items do add(newitem('click',0,False,True,fm.x1Click,0,'MenuItem1'));
popupmenu1.popup(mouse.cursorpos.x,mouse.cursorpos.y);
end
else
Result := CallNextHookEx(theHook, nCode, wParam, lParam);
end;
End;
procedure Start;
begin
theHook := SetWindowsHookEx(wh_mouse, @mouseHook, hInstance, 0);
if theHook = 0 then
messageBox(0,'Error!','Error!',mb_ok);
end;
procedure Remove;
begin
UnhookWindowsHookEx(theHook);
end;
exports
Start index 1 name 'Start',
Remove index 2 name 'Remove';
begin
DLLProc:= @DLLProc_;
end. Баги начинают плодиться именно на выгрузке, но с условием, что не было закрыто хотя бы одно из чужих окон, куда был произведен правый щелчок мыши.
-
-
Ну незнаю )), вообще то это почти полный оригинал примера размещенного в небезизвестной DRKB 3, вполне рабочий, надо сказать, ну кроме выхода..) Думаю, вас прежде всего смутил:
type
TFm = class(TForm)
procedure x1Click(Sender: TObject);
end;
..но для меня это стало производственной необходимостью, иначе не выходило вписать обработчик меню x1Click в аdd(newitem(..)). Подозреваю, что дело именно в нем, потому как с showmessage() заместо popupmenu1.popup() работает все распрекрасно.
-
-
> inkognito (01.02.13 04:21) [9]
ты неправильно понимаешь принцип работы данного вида хуков. эта область затрагивает чужие процессы, туда нельзя лезть, не понимая что делаешь. разобраться "по быстрому" с хуками не выйдет и не надейся.
-
Наверное так и есть и GunSmoker прав на 200%, но способ все-равно найду, уж больно заманчивая идейка!)
-
-
Rouse_: Да, но ведь изменения довольно косметические: убрал ненужный код на прочие кнопки мыши в обработчике MouseHook , добавил пару переменных(одну, а именно fm вообще для совместимости только), добавил dllproc, которая здесь вообще ничего не делает.. Еще забыл убрать лишнюю глоб. переменную pt из этого примера. Вот, пожалуй, и все вроде бы.. Повторюсь, что если подменяю P.Popup() на банальный ShowMessage() - все работает без нареканий, по крайней мере с моей скромной стороны.
-
А ты не добавляй dllproc, меню создал, отобразил - разрушай его сразу, а не в dllproc, избавишся и от проблем и от мемлика. Далее, форма у тебя не создается, тут вообще все упасть должно, да и зачем тебе нужна она? Хочешь показать свое меню, так и работай с ним нормально CreatePopupMenu + TrackPopupMenu + DestroyMenu, а не то что ты написал где все в кучу смешано и API и VCL.
-
Rouse_: Знаю что вы профи, одна только ваша статья о компиляторе Delphi очень даже мне пригодилась. Поэтому расчитываю на ваше компетентное мнение в отношении стратегии внедрения этого треклятого попапа грамотно и без последствий, если это возможно конечно...
-
Спасибо, попробую. Не подозревал о наличие CreаtPopupMenu, дилетант.. )) Немного опоздал с предпоследним комментарием. :)
-
Если задача встроить свой пункт меню в уже существующее, то имеет смысл сделать так, по шагам: 1. перехватить TrackPopupMenu 2. в пойманном вызове удостоверится что это требуемое нам меню (ну например по составу его итемов или по хэндлу окна) 3. добавить свой пункт через InsertMenuItem 4. перекрыть обработчик окна указанный в параметре hWnd 5. вызывать оригинальный обработчик TrackPopupMenu 6. в перекрытом обработчике окна обработать WM_COMMAND где проверить, выбран наш пункт меню. 6.1 если выбран наш - выполнить его обработчик (например показать сообщение) 6.2 если не наш - вызвать оригинальный обработчик 7. снять перехват обработчика окна 8. по завершении работы снять перехват TrackPopupMenu
-
ЗЫ: ну это при условии что в uFlag отсутствует TPM_RETURNCMD, если он присутствует, то пункты 4, 6, 6.1, 6.2, 7 лишние. В место 6.1 проверять то что вернула TrackPopupMenu и если это наш пункт меню - то выполнить его обработчик.
|