这两天看了看换肤的程序,不大明白:) 也看了看一些相关的文章,但文章写的都是实现过程,程序中连个注释也没有(干着急)
但我想弄明白细节,如 为什么要用到HOOK,怎样实现子类化,子类化中的一些重载的函数
SubclassDlgItem,SubclassWindow(hWnd),SetWindowLong(hWnd, GWL_WNDPROC, (LONG) ProcButton);DrawItem都是什么意思?
大家能否帮帮我,说的细点!谢了先!

解决方案 »

  1.   

    换皮肤主要是子类化的思想。windows是消息系统,当窗口上有事件发生的时候,系统就会发送适当的消息到某个窗口处理过程,如果用自己的窗口处理函数替代了原来的,那么就称为子类化,可以用SetWindowLong修改窗口的处理过程。SubclassDlgItem,SubclassWindow是mfc中CWnd类的函数。
    SubclassDlgItem在内部调用SubclassWindow,这个函数完成3件事情:
    1,在一个内部映射表中将一个窗口句柄和一个CWnd的类对象绑定。他的作用是,当消息发送到一个处理过程的时候(AfxWndProc,后面提到),会将句柄再转换成对应的一个窗口对象,c++的虚拟函数机制能够很好的发挥作用,使和消息有关的一些处理交给用户完成。2,调用PreSubclassWindow虚函数,给用户处理子类化之前的一些工作。3,用SetWindowLong改变原来的窗口处理过程,并替换成AfxWndProc.所以,在mfc框架下,消息都是流入一个函数AfxWndProc中,在这个函数在根据消息的句柄装换成映射表中的窗口对象,由对象来完成消息响应的操作。根据窗口类的继承层次,消息映射表可以利用c++的特性很好的工作,完成对消息的处理。在虚拟函数CWnd::DefWindowProc一般会根据保留的以前的窗口处理过程m_pfnSuper先处理消息。一般,你可以重载这个函数决定是否还调用以前的处理函数,也进行自己的处理。当然,上面只是mfc的处理方式,他和整个mfc的基本机制结合的很紧密。你也可以子类化到自己的处理过程,自己处理消息。关于DrawItem,属于mfc消息反射。消息反射其实是定义了一组标准接口和消息,方便拥有窗口(一般是父窗口)对子窗口的调用。比如,控件需要重画时,发送WM_DRAW消息到父窗口,父窗口会在适当的时候调用控件的某个函数,比如DrawItem. 
      

  2.   

    谢谢 enoloo(努力COM) 啊! 帮我加一下注释好吗?
    LRESULT CALLBACK IRCallWndProc( int nCode, WPARAM wParam, LPARAM lParam )
    {
    PCWPSTRUCT pcs = (PCWPSTRUCT) lParam; //PCWPSTRUCT是什么结构?
    HWND hWnd = pcs->hwnd;    //这里hwnd里存的是什么? if( hWnd ) {
    char sClassName[201] = "\0"; GetClassName( hWnd, sClassName, 200 );//?
    if( strcmp( sClassName, "Button" ) == 0 ) { 
    CWnd *pWnd = CWnd::FromHandle( hWnd );//?
    DWORD dwStyle = pWnd->GetStyle();
    if( dwStyle == 0x50010000 ) { //?
    WNDPROC WndProc;
    WndProc = (WNDPROC) GetWindowLong( hWnd, GWL_WNDPROC );                     //?
    if( CButtonExt::m_cWndProc != NULL &&  WndProc != CButtonExt::m_cWndProc )
    {
    return CallNextHookEx( globalWndHookEx, nCode, wParam, lParam );
    }
    if( WndProc != (WNDPROC) CButtonExt::DefWindowProc ) {
    WndProc = (WNDPROC) SetWindowLong( hWnd, GWL_WNDPROC, (LONG) CButtonExt::DefWindowProc );   //?
    CButtonExt::m_cWndProc = WndProc;
    }
    }
    }
    }
      

  3.   

    这个函数是hook的回调。注释依次为:
    //得到窗口类的类名
    //根据窗口句柄得到该窗口的CWnd
    //如果该窗口的样式等于0x50010000的话
    //把按钮默认的窗口过程替换成CButtonExt::m_cWndProc