MFC – 消息和事件

MFC – 消息和事件


应用程序由各种对象组成。大多数情况下,计算机上运行着不止一个应用程序,并且不断要求操作系统执行一些任务。因为可能有如此多的请求不可预测地呈现,操作系统将它留给对象来指定它们想要什么、何时想要它以及它们期望什么行为或结果。

概述

  • Microsoft Windows 操作系统无法预测一个对象需要处理什么类型的请求以及另一个对象需要什么类型的分配。

  • 为了管理所有这些分配和请求,对象发送消息。

  • 每个对象都有责任决定发送什么消息以及何时发送。

  • 为了发送消息,控件必须创建一个事件。

  • 为了区分两者,消息的名称通常以 WM_ 开头,WM_ 代表窗口消息。

  • 事件的名称通常以 On 开头,表示动作。

  • 事件是发送消息的动作。

消息地图

由于 Windows 是面向消息的操作系统,因此 Windows 环境的大部分编程都涉及消息处理。每次发生诸如击键或鼠标单击之类的事件时,都会向应用程序发送一条消息,然后应用程序必须处理该事件。

  • 为了让编译器管理消息,它们应该包含在类定义中。

  • 所述DECLARE_MESSAGE_MAP宏应在类定义的结尾被设置为显示在下面的代码。

class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      DECLARE_MESSAGE_MAP()
};
  • 实际消息应列在 DECLARE_MESSAGE_MAP 行上方。

  • 要实现消息,您需要创建一个程序正在使用的消息表。

  • 该表使用两个定界宏;

  • 它以BEGIN_MESSAGE_MAP开始,以END_MESSAGE_MAP结束

  • BEGIN_MESSAGE_MAP 宏采用两个参数,类名和派生类的 MFC 类,如下面的代码所示。

#include <afxwin.h>
class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      DECLARE_MESSAGE_MAP()
};
CMainFrame::CMainFrame() {

   // Create the window's frame
   Create(NULL, L"MFC Messages Demo", WS_OVERLAPPEDWINDOW,
                                      CRect(120, 100, 700, 480), NULL);
}
class CMessagesApp : public CWinApp {
   public:
      BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
END_MESSAGE_MAP()
BOOL CMessagesApp::InitInstance(){
   m_pMainWnd = new CMainFrame;
   m_pMainWnd->ShowWindow(SW_SHOW);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}
CMessagesApp theApp;

让我们通过创建一个新的 Win32 项目来查看一个简单的示例。

Win32 项目

步骤 1 – 要创建 MFC 项目,请右键单击该项目并选择“属性”。

步骤 2 – 在左侧部分,单击配置属性 → 常规。

步骤 3 – 在“项目默认值”部分中选择“在共享 DLL 中使用 MFC”选项,然后单击“确定”。

第 4 步– 我们需要添加一个新的源文件。

第 5 步– 右键单击​​您的项目并选择添加 → 新项目。

步骤 6 – 在模板部分,单击 C++ 文件 (.cpp)。

赢项目

步骤 7 – 单击添加继续。

步骤 8 – 现在,在 *.cpp 文件中添加以下代码。

#include <afxwin.h>
class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      DECLARE_MESSAGE_MAP()
};

CMainFrame::CMainFrame() {
   // Create the window's frame
   Create(NULL, L"MFC Messages Demo", WS_OVERLAPPEDWINDOW,
      CRect(120, 100, 700, 480), NULL);
}

class CMessagesApp : public CWinApp {
   public:
      BOOL InitInstance();
};

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
END_MESSAGE_MAP()
BOOL CMessagesApp::InitInstance() {
   m_pMainWnd = new CMainFrame;
   m_pMainWnd->ShowWindow(SW_SHOW);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}
CMessagesApp theApp;

视窗讯息

有不同类型的 Windows 消息,例如创建窗口、显示窗口等。以下是一些常用的 Windows 消息。

让我们看一个简单的窗口创建示例。

WM_CREATE – 当创建一个称为窗口的对象时,创建对象的框架会发送一条标识为ON_WM_CREATE的消息

步骤 1 – 要创建 ON_WM_CREATE,添加 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 在 DECLARE_MESSAGE_MAP() 之前,如下所示。

class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      DECLARE_MESSAGE_MAP()
};

第 2 步– 在 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 之后和 END_MESSAGE_MAP() 之前添加 ON_WM_CREATE()

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
END_MESSAGE_MAP()

第 3 步– 这是 OnCreate() 的实现

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
   // Call the base class to create the window
   if (CFrameWnd::OnCreate(lpCreateStruct) == 0) {

      // If the window was successfully created, let the user know
      MessageBox(L"The window has been created!!!");
      // Since the window was successfully created, return 0
      return 0;
   }
   // Otherwise, return -1
   return -1;
}

第 4 步– 现在您的 *.cpp 文件将如下面的代码所示。

