默认情况下,窗口是不响应 WM_MOUSELEAVE 和 WM_MOUSEHOVER 消息的,所以要使用 _TrackMouseEvent 函数来激活这两个消息。调用这个函数后,当鼠标在指定窗口上停留超过一定时间或离开窗口后,该函数会 Post 这两个消息到指定窗口。
使用方法:
1. 在对话框类中定义一个变量来标识是否追踪当前鼠标状态,之所以要这样定义是要避免鼠标已经在窗体之上时,一移动鼠标就不断重复产生 WM_MOUSEHOVER 。
BOOL _bMouseTrack = TRUE ;
2. 在 OnMouseMove 中调用 _TrackMouseEvent 函数
if (_bMouseTrack) // 若允许 追踪,则。
{
TRACKMOUSEEVENT csTME;
csTME.cbSize = sizeof (csTME);
csTME.dwFlags = TME_LEAVE | TME_HOVER;
csTME.hwndTrack = m_hWnd ;// 指定要 追踪 的窗口
csTME.dwHoverTime = 10; // 鼠标在按钮上停留超过 10ms ,才认为状态为 HOVER
::_TrackMouseEvent (&csTME); // 开启 Windows 的 WM_MOUSELEAVE , WM_MOUSEHOVER 事件支持
_bMouseTrack = FALSE ; // 若已经 追踪 ,则停止 追踪
}
(#add 摘自MSDN:The _TrackMouseEvent function posts messages when the mouse pointer leaves a window or hovers over a window for a specified amount of time. This function calls TrackMouseEvent if it exists, otherwise it emulates it.)
3. 在 OnMouseLeave 中再次允许追踪鼠标状态
_bMouseTrack = TRUE ;
4. 备注:这两个消息的映射要自己写
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
注意: 也可以用下面代码在PreTranslateMessage函数中接收,不需要自己写WM_MOUSELEASE和WM_MOUSEHOVER消息的响应函数(当然你要自己写也行):
if(pMsg-> message == WM_MOUSELEAVE)
AfxMessageBox( "mouse leave ");
else if(pMsg->message == WM_MOUSEHOVER)
AfxMessageBos("mouse leave");
return CDialog::PreTranslateMessage(pMsg);
附一个例子:
.h文件加入:
afx_msg LRESULT OnMouseLeave(WPARAM , LPARAM );
afx_msg LRESULT OnMouseHover(WPARAM , LPARAM );
.cpp文件加入:
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
LRESULT CIconButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
InvalidateRect(NULL);
return 0;
}
LRESULT CIconButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
//获取鼠标坐标
POINT point;
::GetCursorPos(&point);
ScreenToClient(&point) ;
//亦用如下方法,推荐.OnMouseMove 也可用.
CPoint pt;
pt.x = LOWORD(lParam); // horizontal position of cursor
pt.y = HIWORD(lParam); // vertical position of cursor
//还有如下,和上边其实是一样
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
CClientDC dc(this);
CRect rt;
GetClientRect(&rt);
dc.Draw3dRect(0, 0,
m_rect.right - m_rect.left, m_rect.bottom - m_rect.top,
RGB(0, 0, 0), RGB(10, 10, 10));
return 0;
}
void CIconButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CButton::OnMouseMove(nFlags, point);
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
tme.hwndTrack = m_hWnd;
_TrackMouseEvent(&tme);
}
OnMouseMove没有声明,在CNy4View的头文件中声明一下,形式afx_msg void OnMouseMove(...);
因为WM_MOUSEMOVE是windows的标准消息,所以在BEIGN_MESSAGE_MAP和END_MESSAGE_MAP()之前添加
ON_WM_MOUSEMOVE(),最后添加OnMouseMove()函数的实现部分,其中不要忘记调用基类的OnMouseMove。
以上是手动添加的,最方便的是使用classWizzard给你生成。vc6.0和vsxx差不多。
实现按下control键方法
1.可以
void CSDITabView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
UINT nShort = GetAsyncKeyState(VK_CONTROL);
if(nShort)
{
//MessageBox(_T("VK_CONTROL按下"));
}
CView::OnMouseMove(nFlags, point);
}
2.可以
BOOL CSDITabView::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
switch(pMsg->message)
{
case WM_KEYDOWN:
if(pMsg->wParam == VK_CONTROL)
{
//bCtrlKeyDown = TRUE;
//设置control键按下的标志,在OnMouseMove中判断是否为true
}
return TRUE;
}
return CView::PreTranslateMessage(pMsg);
}
void CSDITabView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(bCtrlKeyDown)
{
//MessageBox(_T("VK_CONTROL按下"));
bCtrlKeyDown = FALSE;
}
CView::OnMouseMove(nFlags, point);
}
3.可以响应WM_KEYDOWN消息
这里省略...
提点建议:这里是c/c++板块,lz可以去vc/mfc板块,那边的这方面的资源丰富些。希望以上对你有帮助。