当前位置:网站首页>二、MFC窗口和消息
二、MFC窗口和消息
2022-07-23 17:44:00 【[T]】
一、钩子函数
钩子函数,具有优先获取消息(如键盘、鼠标消息)能力,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边栏推荐
- You must execute multiple requests and catch errors. Using try catch is not elegant
- Terminal command (all)
- Alibaba's latest masterpiece! It took 187 days for the liver to come out. 1015 pages of distributed full stack manuals are so delicious
- AE tutorial, how to animate illustrator layered documents in after effects?
- 【leetcode天梯】链表 · 206 反转链表
- 【C语言】程序环境和预处理
- 时代潮头,华为将风帆对准数字金融的风与海
- LeetCode刷题:回文数
- Little fish sends lidar | just dinner is the first lottery
- [shutter -- layout] flexible layout (flex and expanded)
猜你喜欢

MySQL数据库【数据库基础--引入篇】

【leetcode天梯】链表 · 022 链表中倒数第k个节点

DHCP:在网络中防止 Rogue DHCP Server

时代潮头,华为将风帆对准数字金融的风与海

Source code analysis of ThreadPoolExecutor

ACM MM 2022 Oral | DIG: 自监督文字识别的新框架,刷新11个公开场景文字数据集的识别性能,平均提升5%...

What content does the software test plan include and how to write it. Share test plan template

国外芯片,为什么有中文资料和网页?

Lendingclub loan status business details current, charge off, issued, full paid, grace period

进程调度的基本过程
随机推荐
Shell
图学习总结
Summary of smart data corresponding to some topics
Lendingclub loan status business details current, charge off, issued, full paid, grace period
(CVPR-2022)BiCnet
数据链路层 -------- 以太网 和 ARP
elk筆記25--快速體驗APM
LeetCode刷题:回文数
R语言筛选dataframe指定的数据列、R语言排除(删除)dataframe中的指定数据列(变量)
Why are there Chinese materials and web pages for foreign chips?
Elk note 25 - expérience rapide APM
What is the difference between preamplifier and power amplifier?
人脸识别系统技术方案
PHP file lock lottery to prevent concurrency
Mbio | the sun Chaomin formation of Ocean Institute has verified in situ the new pathway of microbial mediated elemental sulfur formation in the deep sea
基於FPGA的UART接口設計
Mee | Zhejiang University Chenglei group develops a new method for designing and constructing synthetic flora
还在用Xshell?你out了,推荐一个更现代的终端连接工具
[shutter -- layout] flexible layout (flex and expanded)
R语言使用quantile函数计算向量数据或者dataframe指定数据列的分位数(百分位数)