#include <afxwin.h>
class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      DECLARE_MESSAGE_MAP()
};
CMainFrame::CMainFrame() {

   // Create the window's frame
   Create(NULL, L"MFC Messages Demo", WS_OVERLAPPEDWINDOW,
      CRect(120, 100, 700, 480), NULL);
}
class CMessagesApp : public CWinApp {
   public:
      BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
END_MESSAGE_MAP()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
   // Call the base class to create the window
   if (CFrameWnd::OnCreate(lpCreateStruct) == 0) {
      // If the window was successfully created, let the user know
      MessageBox(L"The window has been created!!!");
      // Since the window was successfully created, return 0
      return 0;
   }
   // Otherwise, return -1
   return -1;
}
BOOL CMessagesApp::InitInstance() { 
   m_pMainWnd = new CMainFrame;
   m_pMainWnd -> ShowWindow(SW_SHOW);
   m_pMainWnd -> UpdateWindow();
   return TRUE;
}
CMessagesApp theApp;

Step 5 – 编译并执行上述代码后,您将看到以下输出。

信息

步骤 6 – 当您单击确定时,它将显示主窗口。

信息

命令信息

图形应用程序的主要功能之一是提供允许用户与机器交互的 Windows 控件和资源。我们将学习的控件示例有按钮、列表框、组合框等。

我们在上一课中介绍的一种资源是菜单。当用户点击它们时,这些控件和资源可以启动它们自己的消息。从 Windows 控件或资源发出的消息称为命令消息。

让我们看一个简单的命令消息示例。

为了让您的应用程序能够创建新文档,CWinApp 类提供了 OnFileNew() 方法。

afx_msg void OnFileNew();

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_COMMAND(ID_FILE_NEW, CMainFrame::OnFileNew)
END_MESSAGE_MAP()

这是方法定义 –

void CMainFrame::OnFileNew() {
   // Create New file
}

键盘信息

键盘是连接到计算机硬件对象。默认情况下,它用于在控件上输入可识别的符号、字母和其他字符。键盘上的每个键都显示一个符号、一个字母或它们的组合,以指示该键的用途。用户通常按下一个键,该键向程序发送信号。

每个键都有一个操作系统可以识别的代码。此代码称为虚拟键代码

按下一个键会导致WM_KEYDOWNWM_SYSKEYDOWN消息被放置在线程消息中。这可以定义如下 –

afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

让我们看一个简单的例子。

步骤 1 – 这是消息。

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
   ON_WM_KEYDOWN()
END_MESSAGE_MAP()

第 2 步– 这是 OnKeyDown() 的实现。

void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
   switch (nChar) {

      case VK_RETURN:
         MessageBox(L"You pressed Enter");
         break;
      case VK_F1:
         MessageBox(L"Help is not available at the moment");
         break;
      case VK_DELETE:
         MessageBox(L"Can't Delete This");
         break;
      default:
         MessageBox(L"Whatever");
   }
}

Step 3 – 编译并执行上述代码后,您将看到以下输出。

消息窗口

步骤 4 – 当您按 Enter 时,它将显示以下消息。

消息输出

鼠标消息

鼠标是连接到计算机的另一个对象,允许用户与机器进行交互。

  • 如果按下鼠标左键,则发送 ON_WM_LBUTTONDOWN 消息。此消息的语法是 –

    • afx_msg void OnLButtonDown(UINT nFlags, CPoint point)

  • 如果按下鼠标右键,则会发送 ON_WM_RBUTTONDOWN 消息。它的语法是 –

    • afx_msg void OnRButtonDown(UINT nFlags, CPoint point)

  • 类似地,如果正在释放鼠标左键,则发送 ON_WM_LBUTTONUP 消息。它的语法是 –

    • afx_msg void OnLButtonUp(UINT nFlags, CPoint point)

  • 如果正在释放鼠标右键,则发送 ON_WM_TBUTTONUP 消息。它的语法是 –

    • afx_msg void OnRButtonUp(UINT nFlags, CPoint point)

让我们看一个简单的例子。

Step 1 – 在 CMainFrame 类定义中添加以下两个函数,如下面的代码所示。

class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
      DECLARE_MESSAGE_MAP()
};

步骤 2 – 添加以下两个消息映射。

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_KEYDOWN()
   ON_WM_LBUTTONDOWN()
   ON_WM_RBUTTONUP()
END_MESSAGE_MAP()

第 3 步– 这是函数定义。

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) { 
   CString MsgCoord;
   MsgCoord.Format(L"Left Button at P(%d, %d)", point.x, point.y);
   MessageBox(MsgCoord);
}
void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point) { 
   MessageBox(L"Right Mouse Button Up");
}

第 4 步– 当您运行此应用程序时,您将看到以下输出。

鼠标消息

步骤 5 – 单击确定后,您将看到以下消息。

鼠标消息

步骤 6 – 右键单击​​此窗口。现在,当您松开鼠标右键时,它将显示以下消息。

鼠标消息

觉得文章有用?

点个广告表达一下你的爱意吧 !😁