MFC消息机制

Windows程序和MFC程序是靠消息驱动的,他们对于消息的处理本质上是相同的。只是Windows程序对于消息处理的过程十分清晰明了,MFC程序则掩盖了消息处理的过程,以消息映射的方式呈现在开发者面前,使得开发消息的处理十分简单。用多了mfc就想对它的消息映射机制有一个本质的了解,下面将对消息映射做详细的分析。当然,在分析MFC消息映射之前首先对Windows程序的消息处理过程进行一个简单的描述。
1、Windows应用程序消息处理

      Windows程序都维护有自己的消息队列,保存了队列消息(当然也有非队列消息,它们直接发给窗口),并用过消息循环对消息进行处理。消息循环首先通过GetMessage取得消息并从队列中移走,对于加速键会调用TranslateAccelerator函数,对其进行翻译和处理,如果处理成功就不在调用TranslateMessage。如果不是加速键,就进行消息的转换和派发,让目的窗口的窗口过程来处理消息。示例代码:

 while (GetMessage(&msg, NULL, 0, 0))  
 {  
   if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))  
   {  
      TranslateMessage(&msg);  
      DispatchMessage(&msg);  
   }  
 }  
真正处理消息的是所谓的窗口过程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),这个函数的参数记录了过程对应的窗口、消息的ID以及参数,在其内部开发者可以实现自己需要的消息处理功能。那消息分发是如何发送给窗口过程的呢?我们知道窗口创建过程中有一个注册窗口类的步骤,如下:

ATOM MyRegisterClass(HINSTANCE hInstance)  
{  
   WNDCLASSEX wcex;  
  
   wcex.cbSize = sizeof(WNDCLASSEX);  
  
   wcex.style   = CS_HREDRAW | CS_VREDRAW;  
   wcex.lpfnWndProc = WndProc;   // 啊!!!原来在这里  
   wcex.cbClsExtra  = 0;  
   wcex.cbWndExtra  = 0;  
   wcex.hInstance  = hInstance;  
   wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSP));  
   wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);  
   wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);  
   wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDOWSP);  
   wcex.lpszClassName = szWindowClass;  
   wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));  
  
   return RegisterClassEx(&wcex);  
}  

2、MFC消息映射

     MFC窗口使用同一窗口过程,通过消息映射隐藏了消息处理的过程,更加详细点是隐藏了,那消息映射如何实现的呢?

     首先,我们先对MFC的消息映射做一个简单介绍。MFC为了实现消息映射在响应消息的类内部自动做了如下两方面的处理:

     a、消息映射声明和实现

          在类的定义(头文件)里,添加声明消息映射的宏DECLARE_MESSAGE_MAP,在类的实现(源文件)里,通过

          BEGIN_MESSAGE_MAP和END_MESSAGE_MAP()实现消息映射。

     b、消息响应函数的声明和实现

          当通过ClassWizard添加消息响应函数时就会自动添加函数的声明和实现,代码如下:

     声明: 

//{{AFX_MSG  
afx_msg void OnTimer(UINT nIDEvent);  
afx_msg void OnPaint();  
//}}AFX_MSG  
DECLARE_MESSAGE_MAP()  
     映射:

BEGIN_MESSAGE_MAP(CTestDialog, CDialog)  
//{{AFX_MSG_MAP(CTestDialog)  
ON_WM_TIMER()  
ON_WM_PAINT()  
//}}AFX_MSG_MAP  
END_MESSAGE_MAP()  
    实现:

void CTestDialog::OnPaint()   
{  
}  
  
void CTestDialog::OnTimer(UINT nIDEvent)   
{     
    CDialog::OnTimer(nIDEvent);  
}  

3、例子

.h

class DlgClass : public BaseDlg
{
    DECLARE_DYNAMIC(DlgClass)

    enum  {IDD_IDD_DIALOG_sss};
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	virtual void OnOK();
	virtual void OnCancel();
	virtual BOOL OnInitDialog();
	afx_msg void OnCheckContourBold();
	afx_msg void OnCheckContourShowname();

	DECLARE_MESSAGE_MAP()
};
.cpp

#include "DlgBoldContour.h"

IMPLEMENT_DYNAMIC(CDlgBoldContour, jgBaseDialog)

void CDlgBoldContour::DoDataExchange(CDataExchange* pDX)
{
	jgBaseDialog::DoDataExchange(pDX);

	DDX_Control(pDX, IDC_CHECK_CONTOUR_SHOWNAME, m_ShowContourName);
}
BEGIN_MESSAGE_MAP(CDlgBoldContour, jgBaseDialog)
	ON_BN_CLICKED(IDC_CHECK_CONTOUR_BOLD, OnCheckContourBold)
	ON_BN_CLICKED(IDC_CHECK_CONTOUR_SHOWNAME, OnCheckContourShowname)

END_MESSAGE_MAP()
void CDlgBoldContour::OnOK() 
{
...
}









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值