一、钩子函数
钩子函数,具有优先获取消息(如键盘、鼠标消息)能力,MFC内部是通过钩子获取消息的
1、创建钩子函数
//MFC内部会创建钩子,钩子类型为WH_CBT,用于接受MFC消息
HHOOK SetWindowsHookEx(
int idHook, //钩子类型(WH_CBT)
HOOKPROOC lpfn, //钩子处理函数
HINSTANCE hMod, //应用程序实例句柄,NULL:钩取所有消息
DWORD dwThreadId) //线程ID,0:钩取所有线程的消息
2、钩子处理函数
LRESULT CALLBACK CBTProc(
int nCode, //钩子码(HCBT_CREATEWND)
WPARAM WParam, //创建成功的窗口句柄
LPARAM lParam)
二、创建MFC应用
1、创建
2、编写程序
#include <afxwin.h>
class CMyFrameWnd : public CFrameWnd
{
public:
virtual LRESULT WindowProc(UINT msgID, WPARAM wParam, LPARAM lParam);
};
//父类的虚函数,处理消息函数
LRESULT CMyFrameWnd::WindowProc(UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch(msgID)
{
case WM_CREATE:
//创建消息
AfxMessageBox("WM_CREATE 消息被处理");
break;
case WM_PAINT:
//绘图消息
{
PAINTSTRUCT ps={0};
HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
::TextOut(hdc, 100, 100, "绘图消息", strlen("绘图消息"));
::EndPaint(m_hWnd, &ps);
}
break;
}
return CFrameWnd::WindowProc(msgID, wParam, lParam);
}
class CMyWinApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
CMyFrameWnd* pFrame = new CMyFrameWnd;
pFrame->Create(NULL, "MFCCreate");
m_pMainWnd = pFrame;
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return TRUE;
}
CMyWinApp theApp;
程序框架与继承关系
3、窗口创建过程
CMyFrameWnd* pFrame = new CMyFrameWnd;
pFrame->Create(NULL, "MFCCreate")//函数内部this为pFrame(自己new框架类对象地址)
{
//加载菜单
CreateEx(..., NULL,...)//函数内部this为pFrame
{
CREATESTRUCT cs;
....
cs.lpszClass = NULL;//下面将更改
...
cs.hInstance = AfxGetInstanceHandle();
PreCreateWindow(cs)
{
AfxDeferRegisterClass(...)
{
WNDCLASS wndcls;
...
wndcls.lpfnWndProc = DefWindowProc;//下面将更改
...
_AfxRegisterWithIcon(&wndcls, "AfxFrameOrView100sd"..)
{
&wndcls->lpszClassName = "AfxFrameOrView100sd";
::RegisterClass(&wndcls)
}
}
cs.lpszClass = _afxWndFrameOrView; //"AfxFrameOrView100sd"
}
AfxHookWindowCreate(pFrame)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
//获取全局变量&ccc(当前程序线程信息)
::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook,...);
//利用Win32的API函数,埋下一个类型为WH_CBT的钩子
pThreadState->m_pWndInit = pFrame;
//将自己new的框架类对象pFrame保存到全局变量ccc的一个成员中。
}
::CreateWindowEx(...);//此函数一旦执行成功,立即转到钩子处理函数。
}
}
钩子处理函数
_AfxCbtFilterHook(.wParam.)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();//获取&ccc
CWnd* pWndInit = pThreadState->m_pWndInit;//获取pFrame===pWndInit
HWND hWnd = (HWND)wParam;//刚刚创建成功的框架窗口句柄
pWndInit->Attach(hWnd)//函数内部this为pFrame,参数为窗口句柄
{
CHandleMap* pMap = afxMapHWND(TRUE)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
pState->m_pmapHWND = new CHandleMap(..);
//new了一个映射类对象,并将对象地址保存到bbb的一个成员中
return pState->m_pmapHWND;
//返回映射类对象地址
}
pMap->SetPermanent(m_hWnd = hWnd, pFrame)//函数内部this为pMap
{
m_permanentMap[hWnd] = pFrame;
}
}
(WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,AfxWndProc);
//将窗口处理函数更改为AfxWndProc(才是真正的窗口处理函数)
}
4、消息处理
//以WM_CREATE消息为例,捎带想着点WM_PAINT消息
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd) //通过窗口句柄获取框架窗口对象(pFrame)
{
CHandleMap* pMap = afxMapHWND()
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
return pState->m_pmapHWND;//返回就是之前保存在bbb中的映射类对象地址
}
pWnd = pMap->LookupPermanent(hWnd)//函数内部this为pMap
{
return m_permanentMap[hWnd];//返回的为pFrame
}
}
AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam)//参数pWnd===pFrame
{
pWnd->WindowProc(nMsg, wParam, lParam);//回到自己的代码
}
}
三、消息映射机制
在重写WindowProc虚函数的前提,处理消息
1、类必须具备条件
(1)类内必须添加申明宏:DECLARE_MESSAGE_MAP()
(2)类外必须添加实现宏:
BEGIN_MESSAGE_MAP(theClass, baseClass)
//注册(绑定)消息ID和消息处理函数
END_MESSAGE_MAP()
2、创建新项目
#include <afxwin.h>
class CMyFrameWnd : public CFrameWnd
{
DECLARE_MESSAGE_MAP();
public:
//申明WM_CREATE消息处理函数
LRESULT OnCreate(WPARAM wParam, LPARAM lParam);
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
//注册(绑定)消息ID和处理函数
ON_MESSAGE(WM_CREATE, OnCreate)
END_MESSAGE_MAP()
//实现WM_CREATE消息处理函数
LRESULT CMyFrameWnd::OnCreate(WPARAM wParam, LPARAM lParam)
{
AfxMessageBox("WM_CREATE 消息处理");
return 0;
}
class CMyWinApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
CMyFrameWnd* pFrame = new CMyFrameWnd;
pFrame->Create(NULL, "MFCCreate");
m_pMainWnd = pFrame;
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return TRUE;
}
//应程序入口
CMyWinApp theApp;
3、宏替换
(1)类内申明宏
//DECLARE_MESSAGE_MAP();
protected:
static const AFX_MSGMAP* PASCAL GetThisMessageMap();
virtual const AFX_MSGMAP* GetMessageMap() const;
(2)类外实现宏
//BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
// ON_MESSAGE(WM_CREATE, OnCreate)
//END_MESSAGE_MAP()
PTM_WARNING_DISABLE
const AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const
{
return GetThisMessageMap();
}
const AFX_MSGMAP* PASCAL CMyFrameWnd::GetThisMessageMap()
{
static const AFX_MSGMAP_ENTRY _messageEntries[] =
{
{
{ WM_CREATE, 0, 0, 0, AfxSig_lwl,(AFX_PMSG)(AFX_PMSGW)(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) >(OnCreate)) },
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}
};
};
static const AFX_MSGMAP messageMap =
{
&CFrameWnd::GetThisMessageMap, &_messageEntries[0]
};
return &messageMap;
}
PTM_WARNING_RESTORE