应该在安装回调时函数已经存在(包含它的对象已经建立),拆除时函数还在(包含它的对象还在)这样才用(理论上,我一般用全局的),切记不要在构造函数中安装本类成员作为callback函数否则你会死得难看的!

解决方案 »

  1.   

    静态成员函数可以做回调函数!
    没有自动提示可以试试将项目目录下的.ncb删除,再重新大开该项目。(别担心!VC会重新生成一个新的.ncb文件)
      

  2.   

    没有自动提示,你要把.h文件加到你的"Header Files"里。
      

  3.   

    回调函数最好用全局函数。如果要是必须用类成员函数的话,这个成员函数一定要是static类型的,也就是静态成员函数。
    因为回调函数必须具有独立于任何对象实例的地址。普通成员函数的地址是通过类中的this指针计算出来的,所以不是独立地址。而静态成员函数的地址是与this指针无关的,具有全局函数的性质。
      

  4.   

    全局函数或静态成员函数(因为静态成员函数本质上就是全局函数)。
    类成员函数是隐含带有this指针工作的(由编译器实现),所以即使成员函数和回调函数的声明看上去一模一样,但实际却是不同的。
      

  5.   

    可以做到的,<Using windows Hooks with MFC> 里边有说明(英文的,不过不难):
    不过 m_mov 为什么要用 0xB9 我就不明白,你要是看明白了,千万要告诉我 :)
    template <class T> class HOOKDLL_API CHKThunk
    {
      BYTE    m_mov;    // mov ecx, <0xB9>
      ....
    }Callback thunking
    As good C++ programmers, our intention is to provide a generic wrapper class to encapsulate all the windows hooks-related issues. In the optimal case, the programmer will only have to derive from my CHook class, and to override (if necessary) a member function, namely the hook procedure. Unfortunately, the hook procedures, as any callback functions, are prototyped as C functions, which do not associate data with operations on that data. Therefore, one cannot use as callback a normal member function, which needs the hidden “this” pointer. Sometimes, it is possible to handle callbacks with member functions, by keeping a pointer in a collection indexed by a return value or passing a pointer in a parameter for application-supplied data. (See Davide Marcato's article, “Encapsulating Windows Timers in MFC,” in the January 98 issue of VCDJ.) However, these techniques are dependent on the particularities of the callback functions and not suitable for our case. The solution appears from a deeper observation of the ATL source code, which ships with VC++ 6.0. The ATL team used thunks to give WindowProc access to the this pointer of the CWindowImpl<> class (See also Richard Grimes' article,  “ATL and Win32 Applications” in the February 99 issue of VCDJ.). Generally, a thunk is a stubroutine, in an overlay-programming environment, which loads and jumps to the correct overlay.In our case, we have to simulate the function call mechanism by putting the this value in the ECX CPU's register, and forcing a jump to the member function's code. As in the ATL code, I defined a helper class CThunk to "wrap" the method to be used as a callback. The difference between my example and the ATL code is in the CPU's instructions, which are completely different because we are using the thiscall calling convention, i.e. the this pointer is stored in ECX.Here is the complete code for the class, which has only two methods:#pragma pack(push, 1) // Force byte alignment template <class T> class HOOKDLL_API CHKThunk
    {
      BYTE    m_mov;          // mov ecx, <0xB9>
      DWORD   m_this;         // pThis
      BYTE    m_jmp;          // jmp func     <0xE9>
      DWORD   m_relproc;      // jmp is relative
    public:
      typedef void (T::*TMPFN)();
      void InitThunk(TMPFN method, const T* pThis)
      {
        union {
          DWORD func;
          TMPFN method;
        } addr;    addr.method = method;
        m_mov = 0xB9;
        m_this = (DWORD)pThis;
        m_jmp = 0xE9;
        m_relproc = addr.func - (DWORD)(this+1);
        FlushInstructionCache(GetCurrentProcess(), this, sizeof(*this));
      }
      FARPROC GetThunk() const {
        _ASSERTE(m_mov == 0xB9);
        return (FARPROC)this; }
    };#pragma pack(pop) // CHKThunkNow, we simply derive the hook class from CHKThunk. The SetWindowsHookEx() function expects a callback function as a second argument, which normally cannot be a member in any class. After initializing the thunk in CHook's constructor with the address of our HKHookProc() member function, we simply pass to SetWindowsHookEx() the pointer returned by GetThunk(). This pointer can be interpreted as the address of a piece of code, which finally calls the HKHookProc() member function:class HOOKDLL_API CHook: public CHKThunk<CHook>
    {
    public:
      HHOOK m_hhook;  CHook(HHOOK hHook = NULL): m_hhook(hHook)
      {
        InitThunk((TMPFN)HKHookProc, this);
      }
      LRESULT HKHookProc(int nCode, WPARAM wParam, LPARAM lParam);
      BOOL Hook();
      BOOL UnHook();
    };Of course, this implementation is characteristic of the Intel X86 architecture, but the same technique can be used for any platform. For example, the window thunk used by ATL (see the file atlcom.h, which ships with VC++ 6.0) is implemented for both machines based on Intel and Alpha architectures.
      

  6.   

    将成员函数声明为static FAR PASCAL
    不过一般不要将回调函数放在类里面,这样会反而会破坏程序的结构,而且效率也较低。
    通常回调函数要么什么都不做,要么就是实现一个完整的算法,应该把它独立在你的对象结
    构之外,便于调试和修改。