1、重载消息响应函数OnSetCursor( )
2、在OnSetCursor( )里用_TrackMouseEvent( )跟踪WM_MOUSELEAVE事件
3、编一个鼠标离开消息响应函数afx_msg LRESULT OnMouseLeave( WPARAM wp,
LPARAM lp )
4、添加消息映射 ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave )
5、自己再琢磨琢磨……,好运!
footway(靠边行走)的方法应该是可行的,当鼠标进入和离开Button区域时都会产生OnSetCursor( )事件,通过读取鼠标的位置或自己设置一个标志就可以判断鼠标是进入或是离开Button区域了
footway(靠边行走) 的方法是可以的了..
mouseleave的消息只要你吧CArrowButton的类型在class wizard里面改成CWnd,就可以直接使用class wizard添加WM_MOUSELEAVE的message handler函数而不用手动添加
判断CRect的方法多余了,而且MouseMove的消息在没有setcapture的情况下发送频率不高,容易造成丢失...
得到BUTTON的rect,在OnMouseMove中用PtInRect()函数来判断。
还是trcakmouseEvent吧,这样在情况比较复杂的情况下,还会有效
SetCapture是不行的,因为SetCapture要求鼠标键按下才会进入capture状态,而且放开鼠标健后就自动退出capture状态了,所以肯定不行。用MouseMove也不行,因为鼠标离开button后就收不到消息了。建议用_trcakmouseEvent,这个不会出问题,实现也不难。
有个很简单但是很蠢的办法(我以前不知道WM_MOUSELEAVE时用的),就是用Timer,不断地判断鼠标是否在图标上……
看起来简单,其实实现还是很麻烦的。
一种更好的方法是调用
SetWindowsHookEx(WH_MOUSE,fnMouseHookProc,...)
在fnMouseHookProc的参数MOUSEHOOKSTRUCT中找到Mouse message的hwnd.把窗口handler跟CButton的handler相比较就可以发现mouse 是否在Button区域中.
具体函数说明可以查MSN资料.
To Hover(翔):
我已经承认SetCapture在不按键的情况下至少在窗口内是有效的,这还不够吗(对了,有关这个窗口还要作进一步解释:这个窗口是指应用程序的主窗口,而不是他的子窗口(如button),也就是说,在子窗口(button)内调用SetCapture的话则Capture在整个主窗口(包括非客户区)都能起效,但在主窗口外则是无效的)?
我所做的实验是很完备的,后来我又用spy++跟踪消息,结果当然是一样的。
介于这个东西我已经完全弄清楚了,我不觉的还有赌的必要(这好像是抢一样,当然你想送分给我我是不会介意的^_^).
关于Bug:
这个bug并不是总能再现,由于即使button紧贴着窗口边缘,他们之间总有很小的非客户区,如果鼠标在该区域的消息被捕获自然看不出这个bug来。由于鼠标有一定的扫描精度(一般100次/秒),所以在某些情况下鼠标经过非客户区的消息没有得到,就会发生bug,所以在比较好的鼠标上就不容易发生这个bug(现在有的鼠标扫描率高达600次/秒,我记得)
P.s.如果你执意要赌的话,我也愿意奉陪,当然只能出我现在仅有的4000分,赌的东西就是:
1.在鼠标没有按下的情况下SetCapture后,当鼠标移除主窗体外,就收不到鼠标消息(以WM_MOUSEMOVE为例)——我的观点。
2.在鼠标没有按下的情况下SetCapture后,当鼠标移除主窗体外,仍能收到鼠标消息(以WM_MOUSEMOVE为例)——你的观点(如果你同意你的观点如此的话)
最后说一下,就像我上面所说的,我已经完全弄清楚这个东西了,这样还说要赌的话我觉得是不道德的。
另外我的环境是VC6+win2k,我相信在非win3.1的系统上应该都是一样的。