Как узнать, что мышь вышла за пределы окна?
От: Аноним  
Дата: 13.01.02 03:01
Оценка: 180 (8) +2
Статья:
Как узнать, что мышь вышла за пределы окна?
Автор(ы): Александр Шаргин, Антон Баула
Дата: 11.07.2001


Авторы:
Alexander Shargin
Gambler

Аннотация:
При создании пользовательского интерфейса иногда требуется определить момент, когда курсор мыши выходит за пределы окна. Для решения этой задачи существуют различные методы. Можно воспользоваться готовой функцией TrackMouseEvent, которая появилась в Win32 API, начиная с Windows 98/NT4, или же эквивалентной ей функцией _TrackMouseEvent из библиотеки comctl32.dll. А можно добиться требуемого поведения "вручную", использую стандартные средства.
WM_MOUSEENTER
От: odisseyLM  
Дата: 14.01.02 03:01
Оценка:
Для проверки входа курсора можно использовать обработка WM_SETCURSOR.
Как узнать, что мышь вышла за пределы окна?
От: Dima2  
Дата: 03.02.02 21:52
Оценка:
Можно еще использовать SetCapture
Re: Как узнать, что мышь вышла за пределы окна?
От: Alexander Shargin Россия RSDN.ru
Дата: 04.02.02 06:57
Оценка:
Только если удерживается левая кнопка мыши. В противном случае, в Win32 (в отличие от Win16) мышь не отслеживается.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Рецептик для WM_MOUSELEAVE и WM_MOUSEHOVER.
От: nixy Россия  
Дата: 07.02.02 20:05
Оценка:
Рецептик для WM_MOUSELEAVE и WM_MOUSEHOVER.
-------------------------------------------

#define ON_WM_MOUSELEAVE() \
{ WM_MOUSELEAVE, 0, 0, 0, AfxSig_bv, (AFX_PMSG)(AFX_PMSGW) \
(int (AFX_MSG_CALL CWnd::*)(void))&OnMouseLeave },
#define ON_WM_MOUSEHOVER() \
{ WM_MOUSEHOVER, 0, 0, 0, AfxSig_vwp, \
(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, CPoint))&OnMouseHover },

...............

void CMyWnd::OnMouseMove(UINT nFlags, CPoint point)
{
// заряжаем трекинг WM_MOUSELEAVE
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE;
_TrackMouseEvent(&tme);

// заряжаем вдогонку WM_MOUSEHOVER
// если мышку двинули до того, как всплыло сообщение
// произойдет перезарядка (обнуление таймера)
tme.dwFlags = TME_HOVER;

// время срабатывания по умолчанию, вообще задается в миллисекундах
tme.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&tme);

if(!m_MouseInside) {
m_MouseInside = true;
Invalidate();
UpdateWindow();
}

CWnd::OnMouseMove(nFlags, point);
}

int CMyWnd::OnMouseLeave()
{
// чего-то делаем
return 0;
}

int CMyWnd::OnMouseHover(UINT nFlags, CPoint point) {
// еще чего-то делаем
return 0;
}
...............

Счастья Вам!
Конечно лажовые способы
От: Ерусов Дмитрий  
Дата: 03.06.02 23:32
Оценка:
Конечно лажовые способы использование таймера и прочей чепухи
намного лучше написать стандартную функцию
типа InitExMouseMessages() в длл
где
1. создается хук на WndProc на все потоки в системе
2. в этом хуке помня обрабатывается только сообщение MouseMove
3. соответсвенно смотря входящий хэндл окна и сравнивая его с переменной типа hOldWnd отсылать PostMessage(hOldWnd, WM_MOUSELEAVE, 0, 0) и hOldWnd = hWnd вот собственно и все
весь код пишется за минут 10, главное не забыть что hOldWnd это переменная которая расшаривается между процессами для этого соответсвенно нужно написать небольшой кодик
в функции инициализации длл
вот и все
зато спосо будет работать на всех окнах в системе
Re: Конечно лажовые способы
От: Alexander Shargin Россия RSDN.ru
Дата: 03.06.02 23:42
Оценка:
Чем этот способ лучше _TrackMouseEvent (если не считать совместимость с Windows95 в период до выхода IE3)?
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re: Конечно лажовые способы
От: Ерусов Дмитрий  
Дата: 03.06.02 23:50
Оценка:
Ничем:) но я говорил про другое
про способ когда мы делаем все сами
да и ктому же этот спсоб не требует вызовов TrackMouseEvent запалонения структур
и прочего что отнимает процессорное и программисткое время
мой способ действует на верняка и на все окна системы
в общем то я думаю что это лучше
Re: Конечно лажовые способы
От: nixy Россия  
Дата: 04.06.02 00:05
Оценка:
Сколько окон одновременно ты можешь контролировать на WM_MOUSE_LEAVE одновременно таким способом?
Re: Конечно лажовые способы
От: Alexander Shargin Россия RSDN.ru
Дата: 04.06.02 00:12
Оценка:
Но есть и недостатки.
1. Необходимость отдельной DLL
2. Нужно писать больше кода. Как ни крутись, там его будет больше. Да и ошибаются программисты в глобальных хуках очень и очень часто.
3. Нестандартно. Функция _TrackMouseEvent входит в Windows, используется IE и другими программами и с гарантией будет работать всегда и везде. А в своей функции можно случайно допустить ошибку и расхлёбывать потом. В конце концов, другая программа может засадить свой собственный хук и "забыть" вызвать по цепочке твой. Доказывай потом юзеру, что нефиг ставить такие программы. ;)
4. Ну и по поводу производительности. Структуру заполнять не надо и вызывать функцию не надо — это плюс. Но кто сказал, что глобальный хук не вносит задержки (теперь уже глобальной)? Ведь через него пропускаются все мышиные сообщения в системе... DLL мапится в пространства каждого процесса, который работает с мышью...

