1、重载消息响应函数OnSetCursor( )
2、在OnSetCursor( )里用_TrackMouseEvent( )跟踪WM_MOUSELEAVE事件
3、编一个鼠标离开消息响应函数afx_msg LRESULT OnMouseLeave( WPARAM wp,
   LPARAM lp )
4、添加消息映射 ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave )
5、自己再琢磨琢磨……,好运!

解决方案 »

  1.   

    OnMouseMove 消息并不能判断mouse 进入和离开这两种状态
    不只footway的方法实现起来可行否?
      

  2.   

    footway(靠边行走)的方法应该是可行的,当鼠标进入和离开Button区域时都会产生OnSetCursor( )事件,通过读取鼠标的位置或自己设置一个标志就可以判断鼠标是进入或是离开Button区域了
      

  3.   

    footway(靠边行走) 的方法是可以的了..mouseleave的消息只要你吧CArrowButton的类型在class wizard里面改成CWnd,就可以直接使用class wizard添加WM_MOUSELEAVE的message handler函数而不用手动添加判断CRect的方法多余了,而且MouseMove的消息在没有setcapture的情况下发送频率不高,容易造成丢失...
      

  4.   

    使用这种方法最简单:
    在第一次获得MouseMove消息时设置一个标志量,并SetCapture();捕获Mouse无论Mouse到哪消息都会传送到按钮。
    在MouseMove消息中这个标志量为真时,取得按钮的CRect与Mouse坐标判断,如果Mouse移出了CRect以外,则ReleaseCapture();,释放Mouse,置标志量为假.
      

  5.   

    偶也见过这个问题,只要pretranslatemessage就可以了
      

  6.   

    得到BUTTON的rect,在OnMouseMove中用PtInRect()函数来判断。
      

  7.   

    得到BUTTON的rect,在OnMouseMove中用PtInRect()函数来判断。
      

  8.   

    还是trcakmouseEvent吧,这样在情况比较复杂的情况下,还会有效
      

  9.   

    我的Buttons是三角形区域的,我希望通过只处理鼠标进入和离开Button
    事件来实现。
      如何跟踪鼠标,捕获到这两个事件呢?
       footway(靠边行走) 能提供些代码吗?……
       谢谢!
      

  10.   

    可 以 看 一 下 V C L 中 的 代 码 , 就 有 这 个 的 处 理 方 法 。
      

  11.   

    CButton好象没有OnMouseMove事件?
      

  12.   

    1、WinExec(_T("c:\windows\calc.exe"),SW_SHOWMAXIMIZED);2、
    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)
      

  13.   

    SetCapture是不行的,因为SetCapture要求鼠标键按下才会进入capture状态,而且放开鼠标健后就自动退出capture状态了,所以肯定不行。用MouseMove也不行,因为鼠标离开button后就收不到消息了。建议用_trcakmouseEvent,这个不会出问题,实现也不难。
      

  14.   

    看看著名的界面程序 CJLib 就清楚了。
    在Win2000以上用TrackMouseEvent方法监控WM_MOUSELEAVE最
    方便,但在Win98上该方法不可行,必须根据鼠标位置是否
    在Button焦点中才行,具体代码参见 CJLib
      

  15.   

    Win 9X也可以使用TrackMouseEvent,不过换成_trackmouseevent,上一个是2000特有的API函数,而后一个是模拟出来的,所以任何版本都可以用。
      

  16.   

    有个很简单但是很蠢的办法(我以前不知道WM_MOUSELEAVE时用的),就是用Timer,不断地判断鼠标是否在图标上……
    看起来简单,其实实现还是很麻烦的。
      

  17.   

    使用这种方法最简单:
    在第一次获得MouseMove消息时SetCapture();捕获Mouse无论Mouse到哪消息都会传送到按钮。
    在MouseMove消息中取得按钮的CRect与Mouse坐标判断,如果Mouse移出了CRect以外,则ReleaseCapture();,释放Mouse.
      

  18.   

    我记得在 Delphi 和 C++ Builder 里处理了
    MouseIn 和MouseLeave 消息,你可以自己
    定义 MouseIn 和 MouseLeave消息,但是
    具体的消息值我忘了,去 Delphi 和 C++ Builder
    可以查到
      

  19.   

    一种更好的方法是调用SetWindowsHookEx(WH_MOUSE,fnMouseHookProc,...)在fnMouseHookProc的参数MOUSEHOOKSTRUCT中找到Mouse message的hwnd.把窗口handler跟CButton的handler相比较就可以发现mouse 是否在Button区域中.具体函数说明可以查MSN资料.
      

  20.   

    To: HoverSetCapture是不行的,我前面已经说过,SetCapture要求鼠标键按下才会进入capture状态,而且放开鼠标健后就自动退出capture状态了,说以只能在鼠标键被按下的情况(拖曳)才可以使用。
    Loyee的Hook用法……有种杀鸡用牛刀的感觉……
      

  21.   

    to wolfliu:delphi和BCB的VCL控件本身就支持MouseIn,MouseOut,实现机制本来就有多种Hover的方法是可行的,alexanderyu的timer也是可行的,hook和重载pretranslatemessage差别不大
    只是你们的方法都要轮寻...当然不要求效率的情况下(现在CPU快得很)都可以使用,而且很稳定_tackmouseevent则是MFC支持的,但并没有显式的在class wizard里面支持,可能MS认为需要使用这个的人不多吧.
    其实用它多好,又稳定量又足...即插即用,关键是代码耦合度低呀!!!
    想重用代码的话,考虑用那个吧,效果好得超出你的想象当然前提是该控件基类是CWnd,不然还得自己判断
      

  22.   

    to wolfliu:delphi和BCB的VCL控件本身就支持MouseIn,MouseOut,实现机制不明(本来就可以有多种,但机理大同小异)Hover的方法是可行的,alexanderyu的timer也是可行的,hook和重载pretranslatemessage差别不大
    只是你们的方法都要轮寻...当然不要求效率的情况下(现在CPU快得很)都可以使用,而且很稳定_tackmouseevent则是MFC支持的,但并没有显式的在class wizard里面支持,可能MS认为需要使用这个的人不多吧.
    其实用它多好,又稳定量又足...即插即用,关键是代码耦合度低呀!!!
    想重用代码的话,考虑用那个吧,效果好得超出你的想象当然前提是该控件基类是CWnd,不然还得自己判断
      

  23.   

    alexanderyu(alex) :是否考虑了应用程序不是激活状态下的情况.
      

  24.   

    to loyee:
    我不知道_tackmouseevent是否能在窗口非激活状态下工作,应该是不会有效果的。如果你说的是timer的话,应该可以的吧……另外hook也应该可以。我想起有些应用程序的hover功能(我是指flat的button)在非激活状态下也会起作用,而另一些程序就不会,我想可能就是用hook和_tackmouseevent的区别吧……
      

  25.   

    TO:alexanderyu(alex)你的说话有何依据?我做的一种CHovBut自绘按钮就是用这种方法实现的,在Mouse移动到Button上时就SetCapture()
      

  26.   

    to Hover(翔):
    如果你说的是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应用程序吗?
      

  27.   

    To:alexanderyu(alex) 程序都写完了,用的就是这种方法,你要看源程序吗?
      

  28.   

    To Hover(翔):
    我可以肯定你一定是弄错了,你可以把你程序里的SetCapture语句去掉,那个程序应该还是能正常运行的。
      

  29.   

    to  gameboy999(我心迷茫) 我知道 Delphi and BCB 处理了这个消息,我的意思是你从那里
    查到 MouseIn和MouseLeave的值,然后在VC中自定义消息
    #define MouseIn   WM_USER + ..
    #define MouseOut  WM_USER + ..然后在自编的控件中处理这两个消息就行了,我原来的一个同事就是
    这么做的
      

  30.   

    to hover:
    本来是想赌的,不过我可用分还不够你的筹码……呜……
    不过你要赌的是什么呢?是你的程序在去掉capture后不能运转了,还是capture在不按键情况下也能得到鼠标消息?看你那么坚持,我又做了一次试验,现在结论是这样的:
    不按住按键可以调用Setcapture,而且窗口也的确能进入Capture状态,但是,这个capture是仅限于本窗体内的,也就是说鼠标移除窗体外后鼠标消息就跟踪不到了。
    不过,capture后和没有capture的确有很大的区别,最重要的是消息接受得多了,capture后在非客户区(NonClient,菜单,标题栏等)也能收到鼠标消息,而且移动到窗体内的其他子窗体上也能收到消息,这样的确对设计hover按钮有很大帮助。
    但是:当鼠标移除窗体后是不能收到鼠标消息的(要想收到只能在按键状况下SetCapture),所以这个设计有个重大的Bug:如果button处于"hover"状态(也就是说鼠标在button上),而按钮又紧贴着窗口边缘的话,将鼠标从窗口边缘的方向移出窗口,button就有可能会漏掉关键的表示鼠标移出的消息——这样会导致鼠标移除窗口后button仍然处于hover状态而无法恢复。
    以上这个bug就是我当初放弃使用capture来实现hover的原因,因为有的消息会漏掉,而用_TrackMouseEvent就不会有这个问题。
      

  31.   

    最方便的方法是起用定时器
    SetTimer(...)
    再用ptInRect(...)
      

  32.   

    To:alexanderyu(alex) 看到你的回复写了这么多,很好,针对你所提出的所谓“重大的Bug”我把铵钮放置在窗口边缘,测试了大半天,也没发现你所说那回事儿,并用SPY++监视所有的消息,也没有发现有消息漏掉的现象
    这就让我不明白了,你用的是什么开发工具?是什么操作系统?呵呵,总不会是你的Mouse有问题吧???到底是不愿意诚认错误呢?还是不愿和我赌呢?可用分太少的话我可以先借你点,分不是问题,我可用分有的是...
      

  33.   

    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的系统上应该都是一样的。
      

  34.   

    To:AlexanderYu(alex) 
    根据我的测试在按钮中SetCapture在主窗外也能获得Mouse消息,关于:
    "介于这个东西我已经完全弄清楚了,我不觉的还有赌的必要(这好像是抢一样,当然你想送分给我我是不会介意的^_^"
    如我不说来赌的话,你会这么认真的来看这个问题吗?你会弄清楚这个问题吗?还会有你今天的这么长的回复吗?关于你所说的Bug:
    我进行测试时,按钮放在主窗的边框边缘,与边框的距离为零,不存在非客户区的问题而且进行了多次测试,并没有出现一例情况
      

  35.   

    据我测试,当按钮在主窗边缘,无客户区时,Mouse移出主窗仍然会获得一次已移出主窗的消息(WM_MOUSEMOVE)
      

  36.   

    要是现场讨论就好了!!!!
    我是深自遗憾!!!!
    大家说我的这个意见好不好!!!!
    如果这样那csdn的服务器就哈哈了!!!
    这样的氛围我好久没有看到了!!!!
    在商业化风气正盛的今天也不太常见了!!!!!
    这是很遗憾的事!!!
      

  37.   

    To Hover(翔):
    先澄清一下:我一向不喜欢赌博,这和我为人谨慎有关系(有时也不喜欢自己这一点),我并不是想赌所以画那么大力气弄清楚这个问题,而是我有和别人争论时一定要把事情弄清的习惯。所以即使你只是一直坚持你的说法而没提到赌我也会做研究的。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在一定范围内有用,也是一种不规范的用法。