1、重载消息响应函数OnSetCursor( )
2、在OnSetCursor( )里用_TrackMouseEvent( )跟踪WM_MOUSELEAVE事件
3、编一个鼠标离开消息响应函数afx_msg LRESULT OnMouseLeave( WPARAM wp,
LPARAM lp )
4、添加消息映射 ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave )
5、自己再琢磨琢磨……,好运!
2、在OnSetCursor( )里用_TrackMouseEvent( )跟踪WM_MOUSELEAVE事件
3、编一个鼠标离开消息响应函数afx_msg LRESULT OnMouseLeave( WPARAM wp,
LPARAM lp )
4、添加消息映射 ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave )
5、自己再琢磨琢磨……,好运!
不只footway的方法实现起来可行否?
在第一次获得MouseMove消息时设置一个标志量,并SetCapture();捕获Mouse无论Mouse到哪消息都会传送到按钮。
在MouseMove消息中这个标志量为真时,取得按钮的CRect与Mouse坐标判断,如果Mouse移出了CRect以外,则ReleaseCapture();,释放Mouse,置标志量为假.
事件来实现。
如何跟踪鼠标,捕获到这两个事件呢?
footway(靠边行走) 能提供些代码吗?……
谢谢!
ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:\windows\temp"),SW_SHOWMAXIMIZ
ED);3、STARTUPINFO stinfo;
PROCESSINFO procinfo;
CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,
NORMAL_PRIORITY_
CLASS,NULL,NULL, &stinfo,&procinfo)
在Win2000以上用TrackMouseEvent方法监控WM_MOUSELEAVE最
方便,但在Win98上该方法不可行,必须根据鼠标位置是否
在Button焦点中才行,具体代码参见 CJLib
看起来简单,其实实现还是很麻烦的。
在第一次获得MouseMove消息时SetCapture();捕获Mouse无论Mouse到哪消息都会传送到按钮。
在MouseMove消息中取得按钮的CRect与Mouse坐标判断,如果Mouse移出了CRect以外,则ReleaseCapture();,释放Mouse.
MouseIn 和MouseLeave 消息,你可以自己
定义 MouseIn 和 MouseLeave消息,但是
具体的消息值我忘了,去 Delphi 和 C++ Builder
可以查到
Loyee的Hook用法……有种杀鸡用牛刀的感觉……
只是你们的方法都要轮寻...当然不要求效率的情况下(现在CPU快得很)都可以使用,而且很稳定_tackmouseevent则是MFC支持的,但并没有显式的在class wizard里面支持,可能MS认为需要使用这个的人不多吧.
其实用它多好,又稳定量又足...即插即用,关键是代码耦合度低呀!!!
想重用代码的话,考虑用那个吧,效果好得超出你的想象当然前提是该控件基类是CWnd,不然还得自己判断
只是你们的方法都要轮寻...当然不要求效率的情况下(现在CPU快得很)都可以使用,而且很稳定_tackmouseevent则是MFC支持的,但并没有显式的在class wizard里面支持,可能MS认为需要使用这个的人不多吧.
其实用它多好,又稳定量又足...即插即用,关键是代码耦合度低呀!!!
想重用代码的话,考虑用那个吧,效果好得超出你的想象当然前提是该控件基类是CWnd,不然还得自己判断
我不知道_tackmouseevent是否能在窗口非激活状态下工作,应该是不会有效果的。如果你说的是timer的话,应该可以的吧……另外hook也应该可以。我想起有些应用程序的hover功能(我是指flat的button)在非激活状态下也会起作用,而另一些程序就不会,我想可能就是用hook和_tackmouseevent的区别吧……
如果你说的是SetCapture的话,我很久以前就做过试验,不按键是不行的。
我忘了是在哪里看到的了,不过我在KB里找到这些文字(原文是关于游戏设计的,不过我想这也说明了问题):
Under Windows 3.1, the Moby Dick application could have used the SetCapture function to "capture the mouse," that is, direct all mouse messages to the game regardless of the cursor location. This isn't possible under Windows 95, because of asynchronous input processing—one of the ways Windows 95 keeps any one application from monopolizing the system. You can still capture the mouse, but only when a button is depressed. Obviously this isn't what I want in Moby Dick.
所以,不按鼠标能捕捉只是在windows3.1里面的,你以前写的是win31应用程序吗?
我可以肯定你一定是弄错了,你可以把你程序里的SetCapture语句去掉,那个程序应该还是能正常运行的。
查到 MouseIn和MouseLeave的值,然后在VC中自定义消息
#define MouseIn WM_USER + ..
#define MouseOut WM_USER + ..然后在自编的控件中处理这两个消息就行了,我原来的一个同事就是
这么做的
本来是想赌的,不过我可用分还不够你的筹码……呜……
不过你要赌的是什么呢?是你的程序在去掉capture后不能运转了,还是capture在不按键情况下也能得到鼠标消息?看你那么坚持,我又做了一次试验,现在结论是这样的:
不按住按键可以调用Setcapture,而且窗口也的确能进入Capture状态,但是,这个capture是仅限于本窗体内的,也就是说鼠标移除窗体外后鼠标消息就跟踪不到了。
不过,capture后和没有capture的确有很大的区别,最重要的是消息接受得多了,capture后在非客户区(NonClient,菜单,标题栏等)也能收到鼠标消息,而且移动到窗体内的其他子窗体上也能收到消息,这样的确对设计hover按钮有很大帮助。
但是:当鼠标移除窗体后是不能收到鼠标消息的(要想收到只能在按键状况下SetCapture),所以这个设计有个重大的Bug:如果button处于"hover"状态(也就是说鼠标在button上),而按钮又紧贴着窗口边缘的话,将鼠标从窗口边缘的方向移出窗口,button就有可能会漏掉关键的表示鼠标移出的消息——这样会导致鼠标移除窗口后button仍然处于hover状态而无法恢复。
以上这个bug就是我当初放弃使用capture来实现hover的原因,因为有的消息会漏掉,而用_TrackMouseEvent就不会有这个问题。
SetTimer(...)
再用ptInRect(...)
这就让我不明白了,你用的是什么开发工具?是什么操作系统?呵呵,总不会是你的Mouse有问题吧???到底是不愿意诚认错误呢?还是不愿和我赌呢?可用分太少的话我可以先借你点,分不是问题,我可用分有的是...
我已经承认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的系统上应该都是一样的。
根据我的测试在按钮中SetCapture在主窗外也能获得Mouse消息,关于:
"介于这个东西我已经完全弄清楚了,我不觉的还有赌的必要(这好像是抢一样,当然你想送分给我我是不会介意的^_^"
如我不说来赌的话,你会这么认真的来看这个问题吗?你会弄清楚这个问题吗?还会有你今天的这么长的回复吗?关于你所说的Bug:
我进行测试时,按钮放在主窗的边框边缘,与边框的距离为零,不存在非客户区的问题而且进行了多次测试,并没有出现一例情况
我是深自遗憾!!!!
大家说我的这个意见好不好!!!!
如果这样那csdn的服务器就哈哈了!!!
这样的氛围我好久没有看到了!!!!
在商业化风气正盛的今天也不太常见了!!!!!
这是很遗憾的事!!!
先澄清一下:我一向不喜欢赌博,这和我为人谨慎有关系(有时也不喜欢自己这一点),我并不是想赌所以画那么大力气弄清楚这个问题,而是我有和别人争论时一定要把事情弄清的习惯。所以即使你只是一直坚持你的说法而没提到赌我也会做研究的。1.前问所说:“我进行测试时,按钮放在主窗的边框边缘,与边框的距离为零,不存在非客户区的问题而且进行了多次测试,并没有出现一例情况”,然而我所指的非客户区(NonClient)就是指主窗体的“边框边缘”那儿2-3个像素宽度的区域(就是普通窗口看上去的那条黑线),可能你把非客户区误解为不是子窗体(button)内的区域了吧。2.另一贴:“据我测试,当按钮在主窗边缘,无客户区时,Mouse移出主窗仍然会获得一次已移出主窗的消息(WM_MOUSEMOVE)”
1)“Mouse移出主窗仍然会获得一次已移出主窗的消息(WM_MOUSEMOVE)”,也就是说在mouse移除窗口后就再也不能收到WM_MOUSEMOVE消息了(除了“仍会获得”的那一个)?其实我一直说的就是这个(移除窗口后收不到消息),看来我们之前的理解有太大的分歧。
2)事实上,这最后的一个WM_MOUSEMOVE并不是鼠标移出窗体后发出的,而是鼠标移到窗口边缘的非客户区上时发出的,平时鼠标移到非客户区上时不会发送WM_MOUSEMOVE消息,而发送WM_NCHITTEST消息,表示“非客户区名中测试”,但是当setcapture后,即使鼠标移到非客户区上也会发送WM_MOUSEMOVE消息,就是你收到的最后一个消息了。
另外,我突然想起我是在哪里看到有关这个问题的详细描述了:就在Microsoft Press出的“Windows程序设计”里(中文版,北大出版社出版),这里有那一段话的电子文档:
In the 32-bit versions of Windows, mouse capturing is a bit more restrictive than it was in earlier versions of Windows. Specifically, if the mouse has been captured, and if a mouse button is not currently down, and if the mouse cursor passes over another window, the window underneath the cursor will receive the mouse messages rather than the window that captured the mouse. This is necessary to prevent one program from messing up the whole system by capturing the mouse and not releasing it. To avoid problems, your program should capture the mouse only when the button is depressed in your client area. You should release the capture when the button is released.
从最后一句话可以看出,即使在不按键的情形下SetCapture在一定范围内有用,也是一种不规范的用法。