随笔-80  评论-22  文章-0  trackbacks-0

为什么要有消息映射,它的使用是怎样的?

MFC程序是不包括主要函数和时间循环。所有的事件处理都是作为CWinApp的一部分在后台处理的。而消息映射就是识别感兴趣的事件然后调用函数来响应这些事件。

一,首先是正常的程序

// button1.cpp
  #include
  #define IDB_BUTTON 100
  // Declare the application class
  class CButtonApp : public CWinApp
  {
  public:
  virtual BOOL InitInstance();
  };
  // Create an instance of the application class
  CButtonApp ButtonApp;
  // Declare the main window class
  class CButtonWindow : public CFrameWnd
  {
  CButton *button;
  public:
  CButtonWindow();
  };
  // The InitInstance function is called once
  // when the application first executes
  BOOL CButtonApp::InitInstance()
  {
  m_pMainWnd = new CButtonWindow();
  m_pMainWnd->ShowWindow(m_nCmdShow);
  m_pMainWnd->UpdateWindow();
  return TRUE;
  }
  // The constructor for the window class
  CButtonWindow::CButtonWindow()
  {
  CRect r;
  // Create the window itself
  Create(NULL,
  "CButton Tests",
  WS_OVERLAPPEDWINDOW,
  CRect(0,0,200,200));
  // Get the size of the client rectangle
  GetClientRect(&r);
  r.InflateRect(-20,-20);
  // Create a button
  button = new CButton();
  button->Create("Push me",
  WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
  r,
  this,
  IDB_BUTTON);
  }

当你运行代码时,会注意到按钮响应了用户事件。既它加亮了。除此之外它没有做任何事情,因为我们还没有教它怎样去做。我们需要编写消息映射来使按钮做一些感兴趣的事情。

二,建立消息映射

// button2.cpp
  #include
  #define IDB_BUTTON 100
  // Declare the application class
  class CButtonApp : public CWinApp
  {
  public:
  virtual BOOL InitInstance();
  };
  // Create an instance of the application class
  CButtonApp ButtonApp;
  // Declare the main window class
  class CButtonWindow : public CFrameWnd
  {
  CButton *button;
  public:
  CButtonWindow();
  afx_msg void HandleButton(); //
  DECLARE_MESSAGE_MAP()

  };
  // The message handler function
  void CButtonWindow::HandleButton()
  {
  MessageBeep(-1);
  }

  // The message map
  BEGIN_MESSAGE_MAP(CButtonWindow, CFrameWnd)
  ON_BN_CLICKED(IDB_BUTTON, HandleButton)
  END_MESSAGE_MAP()

/*用宏来建立消息映射。在代码中,你可以看见BEGIN_MESSAGE_MAP宏接收两各参数。第一个指定了使用消息映射的类的名称。第二个是基类。然后是ON_BN_CLICKED宏,接受两个参数控制的ID和该ID发送命令消息时所调用的函数。最后,消息映射用END_MESSAGE_MAP来结束。

当用户单击按钮时,它向其包含该按钮的父窗口发送了一个包含其ID的命令消息。那是按钮的缺省行为,这就是该代码工作的原因。按钮向其父窗口发送消息,是因为它是子窗口。父窗口截取该消息并用消息映射来确定所要调用的函数。MFC来安排,只要指定的消息一出现,相应的函数就会被调用。
  ON_BN_CLICKED消息是CButton发送的唯一感兴趣的消息。它等同于CWnd中的ON_COMMAND消息,只是一个更简单方便的同义词而已。*/

  // The InitInstance function is called once
  // when the application first executes
  BOOL CButtonApp::InitInstance()
  {
  m_pMainWnd = new CButtonWindow();
  m_pMainWnd->ShowWindow(m_nCmdShow);
  m_pMainWnd->UpdateWindow();
  return TRUE;
  }
  // The constructor for the window class
  CButtonWindow::CButtonWindow()
  {
  CRect r;
  // Create the window itself
  Create(NULL,
  "CButton Tests",
  WS_OVERLAPPEDWINDOW,
  CRect(0,0,200,200));
  // Get the size of the client rectangle
  GetClientRect(&r);
  r.InflateRect(-20,-20);
  // Create a button
  button = new CButton();
  button->Create("Push me",
  WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
  r,
  this,
  IDB_BUTTON);
  }

上边修改了两个地方,1增加了一个新的成员函数和一个新的表示消息映射的宏。HandleButton函数是正常的c++函数,它通过afx_msg标签确定为消息处理函数。该函数有一些特殊约束,比如它必须是void型并且不能接收任何参数。 DECLARE_MESSAGE_MAP宏建立了消息映射。函数和宏都必须是public型的。

 

对消息映射的理解:

消息映射智能用于MFC。使用消息映射的原因是解决虚拟函数的基本问题。 MFC文件中CWnd类,它包含200多个成员函数,所有成员函数当不使用消息映射都是虚拟的。MFC中大约有近30个类是以CWnd为基类的。这包括所有的可见控制如按钮、静态标签和列表。想象一下,mfc使用虚拟啊和你熟,并且你建立以应用程序包含20个控制.CWnd中200个虚拟函数中每个都需要自己的虚拟函数表,并且一个控制的每个例程都应有一组200个虚拟函数与之关联。则程序可能就有近4000个虚拟函数表在内存中,这对内存有限的及其来书是个大问题,因为其中的大部分是不用的。

消息映射复制了虚拟函数表的操作,但是它是基于需要的基础之上的。消息映射就是对系统说“当你看见一个特殊的消息时,请调用制定的函数”,只有这些函数实际上被重载到消息映射中,就节省二楼内存和cpu的负担。

posted on 2009-07-18 19:23 Bluesea 阅读(522) 评论(0)  编辑 收藏 引用 所属分类: MFC

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理