WM_MOUSELEAVE не генерируется при удерживании левой кнопки мыши - PullRequest
4 голосов
/ 17 февраля 2010

В моем приложении Win32 я не получаю сообщения WM_MOUSELEAVE, когда я удерживаю левую кнопку мыши и быстро перемещаю указатель мыши из окна. Но если я, удерживая левую кнопку мыши, начну с внутренней части окна и медленно продвинусь к краю окна, это сгенерирует WM_MOUSELEAVE.

Если я не удерживаю левую кнопку мыши, я получаю сообщения WM_MOUSELEAVE каждый раз, независимо от того, как быстро указатель мыши перемещается за пределы окна.

Какая разница? Что я могу сделать, чтобы правильно обрабатывать оба случая?

РЕДАКТИРОВАТЬ: Если я щелкну левой кнопкой мыши и удерживаю, выхожу из окна и затем отпускаю левую кнопку мыши, я получаю сообщение WM_MOUSELEAVE. Но уже слишком поздно.

Ответы [ 3 ]

5 голосов
/ 31 марта 2010

В Windows 7 я пытался сделать кнопку, нарисованную владельцем. Я создал подкласс для кнопки, чтобы получить более точные события ввода мыши / отпускания мыши, по сути. При этом я использовал TrackMouseEvent, когда получил WM_MOUSEMOVE, потому что он публикуется только тогда, когда мышь находится над кнопкой. Если он еще не установлен, я бы установил логическое значение, чтобы указать, что указатель мыши находится над кнопкой, а также вызвал TrackMouseEvent, чтобы при каждом оставлении мыши я мог сбросить логическое значение. Однако, как и вы, я не получал WM_MOUSELEAVE, когда я нажимал и удерживал левую кнопку мыши на кнопке, нарисованной владельцем, а затем вытаскивал мышь. Отпустив мышь за пределы кнопки, я внезапно получаю сообщение WM_MOUSELEAVE - слишком поздно.

Я определил, что причиной этого поведения было то, что обработка кнопки по умолчанию для WM_LBUTTONDOWN вызывает SetCapture и освобождает его позже. Использование SetCapture - это то, что нарушает наш прием события WM_MOUSELEAVE. Однако, как побочный эффект от вызова SetCapture, мы получим события WM_MOUSEMOVE, даже если элемент управления не находится под мышью. Таким образом, мой обходной путь дублирует логику в WM_MOUSELEAVE в обработчике WM_MOUSEMOVE, чтобы сбросить мой логический параметр, который указывает, что мышь находится над кнопкой, если я получаю событие mousemove, которое находится вне области моей кнопки. Если SetCapture фактически не используется внутри WM_LBUTTONDOWN для кнопки по умолчанию, тогда мы уже получим наше сообщение WM_MOUSELEAVE, и код все равно будет работать ... так что этот обходной путь работает в обоих случаях.

Ваша проблема звучит так, как будто она, вероятно, идентична моей, так что, надеюсь, это поможет вам.

3 голосов
/ 20 февраля 2010

WM_MOUSELEAVE позволяет обнаружить мышь, покидающую ваше окно, когда у вас нет захвата. Когда у вас есть захват, вы несете ответственность за его обнаружение (если вы заботитесь).

так что нет никакого смысла для SetCapture И TrackMouseEvent одновременно, вы бы использовали один или другой.

Теперь, если вам было бы удобнее видеть сообщения WM_MOUSELEAVE во время захвата, сделать это самостоятельно в своем насосе сообщений относительно просто.

Вы просто добавили бы код, который выглядит примерно так, между GetMessage() и DispatchMessage() вызовами в вашем обработчике сообщений.

  GetMessage(pmsg, ...);

  .....

  if ((IS_WITHIN(pmsg->message, WM_MOUSEFIRST, WM_MOUSELAST) ||
       IS_WITHIN(pmsg->message, WM_NCMOUSEMOVE, WM_NCMBUTTONDBLCLK)) &&
       MyMouseLeaveDetection(pmsg, g_hwndNotifyMouseLeave))
     {
     MSG msg = *pmsg;
     msg.message = WM_MOUSELEAVE;
     msg.hwnd    = g_hwndNotifyMouseLeave; // window that want's 
     msg.lParam  = 0xFFFFFFFF;
     g_hwndNotifyMouseLeave = NULL;

     DispatchMessage (&msg);
     }

 .....
 TranslateMessage(pmsg);
 DispatchMessage(pmsg);
0 голосов
/ 17 февраля 2010

Поскольку ожидание WM_MOUSELEAVE ненадежно, лучшее решение, которое я нашел, - это прямой взгляд на положение мыши во время WM_MOUSEMOVE. Я сравниваю положение мыши с клиентской областью, и, если она находится снаружи, я обрабатываю ее, когда мышь уходит.

Я также вызываю SetCapture, когда позиция мыши находится в пределах клиентской области, и ReleaseCapture, когда она уходит.

...