二、MFC窗口和消息

一、钩子函数

        钩子函数,具有优先获取消息(如键盘、鼠标消息)能力,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

代码链接:https://download.csdn.net/download/liutit/86249177

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值