大家在还原子类化时一般都喜欢用以下这种方法
注:pWindowProc是你的窗体函数指针, m_hWnd是窗体句柄
//保存子类化之前的窗体指针,用下面两种方法保存
LONG lwndProc = ::GetWindowLong(m_hWnd, GWL_WNDPROC);
或
LONG lwndProc = ::SetWindowLong(m_hWnd, GWL_WNDPROC, pWindowProc);
然后还原时会这样
::SetWindowLong(m_hWnd, GWL_WNDPROC, lwndProc );//还原
其实这样是对的,只是这个窗体必须只有你一个程序进行了子类化,这样还原才行。
假如你的程序是B 有A程序是别人的
A先子类化窗体,接着是你的B子类化窗体,用上面的方法得到的指针将是A的
不信你可以试试,得到的窗体过程指针就是A用SetWindowLong设置进去的pWindowProc
如果还原时,A先还原(A还原肯定是原始的窗体指针啦),然后你的B再去还原
结果将把A的窗体指针设进去,这样窗体原始指针将得不到真正的还原.
过程如下:
原始指针地址是0x00000001 A程序将要设的窗体指针地址是0x00000002
B程序将要设的是0x00000003
A先子类化用GetWindowLong得到原指针(0x00000001)保存,
将0x00000002用SetWindowLong设进去,
还原时是0x00000001
B窗体再去子类化用GetWindowLong得到原指针(0x00000002)保存,
将0x00000003用SetWindowLong设进去,
还原时是0x00000002
如果A先退出,A在退出时已还原了窗体原始指针(0x00000001),结果在B还原时,又将
指针改成了0x00000002,表面看起来还原啦,其实没有还原
如果0x00000002指向的内存在还好,不存在就会崩啦
最关键的是在子类化和子类化还原时都没办法做到谁先谁后,这都是操作系统控制的。
但目的都是子类化窗体,并在退出时还原到原始窗体指针(0x00000001)
正确的做法是在WM_NCDESTROY里还原子类化,切记不要在HOOK过程的WM_NCDESTROY
中还原,要在子类化过程的WM_NCDESTROY消息中处理,MFC的做法也是这样的,不信你
可以去看MFC中CWnd代码
代码如下:
更多代码:http://bbs.panshsoft.com/read.php?tid=2216
//如果调用这个函数,就不要再调用
//CallWindowProc啦
virtual LRESULT NcDestroy()
{
WNDPROC wndproc = NULL;
LRESULT lReturnValue = 1;
//m_WndOldProc是用GetWindowLong子类化前保存的窗体地址
if(NULL == m_WndOldProc) return 0;
wndproc = (WNDPROC)::GetWindowLong(m_hWnd, GWL_WNDPROC);
//pWindowProc是用SetWindowLong(m_hWnd, GWL_WNDPROC,pWindowProc)设进去的
if(wndproc == (WNDPROC)pWindowProc/*你窗体的指针*/)
{
::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_WndOldProc);
lReturnValue = ::CallWindowProc(m_WndOldProc, m_hWnd,
WM_NCDESTROY, 0, 0);
m_WndOldProc = NULL;
}
else
{
lReturnValue = ::CallWindowProc(m_WndOldProc, m_hWnd,
WM_NCDESTROY, 0, 0);
if(wndproc == (WNDPROC)::GetWindowLong(m_hWnd, GWL_WNDPROC))
{
::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_WndOldProc);
m_WndOldProc = NULL;
}
}
return lReturnValue;
}
代码说明
先判断该窗口的窗体过程指针是否发生过变动,
如果没有的话是最好的,赶紧撤销子类化,
再把消息传递给之前窗口过程,然后退出
如果发生过变动,那么也就是说有别程序在你子类化以后又进行了子类化,
而现在又把WM_NCDESTROY传给了你。
所以把消息继续往前传,
如果窗体过程指针(WNDPROC)又发生了改变,
说明之前的某个窗口过程已经作了处理,
就不需要再进行撤销子类化的操作了。
http://bbs.panshsoft.com/read.php?tid=2216