我在程序内挂了个线程钩子,勾取MOUSEMOVE消息,结果我发现,只要我截获这个消息,程序过几秒后绝对假死。
而我截获其他消息,如LBUTTONDOWN/UP啊,就没事。

说下我的程序流程:
窗体A自CDialog派生,A里包含一个与窗体大小相等的第三方控件,称为X
窗体B派生自A程序启动后,窗体B会弹出,因为本窗体包含一个大小与窗体一样的第三方插件X,所以,本窗体的所有鼠标操作都被X给挡住了,比如,我想处理鼠标按下窗体的消息,也被X给挡住了。
所以,我给线程挂钩,截取鼠标在第三方插件X上的任何鼠标操作,然后把消息发给窗体B,让B执行相应的操作。
因为B派生自A,所以,B的函数执行完毕后,还要调用A的函数,来执行某些操作。
整个过程就是如此,下面是关键代码。
关键代码整理如下:
//钩子的勾取消息的代码如下:
LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)   
{   
int x,y;
LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *)lparam;  
if (nCode>=0)   
{   
switch ( (UINT)wparam )
{
case WM_LBUTTONUP:
PostMessage(glhDisplayWnd/*往窗体B发消息*/, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
  break;
case WM_LBUTTONDOWN:
PostMessage(glhDisplayWnd/*往窗体B发消息*/, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
break;                  ////////////////////////////////////////////////////////////
                  //当我把截取MOUSEMOVE消息注释掉时,程序不会假死
                  //但是,当我一勾引这个消息,程序运行后没几秒立刻假死
                  //////////////////////////////////////////////////////////////
case WM_MOUSEMOVE:
ScreenToClient(glhDisplayWnd, &(pMouseHook->pt) );
PostMessage(glhDisplayWnd/*往窗体B发消息*/, WM_MOUSEMOVE, wparam, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
break;
}
}   
return CallNextHookEx(glhHook,nCode,wparam,lparam);   
}   class A : public CDialog
{
  //省略无关代码,函数参数省略,语法没错误,只看流程
void OnLButtonDown(......)
{
    //做些不会让程序假死的操作
    CDialog::OnLButtonDown(....);
}
void OnMouseMove(.....) 
{
    //做些不会让程序假死的操作
    CDialog::OnMouseMove(....);
}
void OnSizing(....)
{
    //做些不会让程序假死的操作
    CDialog::OnSizing(....);
}
}
class B: public A
{
 //省略无关代码
BOOL OnInitDialog()
{
    //挂起线程内钩子,勾鼠标消息
}
LRESULT OnDestroy(WPARAM wParam,LPARAM lParam)
{
    //卸载钩子
}
void OnLButtonDown(......)
{
    //做些不会让程序假死的操作
    A::OnLButtonDown(....);  //执行父类的消息处理函数
}
void OnLButtonUp(......)
{
    //做些不会让程序假死的操作
    A::OnLButtonUp(....);
}
BOOL PreTranslateMessage(MSG* pMsg) 
{ switch (pMsg->message)
{
case WM_MOUSELEAVE:
//做点计算
break; case WM_MOUSEHOVER:
//
break;
case WM_MOUSEMOVE:
                  //这里加了点代码,处理MOUSEMOVE时,在本窗体内要做的事情
                  //然后
                  //再产生以上两个消息
TRACKMOUSEEVENT trmouse;
trmouse.cbSize = sizeof(TRACKMOUSEEVENT);
trmouse.dwFlags = TME_LEAVE | TME_HOVER;
trmouse.dwHoverTime = 2000;
trmouse.hwndTrack = pMsg->hwnd;
if(!_TrackMouseEvent(&trmouse)) 
return FALSE; break; }
return CDialog::PreTranslateMessage(pMsg);
}}

解决方案 »

  1.   

    问题比我想的要严重:不钩MOUSEMOVE会死,是勾取所有的消息都会死,只是其他消息毕竟没MOUSEMOVE发送消息那么频繁,所以,程序死的会慢点罢了究竟怎么回事??用 个钩子就把程序慢慢勾死了
      

  2.   

    PostMessage(glhDisplayWnd/*往窗体B发消息*/, WM_MOUSEMOVE, wparam, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );return CallNextHookEx(glhHook,nCode,wparam,lparam);   如果鼠标在你窗口的话,你会受到两次消息.可能会有问题吧.最好是用自定义消息替换WM_MOUSEMOVE等.
      

  3.   

    我把钩子里的每个消息对应的PostMessage 给注释掉
    发现程序就正常了,如果不注释,程序就会死我就迷糊了,我勾到一个消息,程序不会有问题,但是我给某窗体POST个消息,该窗体慢慢就死了??这是怎么回事???迷糊
      

  4.   


    PostMessage:
    函数功能:该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回。消息队列里的消息通过调用GetMessage和PeekMessage取得。函数原型:B00L PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);参数hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值:HWND.BROADCAST:消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口。NULL:此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样。Msg:指定被寄送的消息。wParam:指定附加的消息特定的信息。IParam:指定附加的消息特定的信息。返回值:如果函数调用成功,返回非零值:如果函数调用失败,返回值是零。若想获得更多的错误信息,请调用GetLastError函数。备注:需要以 HWND_BROADCAST方式通信的应用程序应当用函数 RegisterwindwosMessage来获得应用程序间通信的独特的消息。如果发送一个低于WM_USER范围的消息给异步消息函数(PostMessage.SendNotifyMessage,SendMesssgeCallback),消息参数不能包含指针。否则,操作将会失败。函数将再接收线程处理消息之前返回,发送者将在内存被使用之前释放。
    -------------首先查查你传递的窗口句柄对不对,其次要检查你的消息循环的,很有可能是一直在调用你的消息,没有接受消息机制引起,多调试一下,我之前也遇到过这些问题的
      

  5.   

    你不会发了个消息,被勾住,勾住以后有PostMessage消息,又被勾住,然后又PostMessage消息,就这样如此反复下去了吧
      

  6.   

    当时的确有这个问题,5楼也说了,不过,我把钩子里post的消息,改为我自定义的消息了,这样就不会被重复勾住了,可是程序还是会死
    究竟怎么回事呢??我不用钩子就没事。
      

  7.   

    钩子函数的内容已经改为:LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)   
    {   
    LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *)lparam;  
    if (nCode>=0)   
    {   
    switch ( (UINT)wparam )
    {
      case WM_LBUTTONUP:
    PostMessage(glhDisplayWnd, WM_LBUTTONUP_U/*仅供窗体B使用的自定义消息,等于BUTTONUP*/, MK_LBUTTON, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
       break;
      case WM_LBUTTONDOWN:
    PostMessage(glhDisplayWnd, WM_LBUTTONDOWN_U/*仅供窗体B使用的自定义消息,等于BUTTONUP*/, MK_LBUTTON, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
       }}
    return CallNextHookEx(glhHook,nCode,wparam,lparam);   }可是改完了,程序依然会死。
      

  8.   

    你switch里的东西没有完吧,看到只有一部分
      

  9.   


    //钩子函数的实现:     
    LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)   
    {   
    static int n = 0;
    LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *)lparam;  
    if (nCode>=0)   
    {   
    switch ( (UINT)wparam )
    {
      case WM_LBUTTONUP:
    TRACE("PostMessage M UP %d\n", n++);
    PostMessage(glhDisplayWnd, WM_LBUTTONUP_U, MK_LBUTTON, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
       break;
      case WM_LBUTTONDOWN:
    PostMessage(glhDisplayWnd, WM_LBUTTONDOWN_U, MK_LBUTTON, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
      break; }
    }   
    return CallNextHookEx(glhHook,nCode,wparam,lparam);   
    //继续传递消息    
    }   
    这是钩子的循环,当我在第三方插件(WEBBROWSER2)上点击一个连接时,因为鼠标抬起,会收到一个WM_LBUTTONUP消息,于是,我给窗体B发送自定义的WM_LBUTTONUP_U消息结果更严重的问题出来了:我在WEBBROWSER的空白区域【双击】(注意,不是单击)时,我发现TRACE 输出的数字猛然间增加到了8000多,然后程序就不动了,那肯定不动了啊,瞬间就居然Post了近万条消息,而且在不停的发我就纳闷了,为什么会这样呢??这个WEBBROWSER真头疼
      

  10.   


            case WM_MOUSEMOVE:
                ScreenToClient(glhDisplayWnd, &(pMouseHook->pt) );
                PostMessage(glhDisplayWnd/*往窗体B发消息*/, WM_MOUSEMOVE, wparam, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
                break;这个PostMessage把WM_MOUSEMOVE发到哪里去?反复循环获得WM_MOUSEMOVE消息造成程序死循环。
    你试试自定义消息来PoseMessage,比如PostMessage(glhDisplayWnd/*往窗体B发消息*/, MY_WM_MOUSEMOVE, wparam, MAKELPARAM((pMouseHook->pt.x), (pMouseHook->pt.y)) );
      

  11.   

    已经找到程序假死的原因,原来是钩子不停的往窗口发送消息,瞬间就上万个消息但是这么大量的消息是怎么产生的,没找到原因。只知道我不知道什么时候在窗体点啊点,就会瞬间产生大量的消息,可是我的程序中并没有任何循环发送消息的地方。钩子部分,也并不是重复勾住自己发出的消息形成死循环。
    虽然还是找不到原因,但先结贴了,我把钩子里发送消息的方式,由PostMessage全部改成SendMessage,问题就不会出现了,而且在也不会出现瞬间产生大量消息的问题,程序也就不会死了