Господа, помогите понять в целях повышения самообразованности... СОздаю хук типа WH_CALLWNDPROC и в него не приходят сообщения WM_MOUSEMOVE... Это особенность хука (про нее правда в MSDN ничего не написано)? ОС Windows 2000. Обойти проблему удалось использованием WH_MOUSE_LL — низкоуровневого мышиного хука. Но для меня так и осталось непонятным, почему хук WH_CALLWNDPROC не ловит сообщения мыши. Если заменить WH_CALLWNDPROC на хук WH_GETMESSAGE — все работает! Мне всегда казалось, что разница между этими хуками только в моменте перехвата сообщения, а не в составе отлавливаемых сообщений... В чем бы могло быть дело? Может какой-то другой хук не передает сообщение дальше???
Кстати еще вопро в чем разница между низкоуровневыми (*_LL) и не низкоуровневыми хуками?
Здравствуйте, Kochuev, Вы писали:
K>Господа, помогите понять в целях повышения самообразованности... СОздаю хук типа WH_CALLWNDPROC и в него не приходят сообщения WM_MOUSEMOVE... Это особенность хука (про нее правда в MSDN ничего не написано)? ОС Windows 2000. Обойти проблему удалось использованием WH_MOUSE_LL — низкоуровневого мышиного хука. Но для меня так и осталось непонятным, почему хук WH_CALLWNDPROC не ловит сообщения мыши. Если заменить WH_CALLWNDPROC на хук WH_GETMESSAGE — все работает! Мне всегда казалось, что разница между этими хуками только в моменте перехвата сообщения, а не в составе отлавливаемых сообщений... В чем бы могло быть дело? Может какой-то другой хук не передает сообщение дальше???
Не совсем пойму... Хук-то глобальный. Для всех окон перехватывает...
LT> Вообще, для мыши есть WH_MOUSE.
K>>Кстати еще вопро в чем разница между низкоуровневыми (*_LL) и не низкоуровневыми хуками?
LT> Низкоуровневые работают в контексте установившего их потока.
Т.е. можно не писать DLL для перехвата? Я правильно понял?
Hello Leonid Troyanovsky, you wrote:
> Низкоуровневые работают в контексте установившего их потока.
А также: "The system calls this function every time a new keyboard input
event is about to be posted into a thread input queue. The keyboard input
can come from the local keyboard driver or from calls to the keybd_event
function."
В то время как обычный хук "The system calls this function whenever an
application calls the GetMessage or PeekMessage function and there is a
keyboard message (WM_KEYUP or WM_KEYDOWN) to be processed"
И еще, работа низкоуровневого хука жестко ограничена по времени. "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 does not return during
this interval, the system will pass the message to the next hook."
Всем спасибо за оказанную помощь Вы помогли несколько все разложить по полочкам
Правда, еше не совсем понятно, почему при иснользовании НЕ низкоуровневого хука, процедура хука перестает перехватывать сообщения мыши, когда курсор находится в НЕ-клиентской области какого-либо окна. именно из-за этого и пришлось использовать низкоуровневый хук. Возможно это из-за каких-то других хуков, перехватывающих не пропускающих соощение по цепочке хуков? Если кто-то знает, почему, буду очень благодарен.
Здравствуйте, Kochuev, Вы писали:
K>Всем спасибо за оказанную помощь Вы помогли несколько все разложить по полочкам
K>Правда, еше не совсем понятно, почему при иснользовании НЕ низкоуровневого хука, процедура хука перестает перехватывать сообщения мыши, когда курсор находится в НЕ-клиентской области какого-либо окна. именно из-за этого и пришлось использовать низкоуровневый хук. Возможно это из-за каких-то других хуков, перехватывающих не пропускающих соощение по цепочке хуков? Если кто-то знает, почему, буду очень благодарен.
Может потому, что не то сообщение смотришь. Попробуй WM_NCMOUSEMOVE
Здравствуйте, AcidTheProgrammer, Вы писали:
ATP>Может потому, что не то сообщение смотришь. Попробуй WM_NCMOUSEMOVE
Я говорю о хуке WH_MOUSE, который не передает в процедуру хука никаких сведений о сообщении. Так что возможности смотреть сообщения нет, а значит, проблема не в этом.
Причем, если заменить тип хука на WH_MOUSE_LL, то все работает без проблем с перемещением в неклиентской области.
Здравствуйте, Kochuev, Вы писали:
K>Господа, помогите понять в целях повышения самообразованности... СОздаю хук типа WH_CALLWNDPROC и в него не приходят сообщения WM_MOUSEMOVE... Это особенность хука (про нее правда в MSDN ничего не написано)? ОС Windows 2000. Обойти проблему удалось использованием WH_MOUSE_LL — низкоуровневого мышиного хука. Но для меня так и осталось непонятным, почему хук WH_CALLWNDPROC не ловит сообщения мыши. Если заменить WH_CALLWNDPROC на хук WH_GETMESSAGE — все работает! Мне всегда казалось, что разница между этими хуками только в моменте перехвата сообщения, а не в составе отлавливаемых сообщений... В чем бы могло быть дело? Может какой-то другой хук не передает сообщение дальше???
Возможно здесь дело в том, что сообщение WM_MOUSEMOVE не есть обычное типа WM_MOUSEDOWN и не постится в оконную очередь приложения, а генерится налету, когда приложение вызывает GetMessage(), подобно WM_TIMER или как его там...
Auster wrote: > > Здравствуйте, Kochuev, Вы писали: > > K>Господа, помогите понять в целях повышения самообразованности... СОздаю хук типа WH_CALLWNDPROC и в него не приходят сообщения WM_MOUSEMOVE... Это особенность хука (про нее правда в MSDN ничего не написано)? ОС Windows 2000. Обойти проблему удалось использованием WH_MOUSE_LL — низкоуровневого мышиного хука. Но для меня так и осталось непонятным, почему хук WH_CALLWNDPROC не ловит сообщения мыши.
The CallWndRetProc hook procedure is an application-defined or
library-defined callback function used with the SetWindowsHookEx
function. The system calls this function after the SendMessage function
is called. The hook procedure can examine the message; it cannot modify
it.
The GetMsgProc function is an application-defined or library-defined
callback function used with the SetWindowsHookEx function. The system
calls this function whenever the GetMessage or PeekMessage function has
retrieved a message from an application message queue. Before returning
the retrieved message to the caller, the system passes the message to
the hook procedure.
Поэтому и работает, так как через GetMessage проходит.
>Мне всегда казалось, что разница между этими хуками только в моменте перехвата сообщения, а не в составе >отлавливаемых сообщений... В чем бы могло быть дело? Может какой-то другой хук не передает сообщение >дальше???
Вот в этом и дело. MSDN читать надо.
> > Возможно здесь дело в том, что сообщение WM_MOUSEMOVE не есть обычное типа WM_MOUSEDOWN
Обычное вполне.
>и не постится в оконную очередь приложения, а генерится налету, когда приложение вызывает GetMessage(), >подобно WM_TIMER или как его там...
Это как так налету ?
Кстати, и WM_TIMER через очередь проходит (точнее, там QS_TIMER флаг
взводится). См.GetQueueStatus
Здравствуйте, Pavel Dvorkin, Вы писали:
>>и не постится в оконную очередь приложения, а генерится налету, когда приложение вызывает GetMessage(), >подобно WM_TIMER или как его там...
PD>Это как так налету ?
в момет вызова приложением GetMessage()
PD>Кстати, и WM_TIMER через очередь проходит (точнее, там QS_TIMER флаг PD>взводится). См.GetQueueStatus
вот, вот, а для mouse move там есть флаг QS_MOUSEMOVE.
Сами же сообщения WM_MOUSEMOVE в оконной очереди реально не хранятся.
А иначе как? С какой скоростью они бы эту очередь заполняли, скажем, на пне 3.0 гигагерца, пока приложение ожидает, например, окончания сетевой операции, а юзер нервно дергает мышью?
Auster wrote: > вот, вот, а для mouse move там есть флаг QS_MOUSEMOVE.
Там много флагов есть. Например :
QS_KEY
A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the
queue.
QS_MOUSEBUTTON
A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).
QS_MOUSEMOVE
A WM_MOUSEMOVE message is in the queue.
> Сами же сообщения WM_MOUSEMOVE в оконной очереди реально не хранятся. > А иначе как? С какой скоростью они бы эту очередь заполняли, скажем, на пне 3.0 гигагерца, пока приложение ожидает, например, окончания сетевой операции, а юзер нервно дергает мышью?
Сообщения там все же хранятся, или объясни, где тогда хранятся
координаты курсора мыши, присылаемые с этим сообщением ? lParam то есть.
Для каждого сообщения свой.
А 3.0 ГГц здесь ни при чем. Вот когда ты начнешь мышь двигать с частотой
3 Ггц, тогда поговорим.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Сообщения там все же хранятся, или объясни, где тогда хранятся PD>координаты курсора мыши, присылаемые с этим сообщением ? lParam то есть. PD>Для каждого сообщения свой.
PD>А 3.0 ГГц здесь ни при чем. Вот когда ты начнешь мышь двигать с частотой PD>3 Ггц, тогда поговорим.
Мда.. Видимо майкрософту тоже было проще написать, что они попадают в очередь, чем объяснить откуда они берутся...
Несмотря на то, что мы уже далеко ушли от темы, позволю себе привести здесь небольшое "доказательство от обратного".
Пусть сообщения WM_MOUSEMOVE постятся в оконную очередь приложения при движении мышки с некоторой периодичностью (то ли per seconds, то ли per pixels), и приложение некоторое время не выбирает сообщения из очереди. Через какое-то время (мышь прошла по сложной траектории) приложение начинает вызывать GetMessage() и получает все эти сообщения, то есть ту самую траекторию. Так?
Хорошо. Попробуем это доказать.
Для этого понадобится обычный Paint и Process Explorer от sysinternals. Расположим их рядом. В Paint выберем Pencil и проведем сложную траекторию. Думаю, Вы не будете спорить, что Paint нарисовал ее по сообщениям WM_MOUSEMOVE из очереди?
Теперь сотрем все, приостановим процесс mspaint.exe в Process Explorer (popup menu -> Suspend) и повторим операцию рисования (т.е. mouse down, complex mouse moving and mouse up). Исходя из наших предположений, вся траектория мышки сейчас в очереди приложения. Теперь достаточно пустить процесс (popup menu -> Resume) и увидеть как Paint нарисует прямую линию между начальной и конечной точкой.
Вывод, надеюсь, сделаете сами?
Что бы убедится окончательно, что paint получит только один последний WM_MOUSEMOVE, причем с теми же координатами, что и следующий за ним WM_MOUSEUP, можно еще Spy поцепить на этот процесс. У немя под рукой сейчас нет к сожалению, как и MSDNa
Auster wrote: > Мда.. Видимо майкрософту тоже было проще написать, что они попадают в очередь, чем объяснить откуда они берутся... > > Несмотря на то, что мы уже далеко ушли от темы, позволю себе привести здесь небольшое "доказательство от обратного".
<skipped> > Вывод, надеюсь, сделаете сами?
Не могу утверждать определенно. Может, ты и прав. Кстати, если уж так (у
меня сейчас нет времени на проверку — слишком поздно, иду домой) , то
тогда сообщения WM_KEYDOWN, WM_LBUTTONDOWN и т.д. (насчет них, как я
понимаю, ты согласен, что в очереди хранятся) должны после приостановки
и продолжения процесса прибыть ВСЕ. Можешь попробовать ? Т.е. останови
процесс и пощелкай в его окне мышкой, а потом отпусти процесс. Процесс
можешь сам элементарно сотворить такой, чтобы любой WM_KEYDOWN,
WM_LBUTTONDOWN рисовал что-то.
Если нарисует — ты прав. Если нет — надо копать дальше.
Я проделал следующий эксперимент. Сделал приложение , где на пункт меню
выполняется длинный цикл. За время этого цикла я подвигал в окне мышкой,
при том, что на WM_MOUSEMOVE выводится пиксель. Результат — пикселей
нет.
После этого я сделал то же, но на WM_LBUTTONDOWN рисуется прямоугольник.
Пощелкал несколько раз во время задержки. После окончания задержки
прямоугольники появились.
Alex Reyst wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали: > > PD>Должен признать, что ты прав. > > Извините, что вмешиваюсь в разговор
Бога ради
> > В MSDN есть такая фраза: >
> When mouse messages are posted faster than a thread can process them, the system discards all but the most recent mouse message.
> > Т.е. не означает ли это, что каждое сообщение WM_MOUSEMOVE просто заменяет предыдущее в очереди, если оно еще не обработано?
Похоже, что это именно так. То есть получается, что сообщение все же в
очереди есть, но только одно. Кстати, похоже (хоть и не точно) на
WM_PAINT — оно там всегда одно, если есть.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Похоже, что это именно так. То есть получается, что сообщение все же в PD>очереди есть, но только одно. Кстати, похоже (хоть и не точно) на PD>WM_PAINT — оно там всегда одно, если есть.
Так. Проведенный тщательный эксперимент показал, что из очереди "сокращаются" последовательные WM_MOUSEMOVE, не разделенные другими событиями мыши.
Все логично.
Все, что здесь сказано, может и будет использоваться против меня...
Здравствуйте, Alex Reyst, Вы писали:
AR>Так. Проведенный тщательный эксперимент показал, что из очереди "сокращаются" последовательные WM_MOUSEMOVE, не разделенные другими событиями мыши.
Возможно и так.
Но я думаю, это было проще реализовать через флаги и хранение некоторых параметров отдельно (например региона для WM_PAINT), кроме того, то же WM_PAINT имеет более низкий приоритет, то есть "выбирается из очереди" последним.
Что касательно "разделения" DOWN и UP сообщением MOVE, я думаю это своеобразный bugfix — наверно некоторые не анализируют координаты в WM_LBUTTONUP, рассчитывая на WM_MOUSEMOVE, если было движение.