В общем, всё не так однозначно. Но твой способ также имеет право на существование. Так что если оформишь его в виде законченного кода с пояснениями, можно будет расширить эту статью. Лично я только "за".
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re: Конечно лажовые способы
От: Ерусов Дмитрий  
Дата: 04.06.02 00:19
Оценка:
Все которые получают сообщения от mouse,

InitExMouseMessages()
{
dll = LoadLibrary("exmousemsg.dll");
func = getprocaddress(dll, "WndProc");
setwindowhookex(WH_CALLWNDPROC, func, dll, 0);
}
Re: Конечно лажовые способы
От: Ерусов Дмитрий  
Дата: 04.06.02 00:40
Оценка:
Про статью я тоже "за"
но про пункт четыре я готов поспорить:))
конечно ты прав, как и я
но что именно будет работать быстрее можно
будет посмотреть
Re[2]: Конечно лажовые способы
От: Plazmid Россия http://www.plazmid.web.ur.ru
Дата: 16.06.04 04:05
Оценка:
Здравствуйте,
вот интересный момент наблюдаю, в процедуре обработки сообщений ставлю.
case WM_MOUSELEAVE: MessageBox(NULL,"Hi!", NULL, MB_OK);

при этом нигде в программе не обращаюсь к функции _TrackMouseEvent, но
сообщения приходят, система — ХР про. Что-то не правильно получается?
Re: Как узнать, что мышь вышла за пределы окна?
От: SaZ  
Дата: 11.02.07 02:48
Оценка:
Здравствуйте, Александр Шаргин, Антон Баула, Вы писали:

АША>Статья:

АША>Как узнать, что мышь вышла за пределы окна?
Автор(ы): Александр Шаргин, Антон Баула
Дата: 11.07.2001


АША>Авторы:

АША> Alexander Shargin
АША> Gambler

АША>Аннотация:

АША>При создании пользовательского интерфейса иногда требуется определить момент, когда курсор мыши выходит за пределы окна. Для решения этой задачи существуют различные методы. Можно воспользоваться готовой функцией TrackMouseEvent, которая появилась в Win32 API, начиная с Windows 98/NT4, или же эквивалентной ей функцией _TrackMouseEvent из библиотеки comctl32.dll. А можно добиться требуемого поведения "вручную", использую стандартные средства.

Заметил небольшую неточность написанного Вами обработчика WM_MOUSEMOVE. Если необходимо ловить WM_MOUSEHOVER, то оно никогда не придёт, потому что каждый повторный вызов _TrackMouseEvent при обработке MOUSEMOVE будет "сбрасывать" время задержки курсора на 0. Для решения этой проблеммы можно ввести логическую переменную, которую устанавливать в TRUE при первом вызове WM_MOUSEMOVE (после чего вызвать _TrackMouseEvent), а при обработке WM_MOUSELEAVE устанавливать её в FALSE.
Re: Конечно лажовые способы
От: Аноним  
Дата: 11.02.07 04:02
Оценка:
ЕД>зато спосо будет работать на всех окнах в системе
кроме консольны
Re[3]: Конечно лажовые способы
От: SaZ  
Дата: 13.02.07 22:48
Оценка:
Здравствуйте, Plazmid, Вы писали:

P>Здравствуйте,

P>вот интересный момент наблюдаю, в процедуре обработки сообщений ставлю.
P>
case WM_MOUSELEAVE: MessageBox(NULL,"Hi!", NULL, MB_OK);

P>при этом нигде в программе не обращаюсь к функции _TrackMouseEvent, но
P>сообщения приходят, система — ХР про. Что-то не правильно получается?

А Вы случайно нигде break или return не забыли перед обработкой WM_MOUSELEAVE?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.