树静山空  

前段时间在自己用win32api封装一个进度条,做到后来的时候发现其中有一个重画界面的回调函数不能作为成员函数。不能够实时取得类中成员变量问题。后来经过一番探究以后终于找到了一个可行的方案,现将其发布在此方便后来者。

其中用到了部分汇编转换this指针地址。其中主要的代码如下:

Thunk.h

#include "stdafx.h"

template< typename TDst, typename TSrc >
TDst  UnionCastType( TSrc src ) {
    union {
        TDst  uDst;
        TSrc  uSrc;
    } uMedia;
    uMedia.uSrc  =  src;
    return uMedia.uDst;
}

#pragma pack( push, 1 )
struct  MemFunToStdCallThunk {
    BYTE          m_mov;
    DWORD      m_this;   //mov ecx pThis
    BYTE          m_jmp;
    DWORD      m_relproc;  //jmp

    BOOL  Init( DWORD_PTR proc, void* pThis ) {
        m_mov = 0xB9;   // mov ecx
        m_this = PtrToUlong(pThis);
        m_jmp = 0xe9;          //jmp

        m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(MemFunToStdCallThunk)));
        ::FlushInstructionCache( ::GetCurrentProcess(), this, sizeof(MemFunToStdCallThunk) );
        return TRUE;
    }

    void* GetCodeAddress() {
        return this;
    }
};
#pragma  pack( pop )

下面是需要回调的成员函数:

long ProcessBarProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

将thunk中的结构体声明为一个成员变量:

MemFunToStdCallThunk m_thunk;

设置系统钩子,也就是回调函数的设置:

m_thunk.Init(UnionCastType<DWORD_PTR>(&ProcessBar::ProcessBarProc), this);

SetWindowLongPtr(this->m_pbHwnd, GWL_WNDPROC, (LONG_PTR)m_thunk.GetCodeAddress());

posted on 2011-08-06 20:44  itprograms  阅读(1236)  评论(2编辑  收藏  举报