按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
你设定的一个所谓「滤网函数(filter )」。
请查阅Win32 API 手册中有关于SetWindowsHook 和SetWindowsHookEx 两函数,以获
得更多的hook 信息。(可参考Windows 95 A Developer s Guide 一书第6章Hooks )
MFC 4。x 的hook 动作是在每一个CWnd 衍生类别之对象产生之际发生,步骤如下:
// in WINCORE。CPP (MFC 4。x)
// 请回顾第6章「CFrameWnd::Create产生主窗口」一节
BOOL CWnd::CreateEx(。。。)
{
。。。
PreCreateWindow(cs); // 第6章曾经详细讨论过此一函数。
AfxHookWindowCreate(this);
HWND hWnd = ::CreateWindowEx(。。。);
。。。
}
( )
// in WINCORE。CPP MFC 4。x
void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
{
。。。
pThreadState…》m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT;
_AfxCbtFilterHook; NULL; ::GetCurrentThreadId());
。。。
}
WH_CBT 是众多hook 类型中的一种,意味着安装一个puter…Based Training (CBT )
滤网函数。安装之后,Windows 系统在进行以下任何一个动作之前,会先调用你的滤网
函数:
令一个窗口成为作用中的窗口(HCBT_ACTIVATE )
产生或摧毁一个窗口(HCBT_CREATEWND 、HCBT_DESTROYWND )
最大化或最小化一个窗口(HCBT_MINMAX )
563
…………………………………………………………Page 626……………………………………………………………
第篇 深入 MFC 程式設計
搬移或缩放一个窗口(HCBT_MOVESIZE )
完成一个来自系统菜单的系统命令(HCBT_SYSTEMMAND )
从系统队列中移去一个鼠标或键盘消息 (HCBT_KEYSKIPPED 、
HCBT_CLICKSKIPPED )
因此,经过上述hook 安装之后,任何窗口即将产生之前,滤网函数_AfxCbtFilterHook 一
定会先被调用:
_AfxCbtFilterHook(int code; WPARAM wParam; LPARAM lParam)
{
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
if (code != HCBT_CREATEWND)
{
// wait for HCBT_CREATEWND just pass others on。。。
return CallNextHookEx(pThreadState…》m_hHookOldCbtFilter; code;
wParam; lParam);
}
。。。
if (!afxData。bWin31)
{
// perform subclassing right away on Win32
_AfxStandardSubclass((HWND)wParam);
}
else
{
。。。
}
。。。
LRESULT lResult = CallNextHookEx(pThreadState…》m_hHookOldCbtFilter; code;
wParam; lParam);
return lResult;
}
void AFXAPI _AfxStandardSubclass(HWND hWnd)
{
。。。
// subclass the window with standard AfxWndProc
oldWndProc = (WNDPROC)SetWindowLong (hWnd; GWL_WNDPROC;
(DWORD)AfxGetAfxWndProc ());
}
WNDPROC AFXAPI AfxGetAfxWndProc()
{
564
…………………………………………………………Page 627……………………………………………………………
第9章 訊息映射與命令繞行
。。。
return &AfxWndProc;
}
啊,非常明显,上面的函数合力做了偷天换日的勾当:把「窗口所属之Windows 窗口类
别」中所记录的窗口函数,改换为AfxWndProc 。于是,::DispatchMessage 就把消息源源
推往AfxWndProc 去了。
这种看起来很迂回又怪异的作法,是为了包容新的3D Controls (细节就容我省略了吧),
并与MFC 2。5 兼容。下图把前述的hook 和subclassing 动作以流程图显示出来:
CFrameWnd::LoadFrame
CFrameWnd::LoadFrame
CFrameWnd::Create
CFrameWnd::Create
CWnd::CreateEx
CWnd::CreateEx 安装WH_CBT hook ,设定滤网函数
为_AfxCbtFilterHook
AfxHookWindowCreate(this)
AfxHookWindowCreate(this)
::SetWindowsHookEx(WH_CBT; _AfxCbtFilterHook ;。。。)
::SetWindowsHookEx(WH_CBT; _AfxCbtFilterHook ;。。。)
::CreateWindowEx
::CreateWindowEx
_AfxCbtFilterHook 窗口产生之前一刻,由于曾安装过
_AfxCbtFilterHook WH_CBT hook,所以滤网函数
_AfxCbtFilterHook 会先被唤起。
_AfxStandardSubclass
_AfxStandardSubclass
SetWindowLong(hWnd; GWL_WNDPROC;&AfxWndProc)
SetWindowLong(hWnd; GWL_WNDPROC;&AfxWndProc)
WND structure
subclassing 动作;改 各种消息,来自
变窗口函数。 extra bytes ::DispatchMessage
message mapping and 的唧送,或由操作
mand routing 系统直接送达。
(through message map) CWL_WNDPROC
。
&AfxWndProc
message handler
message handler