一、窗口的创建
1.加载菜单
2.调用CreateEx函数,设计并注册窗口类,创建窗口
(1)调用PreCreateWindow函数,设计窗口并调用win32API函数::RegisterClass注册窗口类
(2)调用AfxHookWindowCreate函数
利用win32API函数GetWindowHookEx在程序中埋下一个类型为WH_CBT的钩子
将自己new的框架类对象地址(pFrame)保存到当前程序线程信息中
(3)调用win32API函数::CreateWindowEx创建窗口,此函数一旦执行成功立即执行钩子处理函数
3.钩子处理函数
(1)将窗口句柄和自己new的框架类对象(pFrame)建立一对一的绑定关系
pFrame->m_hWnd = hWnd
pMap->m_permanentMap[hWnd] = pFrame ;
(2)利用win32API函数SetWindowLong将窗口处理函数更改为AfxWndProc(正真的窗口处理函数)
二、消息处理
1.当消息产生后进入AfxWndProc函数处理
2.找到和窗口句柄(hWnd)绑定在一起的框架类对象地址(pFrame)
3.利用pFrame调用框架类的成员虚函数WindowProc完成消息处理
补充://埋钩子
HHOOK SetWindowsHookEx( int idHook, //钩子类型(WH_CBT)
HOOKPROC lpfn, //钩子处理函数
HINSTANCE hMod, //应用程序实例句柄,为NULL,所有进程都钩
DWORD dwThreadId); //线程ID,为0,所有线程都钩
//钩子处理函数
LRESULT CALLBACK CBTProc( int nCode, //钩子码(HCBT_CREATEWND)
WPARAM wParam, //附带信息(刚创建成功的窗口句柄)
LPARAM lParam); //附带信息
//更改窗口处理函数
LONG SetWindowLong( HWND hWnd, //窗口句柄
int nIndex, //GWL_WNDPROC
LONG dwNewLong); //新的窗口处理函数
伪代码:
CMyFrameWnd *pFrame = new CMyFrameWnd;
pFrame->Create( NULL, L"MFCCreate" ) //函数内部this为pFrame
{
//先加载菜单
//创建窗口
CreateEx( ..., NULL, ... ) //函数内部this为pFrame
{
CREATESTRUCT cs; //cs中就是CreateWindowEx中的12个参数
......
cs.lpszClass = NULL; //窗口类怎么可能为NULL????????
......
cs.hInstance = AfxGetInstanceHandle(); //拿到WinMain的第一个参数
......
PreCreateWindow( cs )
{
if ( cs.lpszClass == NULL )
{
AfxDeferRegisterClass( ... )
{
WNDCLASS wndcls;
......
wndcls.lpfnWndProc = DefWindowProc; //我们怎么处理消息?????
......
_AfxRegisterWithIcon( &wndcls, L"AfxFrameOrView120sud", ... )
{
&wndcls->lpszClassName = L"AfxFrameOrView120sud";
......
AfxRegisterClass( &wndcls )
{
RegisterClass( &wndcls ); //注册窗口类
}
}
}
cs.lpszClass = _afxWndFrameOrView; // L"AfxFrameOrView120sud"
}
}
AfxHookWindowCreate( pFrame )
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData( ); //获取全局变量(当前程序线程信息)的地址
//利用win32API函数在程序中埋下一个类型为WH_CBT的钩子
::SetWindowsHookEx( WH_CBT, _AfxCbtFilterHook, NULL, ::GetCurrentThreadId( ) );
pThreadState->m_pWndInit = pFrame; //将pFrame(自己new的框架类对象地址)保存到全局变量中
}
::CreateWindowEx( ... ); //此函数一旦执行完成,WM_CREATE消息立即被钩子钩走(钩到钩子处理函数中,_AfxCbtFilterHook)
}
}
*************************************************************************************************************
//钩子处理函数
LRESULT CALLBACK _AfxCbtFilterHook( int code, WPARAM wParam, LPARAM lParam )
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData( ); //获取全局变量(当前程序线程信息)的地址
CWnd* pWndInit = pThreadState->m_pWndInit; //从当前程序线程信息重新获取pFrame
HWND hWnd = (HWND)wParam; //获取刚创建的窗口句柄
pWndInit->Attach( hWnd ) //函数内部this为pFrame
{
CHandleMap* pMap = afxMapHWND( TRUE )
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState( ); //获取全局变量的地址
pState->m_pmapHWND = new CHandleMap( ... ); //new了一个映射类对象,并将对象地址全局变量的成员中
return pState->m_pmapHWND;
}
pMap->SetPermanent( pFrame->m_hWnd = hWnd, pFrame )
{
//函数内部this指针为pMap(映射类对象地址)
pMap->m_permanentMap[hWnd] = pFrame ;
}
}
WNDPROC afxWndProc = AfxGetAfxWndProc( ); //获取AfxWndProc函数地址
//利用win32API函数将窗口处理函数更改为AfxWndProc(真正的窗口处理函数)
oldWndProc = (WNDPROC)SetWindowLongPtr( hWnd, GWLP_WNDPROC, (DWORD_PTR)afxWndProc );
}
*************************************************************************************************************
//以WM_CREATE消息为例,查看消息的处理流程
AfxWndProc( ... )
{
CWnd* pWnd = CWnd::FromHandlePermanent( hWnd ) //获取pFrame
{
CHandleMap* pMap = afxMapHWND( ) //映射类对象
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState( ); //获取管局变量
return pState->m_pmapHWND; //返回全局变量的成员(保存了映射类对象)
}
pWnd = (CWnd*)pMap->LookupPermanent( hWnd ) //函数内部this为映射类对象地址
{
return (CObject*)m_permanentMap.GetValueAt( (LPVOID)hWnd ); //获取下标为窗口句柄的值,即pFrame
}
return pWnd; //返回pFrame
}
return AfxCallWndProc( pWnd, hWnd, nMsg, wParam, lParam ) //参数的pWnd即为pFrame
{
lResult = pWnd->WindowProc( nMsg, wParam, lParam ); //调用虚函数,回到自己的代码
}
}
相关代码:
#include "stdafx.h" #include "T09_MFCCreate.h" class CMyFrameWnd : public CFrameWnd { public: virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); }; //AfxWndProc(真正的窗口处理函数)会调用WindowProc LRESULT CMyFrameWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { //此函数的this为pFram PAINTSTRUCT ps = { 0 }; HDC hdc; switch (message) { case WM_PAINT: hdc = ::BeginPaint((HWND)this->m_hWnd, &ps); ::TextOut(hdc, 100, 100, L"hello", 5); ::EndPaint((HWND)m_hWnd, &ps); break; case WM_CREATE: AfxMessageBox(L"WM_CREATE"); break; } return CFrameWnd::WindowProc(message, wParam, lParam); } class CMyWinApp : public CWinApp { public: virtual BOOL InitInstance(); }; CMyWinApp theApp; BOOL CMyWinApp::InitInstance() { CMyFrameWnd *pFrame = new CMyFrameWnd; pFrame->Create(NULL, L"MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; }
运行结果: