Элвис покинул здание (wm_MouseLeave)
Модератор: Модераторы
Элвис покинул здание (wm_MouseLeave)
В Лазаревской прилоге не получается гарантировано (т.е. включая выверты с Alt+Tab etc) отловить уход мыши из контрола.
Под Delphi5 делал обработчик wm_MouseLeave - и вуаля, всегда знал, что мышь окно покинула. А под Лазарем не удаётся получать это сообщение никакими (известными мне) способами: ни впрямую обработчиком (message wm_MouseLeave), ни через перекрытие оконной функции. С wm_NCHitTest второй способ работает, а wm_MouseLeave - не приходит.
Any ideas?
Под Delphi5 делал обработчик wm_MouseLeave - и вуаля, всегда знал, что мышь окно покинула. А под Лазарем не удаётся получать это сообщение никакими (известными мне) способами: ни впрямую обработчиком (message wm_MouseLeave), ни через перекрытие оконной функции. С wm_NCHitTest второй способ работает, а wm_MouseLeave - не приходит.
Any ideas?
какая ОС? и какой Lazarus, потому что вот у меня lazarus 0.9.30 и Windows XP SP3, делаю типа так:
И все работает! Может у вас Контрол какой нибудь редкий?...
Код: Выделить всё
procedure TForm1.Panel1MouseLeave(Sender: TObject);
begin
Panel1.Caption:='Мышь ушла';
end;
procedure TForm1.Panel1MouseEnter(Sender: TObject);
begin
Panel1.Caption:='Мышь пришла';
end;
И все работает! Может у вас Контрол какой нибудь редкий?...
WinXPSP3rus, снэпшот 0.9.31, FPC 2.5.1. Контрол любой: панель, форма...
Maxizar, проведите plz такой эксперимент:
1) запустите "Notepad" или любой другое приложение;
2) разместите его так, чтобы его окно частично закрывало тестовую панель;
3) переключитесь на тестовое приложение ("Блокнот" уходит на задний план);
4) передвиньте мышь в ту часть панели, которая пересекается с notepad'ным окном;
5) по <Alt>+<Tab> переклчитесь на "Блокнот".
Неужели событие Panel1MouseLeave дёрнулось? 8-O
Добавлено спустя 13 минут 44 секунды:
Ха! События MouseEnter/MouseLeave - ерунда полная, даже вывертов с <Alt>+<Tab> не надо, достаточно выводить курсор через чужое окно. На скрине стрелкой движение мыши; по caption'у, она всё ещё над панелью.
Maxizar, проведите plz такой эксперимент:
1) запустите "Notepad" или любой другое приложение;
2) разместите его так, чтобы его окно частично закрывало тестовую панель;
3) переключитесь на тестовое приложение ("Блокнот" уходит на задний план);
4) передвиньте мышь в ту часть панели, которая пересекается с notepad'ным окном;
5) по <Alt>+<Tab> переклчитесь на "Блокнот".
Неужели событие Panel1MouseLeave дёрнулось? 8-O
Добавлено спустя 13 минут 44 секунды:
Ха! События MouseEnter/MouseLeave - ерунда полная, даже вывертов с <Alt>+<Tab> не надо, достаточно выводить курсор через чужое окно. На скрине стрелкой движение мыши; по caption'у, она всё ещё над панелью.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Ну вот скажем как можно победить <Alt>+<Tab> :
Поведение простого ухода мышки при не активном окне на другое... тут нужно подумать, по идее наверное сама ОС забивает, ведь мы уже над другим приложением, наверное так!... хотя утверждать я этого не буду.
Решение с Табом я привел, если необходимо вообще решить проблему и с уходом мыши на другое приложение при не активности нашего, и если ОС реально забивает на этот случай, то наверное решением будет Ловить сообщение ОС о передвижении мыши, и тупо пересчитывать координаты в координаты приложения + координаты нужного нам контрола и уже посылать насильно сообщения мол пришла\ушла как я сделал при потере фокуса при Альт + Таб... Больше умных мыслей нету
Код: Выделить всё
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Messages,LMessages;
type
{ TForm1 }
TForm1 = class(TForm)
Panel1: TPanel;
procedure Panel1MouseEnter(Sender: TObject);
procedure Panel1MouseLeave(Sender: TObject);
private
procedure Focuskill(var Message : Tmessage); message LM_KILLFOCUS;
procedure FocusSet(var Message : Tmessage); message LM_SETFOCUS;
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Panel1MouseEnter(Sender: TObject);
begin
caption:='Мышь пришла'
end;
procedure TForm1.Panel1MouseLeave(Sender: TObject);
begin
caption:='Мышь ушла'
end;
procedure TForm1.Focuskill(var Message: Tmessage);
begin
inherited;
//Насильно посылаем сообщение панели что мышь ушла, при потери фокуса формы.
Panel1.Perform(CM_MOUSELEAVE, 0, 0);
end;
procedure TForm1.FocusSet(var Message: Tmessage);
begin
inherited;
// но нужно добавить находится ли указатель над панаелью а то чушь получится
Panel1.Perform(CM_MOUSEENTER, 0, 0);
end;
end.
Поведение простого ухода мышки при не активном окне на другое... тут нужно подумать, по идее наверное сама ОС забивает, ведь мы уже над другим приложением, наверное так!... хотя утверждать я этого не буду.
Решение с Табом я привел, если необходимо вообще решить проблему и с уходом мыши на другое приложение при не активности нашего, и если ОС реально забивает на этот случай, то наверное решением будет Ловить сообщение ОС о передвижении мыши, и тупо пересчитывать координаты в координаты приложения + координаты нужного нам контрола и уже посылать насильно сообщения мол пришла\ушла как я сделал при потере фокуса при Альт + Таб... Больше умных мыслей нету
2Nik: События/методы_дистпетчеризации в Delphi работают, насколько я помню, не лучше - т.е. не всегда. Но в D5 я писАл так:и получал желаемое. В Лазарусе номер не проходит, увы: wm_MouseLeave кто-то сжирает по дороге.
Насколько я знаю, wm_NCHitTest такой же "вкусный" и сжираемый, но с ним проходит номер с перекрытием оконной функции. А вот искомый wm_MouseLeave в эту функцию всё равно не приходит :-(
Maxizar, спасибо, попробую с lm_KillFocus побарахтаться.
Код: Выделить всё
Procedure WMMouseLeave(var msg:tMessage); message wm_MouseLeave;Насколько я знаю, wm_NCHitTest такой же "вкусный" и сжираемый, но с ним проходит номер с перекрытием оконной функции. А вот искомый wm_MouseLeave в эту функцию всё равно не приходит :-(
Maxizar, спасибо, попробую с lm_KillFocus побарахтаться.
Ха! События MouseEnter/MouseLeave - ерунда полная, даже вывертов с <Alt>+<Tab> не надо, достаточно выводить курсор через чужое окно. На скрине стрелкой движение мыши; по caption'у, она всё ещё над панелью.
Я Вашу логику не пойму. У Вас на скриншоте активным окном является калькулятор. Исходя их чего, Вы считаете что водя мышкой над Form1 в вашем прилажении какие-то события пролетать должны??????
По <Alt>+<Tab> вы перебросили фокус в другое приложение. Все! Ваша прилада отработала, операционка тоже отработала. Фокус теперь в другом окне. Оно теперь ловит и обрабатывает события и от мышки и от клавиатуры... Что Вы хотите-то? Чтоб Form1 продолжал состояние мыши отслеживать? Таки не должно такого быть.
2vada:
Вы б может сначала попробовали? Примерчик за 10с делается. А потОм ужЕ о фокусах рассказывали.
Попадание в обработчик OnMouseLeave не зависит от того, какое приложение активно. Если в примере выше при активном калькуляторе выводить курсор не вниз, а влево, caption панели сменится на 'Мышь ушла'. Логичность такого поведения несколько спорна, согласен. С другой стороны, ОС отсылает мышиные сообщения окну, над которым фактически находится мышь, а не только активному окну активного приложения.
Ну, и главное.
Добавлено спустя 21 минуту 52 секунды:
И ещё об активных окнах и событиях. Если мышь выводить резким рывком, в OnMouseLeave не попадаем вообще, даже при единственном запущенном приложении - нашем - с единственным окном. Лучше всего видно при Panel1.align:=alClient - иначе (если вокруг панели есть широкий бордюр из формы) дёргать придётся очень быстро :-)
Вы б может сначала попробовали? Примерчик за 10с делается. А потОм ужЕ о фокусах рассказывали.
Попадание в обработчик OnMouseLeave не зависит от того, какое приложение активно. Если в примере выше при активном калькуляторе выводить курсор не вниз, а влево, caption панели сменится на 'Мышь ушла'. Логичность такого поведения несколько спорна, согласен. С другой стороны, ОС отсылает мышиные сообщения окну, над которым фактически находится мышь, а не только активному окну активного приложения.
Ну, и главное.
Именно! И об этой потере моё окно должно быть уведомлено. А такого не происходит: мышь ушла, а сообщение об этом сожрали.vada писал(а):Исходя их чего, Вы считаете что водя мышкой над Form1 в вашем прилажении какие-то события пролетать должны??????
По <Alt>+<Tab> вы перебросили фокус в другое приложение.
Ничего из ряда вон выходящего в этом не вижу. Для этого глабальные хуки существуют. Но в данном случае хочу я совсем другого: чтобы окно получило последнее сообщение в цепочке получение_фокуса - перемещения-клики-etc - потеря_фокуса. Логично, не находите?vada писал(а):Что Вы хотите-то? Чтоб Form1 продолжал состояние мыши отслеживать?
Добавлено спустя 21 минуту 52 секунды:
И ещё об активных окнах и событиях. Если мышь выводить резким рывком, в OnMouseLeave не попадаем вообще, даже при единственном запущенном приложении - нашем - с единственным окном. Лучше всего видно при Panel1.align:=alClient - иначе (если вокруг панели есть широкий бордюр из формы) дёргать придётся очень быстро :-)
Всё оказалось просто до безобразия :-)
Лазарь не глотает wm_MouseLeave бесследно - вместо него он отправляет окну lm_MouseLeave.
Всем спасибо, проблема решена.
Лазарь не глотает wm_MouseLeave бесследно - вместо него он отправляет окну lm_MouseLeave.
Всем спасибо, проблема решена.
