首先用自己的窗口过程替换掉某个窗口句柄(传入的参数)原来的窗口过程,这样就可以截获该窗口的一些消息现在的问题是,当其他窗口向这个窗口发送鼠标消息时(使用WINAPI发送),在自定义的窗口过程中也可以看到,但是由于MFC窗口类是在消息映射函数中处理鼠标事件的,它不需要传递到窗口过程处理。所以这样一来,其他窗口发送的鼠标消息就无法触发该窗口类中定义的消息映射处理函数了,有办法解决么?前提是,我只知道一个窗口句柄,这个窗口句柄到底对应什么窗口类是不知道的,简单点说就是只允许通过一个窗口句柄,能否完成这种处理?

解决方案 »

  1.   

    可以用钩子,
    HHOOK SetWindowsHookEx(
      int idHook,        // hook type
      HOOKPROC lpfn,     // hook procedure
      HINSTANCE hMod,    // handle to application instance
      DWORD dwThreadId   // thread identifier
    );
    可以去查查MSDN它的用法,它可以截获所有的消息
      

  2.   

    1. 将这个窗口的鼠标消息响应函数彻底去掉 (声明,定义和BEGIN_MESSAGE_MAP消息映射三处)
    2. 在窗口的OnCreate()中return之前SetWindowLong
      

  3.   

    除了钩子外,可以试试重写应用类的虚函数ProcessMessageFilter,例:CWinYourApp::ProcessMessageFilter(int code, LPMSG lpMsg)
    {
        if(m_hTheWnd != NULL)
        {
    if((lpMsg->hwnd == m_hTheWnd) || ::IsChild(m_hTheWnd, lpMsg->hwnd))
    {
        if(lpMsg->message == WM_LBUTTONDOWN)
        {
    //Do you process
        }
    }
        }
    }
      

  4.   

    MFC定义了下面的两个主要结构: 
    struct AFX_MSGMAP_ENTRY
    {
    UINT nMessage; // windows message
    UINT nCode; // control code or WM_NOTIFY code
    UINT nID; 
    // control ID (or 0 for windows messages)
    UINT nLastID; 
    // used for entries specifying a range of control id's
    UINT nSig; 
    // signature type (action) or pointer to message #
    AFX_PMSG pfn; // routine to call (or special value)
    };
    struct AFX_MSGMAP
    {
    #ifdef _AFXDLL
    const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
    #else
    const AFX_MSGMAP* pBaseMap;
    #endif
    const AFX_MSGMAP_ENTRY* lpEntries;
    };其中AFX_MSGMAP_ENTRY结构包含了
    一个消息的所有相关信息,其中nMessage为Windows消息的ID号
    nCode为控制消息的通知码
    nID为Windows控制消息的ID
    nLastID表示如果是一个指定范围的消息被映射的话,
    nLastID用来表示它的范围。
    nSig表示消息的动作标识
    AFX_PMSG pfn 它实际上是一个指向
    和该消息相应的执行函数的指针。AFX_MSGMAP_ENTRY结构实际上定义了消息和处理此消息的动作之间的映射关系。因此静态数组变量_messageEntries[]实际上定义了一张表,表中的每一项指定了相应的对象所要处理的消息和处理此消息的函数的对应关系,因而这张表也称为消息映射表。AFX_MSGMAP定义了一单向链表,链表中每一项的值是一指向消息映射表的指针(实际上就是_messageEntries的值)。你的消息映射中的DECLARE_MESSAGE_MAP 和DECLARE_MESSAGE_MAP之间的定义都将存放在上面的那个消息映射链表中,你可以通过遍历链表实现查找处理函数的指针,然后调用即可要获得这个消息映射实体链表_messageEntries ,可以通过GetMessageMap()这个虚函数
      

  5.   

       当 自己的窗口 截获到 目标窗口消息时,保存该消息,等处理完毕后,利用 SendMessage 函数把该消息发送给目标窗口。
       该函数定义:
       LRESULT SendMessage(
      HWND hWnd,      // handle to destination window
      UINT Msg,       // message
      WPARAM wParam,  // first message parameter
      LPARAM lParam   // second message parameter
    );
      

  6.   

    用SetWindowsHookEx给窗口所属线程安装WH_GETMESSAGE钩子。
      

  7.   

    在你的处理过程中,判断消息类型是不是自己要修改的,如果不是则SetWindowLong把那个窗口过程设置为原来的,把消息SendMessage发给那个窗口,再SetWindowLong把窗口过程设置回来;
    或者自己去调用那个窗口的消息响应过程
    CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
    if (pWnd != NULL)
    {
    // call window proc directly since it is a C++ window
    AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam);
    }
      

  8.   

    可能自己有个地方没说清楚这个是放在DLL里面,窗口句柄是从APP传入的,我不可能去重载任何函数
      

  9.   

    写段伪码吧// 用户调用
    UserCall(HWND hwnd)
    {
    // 替换窗口过程
    ReplaceWndProc(hwnd, MyWndProc);
    ...
    }// 自定义的窗口过程
    MyWndProc(MSG msg....)
    {
    // 调用原来的窗口过程
    CallOrgWndProc(msg...);switch (msg)
    {
    case WM_LBUTTONDOWN:
    break;
    ...
    }
    }// 另一个窗口发送鼠标消息到这个窗口
    SendMessage(hwnd, msg...)在MyWndProc中是可以看到该消息的,但是这个消息是不会触发应用上MESSAGE_MAP的Cxxxx::OnLButtonDown()处理了,换句话说,APP的鼠标消息在MyWndProc中是看不到的,说明这种消息在之前就被处理了现在的问题不是要截获消息,而是怎样把我在DLL发出的消息触发MESSAGE_MAP中定义的消息映射处理,前提就是我只能通过HWND实现,因为在DLL里面我根本不知道外部它对应的窗口类是什么
      

  10.   

    在MyWndProc中是可以看到该消息的,但是这个消息是不会触发应用上MESSAGE_MAP的Cxxxx::OnLButtonDown()处理了,换句话说,APP的鼠标消息在MyWndProc中是看不到的,说明这种消息在之前就被处理了 ???
    给这个窗口发的鼠标消息到底能不能被MyWndProc看到啊?
      

  11.   

    能看到但是Cxxxx::OnLButtonDown(...)并不被调用
      

  12.   

    向这个窗口发的消息MyWndProc能看到但是APP上的鼠标操作在MyWndProc里面是没有的,就是说我用鼠标点窗口,这个消息不会反映到MyWndProc里面,如果我SendMessage发送鼠标消息到这个窗口,能在MyWndProc中看到
      

  13.   


    那是的啊,你已经用MyWndProc替代了mfc封装的窗口过程了啊,而且窗口消息如果被一窗口响应处理了,就不会再被应用类处理了,为啥要在应用类添加鼠标消息的响应函数呢?
    我还是不明白你要做什么,既然替换了自己的窗口函数,为何还要应用类去响应处理呢(虽然我知道这个窗口是你写的dll封装的,而调用dll的客户程序是第三方的)
    如果是想在你的过程处理完后,还要执行客户程序的消息处理,完全可以定义一个接口,将应用类的鼠标消息
    处理函数的指针传进去(也就是回调函数):
    typedef void (*PMSGFUNC)(UINT nFlags, CPoint point);
    class CYourWnd
    {
        ...
        PMSGFUNC m_pLButtonDownFunc;
    }MyWndProc(MSG msg....) 

    // 调用原来的窗口过程 
    // CallOrgWndProc(msg...);   //不要这个switch (msg) 

    case WM_LBUTTONDOWN: 
        {
            //Do your process
            ...
            
            //调用客户程序的消息句柄
             if(m_pLButtonDownFunc) m_pLButtonDownFunc(nFlags, point);
        }
        break; 
    ... 

      

  14.   

    DLL是我写的,但是应用程序就不一定了,甚至这个窗口是否是MFC窗口类我也不知道(假如别人用WINDOWS SDK方式编程的话),因为我只能看到HWND我的问题就是,假如,注意是假如,用户在他自己的窗口类中定义了Cxxx::OnLButtonDown处理函数的话,我希望当另一个窗口向用户传入的HWND发送WM_LBUTTONDOWN消息时,Cxxx::OnLButtonDown能得到调用这个问题的原因就是我需要在用户的窗口上覆盖一个窗口,但是在点击鼠标的时候,覆盖的这个窗口会将消息发送到原来的窗口,要看起来和原本没有被覆盖的行为一致(放心,不是hack)
      

  15.   

    “那是的啊,你已经用MyWndProc替代了mfc封装的窗口过程了啊,而且窗口消息如果被一窗口响应处理了,就不会再被应用类处理了,为啥要在应用类添加鼠标消息的响应函数呢? ”应该这么说,是先被MFC的消息映射处理函数处理之后,如果没有被处理可能才会调用窗口过程处理
      

  16.   


     你既然在用户的窗口上已经覆盖了一个窗口,那么你完全可以不必替代用户的窗口的处理过程啊?直接将你的窗口的处理过程的消息转发就是了(SendMessage即可)。
      

  17.   


    不替换窗口过程也不行的,似乎从DLL里面SendMessage(hwnd, ...)过去不会触发Cxxx::OnLButtonDown处理
      

  18.   

    搞了半天是窗口过程弄错了,这些消息是在它的父窗口处理的
    害大家折腾这么久,抱歉!我对不起大家,我对不起组织,我对不起CCAV....