Answers
对于一般窗口来说,使用
@唐仕强
的方法就可以搞定,但因为Windows shell不支持MOUSELEAVE消息,所以需要自己来实现,一种方法就像
@唐仕强
所描述的,安装SHellNotify(托盘)窗口的消息钩子来实现。
另外一种是通过线程轮询来实现,思路很简单,如下:
在WM_MOUSEMOVE中保存鼠标的位置,然后启动线程比较当前的鼠标位置与你记录的鼠标位置进行比较,如果不同,就发送鼠标离开消息。
traypos.h
#ifndef TRAYPOS_H
#define TRAYPOS_H
class CTrayPos
{
private:
POINT m_ptMouse;
HANDLE m_hThread;
HANDLE m_hExitEvent;
BOOL m_bTrackMouse;
CRITICAL_SECTION m_cs;
public:
CTrayPos();
virtual ~CTrayPos();
static UINT CALLBACK TrackMousePt(PVOID pvClass);
VOID OnMouseMove();
BOOL IsMouseHover();
protected:
virtual VOID OnMouseHover() = 0;
virtual VOID OnMouseLeave() = 0;
};
class CMsgTrayPos : public CTrayPos
{
private:
HWND m_hNotifyWnd;
UINT m_uID;
UINT m_uCallbackMsg;
public:
CMsgTrayPos(HWND hwnd=NULL, UINT uID=0, UINT uCallbackMsg=0);
~CMsgTrayPos();
VOID SetNotifyIconInfo(HWND hwnd, UINT uID, UINT uCallbackMsg);
protected:
VOID OnMouseHover();
VOID OnMouseLeave();
};
#endif
traypos.cpp
#include "stdafx.h"
#include <commctrl.h>
#include <process.h>
#include "traypos.h"
#include "resource.h"
CTrayPos::CTrayPos()
{
UINT uThreadId;
m_bTrackMouse = FALSE;
m_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThread = (HANDLE) _beginthreadex(NULL, 0, CTrayPos::TrackMousePt, this, 0, &uThreadId;);
InitializeCriticalSection(&m;_cs);
}
CTrayPos::~CTrayPos()
{
if(m_hThread != NULL)
{
SetEvent(m_hExitEvent);
if(WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT)
{
TerminateThread(m_hThread, 0);
}
CloseHandle(m_hThread);
m_hThread = NULL;
}
if(m_hExitEvent != NULL)
{
CloseHandle(m_hExitEvent);
m_hExitEvent = NULL;
}
DeleteCriticalSection(&m;_cs);
}
UINT CALLBACK CTrayPos::TrackMousePt(PVOID pvClass)
{
POINT ptMouse;
CTrayPos *pTrayPos = (CTrayPos *) pvClass;
while(WaitForSingleObject(pTrayPos->m_hExitEvent, 2000) == WAIT_TIMEOUT)
{
if(pTrayPos->m_bTrackMouse == TRUE)
{
GetCursorPos(&ptMouse;);
if(ptMouse.x != pTrayPos->m_ptMouse.x || ptMouse.y != pTrayPos->m_ptMouse.y)
{
pTrayPos->m_bTrackMouse = FALSE;
pTrayPos->OnMouseLeave();
}
}
}
return 0;
}
VOID CTrayPos::OnMouseMove()
{
EnterCriticalSection(&m;_cs);
GetCursorPos(&m;_ptMouse);
if(m_bTrackMouse == FALSE)
{
OnMouseHover();
m_bTrackMouse = TRUE;
}
LeaveCriticalSection(&m;_cs);
}
BOOL CTrayPos::IsMouseHover()
{
return m_bTrackMouse;
}
//////////////////////////////////////////////////////////////////////////
CMsgTrayPos::CMsgTrayPos(HWND hwnd, UINT uID, UINT uCallbackMsg)
: CTrayPos()
{
SetNotifyIconInfo(hwnd, uID, uCallbackMsg);
}
CMsgTrayPos::~CMsgTrayPos()
{
}
VOID CMsgTrayPos::SetNotifyIconInfo(HWND hwnd, UINT uID, UINT uCallbackMsg)
{
m_hNotifyWnd = hwnd;
m_uID = uID;
m_uCallbackMsg = uCallbackMsg;
}
VOID CMsgTrayPos::OnMouseHover()
{
if(m_hNotifyWnd != NULL && IsWindow(m_hNotifyWnd))
PostMessage(m_hNotifyWnd, m_uCallbackMsg, m_uID, WM_MOUSEHOVER);
}
VOID CMsgTrayPos::OnMouseLeave()
{
if(m_hNotifyWnd != NULL && IsWindow(m_hNotifyWnd))
PostMessage(m_hNotifyWnd, m_uCallbackMsg, m_uID, WM_MOUSELEAVE);
}
我上头有神
answered 12 years, 3 months ago