[英]Detect when mouse leaves my app
Hello I am creating an app in win32 that will display the x, y position(In screen coords) of the mouse whereever the mouse is (inside my app client/NC area & outside). 您好我正在win32中创建一个应用程序,它将显示鼠标所在鼠标的x,y位置(屏幕坐标)(在我的app客户端/ NC区域和外部)。
I am at the stage where I want to detect when the mouse leaves my application completely. 我正处于我想要检测鼠标何时完全离开我的应用程序的阶段。 I have written a simple win32 app that should detect & notify myself when the mouse leaves my app, BUT its not working, I never receive the messages WM_MOUSELEAVE & WM_NCMOUSELEAVE.
我写了一个简单的win32应用程序,当鼠标离开我的应用程序时应该检测并通知我自己,但是它不能正常工作,我从未收到WM_MOUSELEAVE和WM_NCMOUSELEAVE消息。
What do you think is wrong? 你觉得怎么了? Am I using the wrong win32 functions?
我使用了错误的win32功能吗?
// Track Mouse.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include <windows.h>
#include <vector>
#include <string>
#include <cstdlib>
static HINSTANCE gInstance;
// Globals //
enum MouseStatus { DEFAULT = 50001, LEFT_CLIENT, LEFT_NCLIENT };
static MouseStatus mouseState = DEFAULT;
static COLORREF bkCol = RGB(0,255,255);
// Functions List //
BOOL TrackMouse( HWND hwnd )
{
// Post:
TRACKMOUSEEVENT mouseEvt;
ZeroMemory( &mouseEvt, sizeof(TRACKMOUSEEVENT) );
mouseEvt.cbSize = sizeof(TRACKMOUSEEVENT);
mouseEvt.dwFlags = TME_LEAVE | TME_NONCLIENT;
//mouseEvt.dwHoverTime = HOVER_DEFAULT;
mouseEvt.hwndTrack = hwnd;
return TrackMouseEvent( &mouseEvt );
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
// Track mouse so I can be notified when it leaves my application (Client & NC areas)
BOOL trackSuccess = TrackMouse( hwnd ); // Returns successful, so I correctly track the mouse
if ( trackSuccess == 0 )
{
MessageBoxW( hwnd, L"Failed to track mouse", L"Error", MB_OK|MB_ICONEXCLAMATION );
}
else MessageBoxW( hwnd, L"Tracking mouse", L"Success", MB_OK|MB_ICONEXCLAMATION );
}
break;
case WM_MOUSELEAVE:
{
// I never receive this message
// Detect when the mouse leaves the client area
mouseState = LEFT_CLIENT;
bkCol = RGB(50,50,50);
InvalidateRect( hwnd, NULL, true );
}
break;
case WM_NCMOUSELEAVE :
{
// I never receive this message
// If the mouse has left the client area & then leaves the NC area then I know
// that the mouse has left my app
if ( mouseState == LEFT_CLIENT )
{
mouseState = LEFT_NCLIENT;
BOOL trackSuccess = TrackMouse( hwnd );
if ( trackSuccess == 0 )
{
bkCol = RGB(255,255,0);
MessageBoxW( hwnd, L"On WM_NCMOUSELEAVE: Failed to track mouse", L"Error", MB_OK|MB_ICONEXCLAMATION );
}
else MessageBoxW( hwnd, L"On WM_NCMOUSELEAVE: Tracking mouse", L"Success", MB_OK|MB_ICONEXCLAMATION );
InvalidateRect( hwnd, NULL, true );
}
}
break;
case WM_ACTIVATE:
case WM_MOUSEHOVER:
{
// The mouse is back in my app
mouseState = DEFAULT;
bkCol = RGB(0,255,255);
InvalidateRect( hwnd, NULL, true );
}
break;
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint( hwnd, &ps );
SetBkColor( hdc, bkCol );
Rectangle( hdc, 10, 10, 200, 200 );
EndPaint( hwnd, &ps );
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = gInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(DKGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"Custom Class";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// if registration of main class fails
if(!RegisterClassEx(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"Custom Class",
L"App Name",
WS_CAPTION|WS_MINIMIZEBOX|WS_VISIBLE|WS_OVERLAPPED|WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 500,
NULL, NULL, gInstance, NULL);
if(hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
The key component your missing is SetCapture(hwnd);
你缺少的关键部分是
SetCapture(hwnd);
which directs all mouse messages to that hwnd until you call ReleaseCapture();
它会将所有鼠标消息定向到该hwnd,直到您调用
ReleaseCapture();
HANDLE_DLGMSG(hwnd, WM_RBUTTONDOWN, SKDemo_OnRButtonDown);
HANDLE_DLGMSG(hwnd, WM_MOUSEMOVE, SKDemo_OnMouseMove);
HANDLE_DLGMSG(hwnd, WM_RBUTTONUP, SKDemo_OnRButtonUp);
void SKDemo_OnRButtonDown (HWND hwnd, BOOL fDbClk, int x, int y, UINT keyFlags)
{
// Force all mouse messages to come to this window.
SetCapture(hwnd);
// Change the mouse cursor to eyes. This provides a visual indication
// to the user that Voyeur is "peering."
SetCursor(LoadCursor(GetWindowInstance(hwnd),
MAKEINTRESOURCE(IDC_POINTER)));
}
void SKDemo_OnMouseMove (HWND hwnd, short x, short y, UINT keyFlags)
{
if( GetCapture() == NULL ) {
return;
}
// do something with the message here
}
void SKDemo_OnRButtonUp (HWND hwnd, int x, int y, UINT keyFlags)
{
ReleaseCapture();
}
I think you need the mouse to be over your window before you all TrackMouseEvent. 我想你需要鼠标才能在你所有的TrackMouseEvent之前。 Try calling whilst you handle a mouse move message.
在处理鼠标移动消息时尝试呼叫。
As written in Win32 documentation, the request expires each time the mouse leaves the window. 如Win32文档中所述,每次鼠标离开窗口时请求都会过期。 So you need to call TrackMouseEvent also in your WM_MOUSELEAVE handler.
因此,您还需要在WM_MOUSELEAVE处理程序中调用TrackMouseEvent。 Note also that if the mouse isn't in your window at the time TrackMouseEvent is called, WM_MOUSELEAVE is generated immediately.
另请注意,如果在调用TrackMouseEvent时鼠标不在窗口中,则会立即生成WM_MOUSELEAVE。
The win32 API is more or less ridiculous. win32 API或多或少是荒谬的。 It doesn't have a mouse enter/leave.
它没有鼠标进入/离开。 A google search for "MFC mouse enter leave" turned up this:
谷歌搜索“MFC鼠标进入休假”出现了这个:
http://www.codeproject.com/KB/cpp/mouseenterleave.aspx http://www.codeproject.com/KB/cpp/mouseenterleave.aspx
Note that MFC is just a thin wrapper around win32 proper. 请注意,MFC只是win32正确的一个薄包装。 You can basically take any member function of a WND and call a C function with the exact same name and HWND as first parameter...the rest being all exactly the same.
您基本上可以使用WND的任何成员函数,并使用与第一个参数完全相同的名称和HWND调用C函数...其余部分完全相同。
Have fun. 玩得开心。 This kind of crap is why I hate all things win32.
这种废话是我讨厌win32所有东西的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.