消息映射、循环机制是Windows程序运行的基本方式。VC++ MFC 中有许多现成的消息句柄,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难。在MFC ClassWizard中不允许添加用户自定义消息,所以我们必须在程序中添加相应代码,以便可以象处理其它消息一样处理自定义消息。通常的做法是采取以下步骤:
第一步:定义消息。
推荐用户自定义消息至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。
#define WM_MY_MESSAGE (WM_USER+100) |
第二步:实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT。
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam) { // TODO: 处理用户自定义消息 ... return 0; } |
第三步:在类头文件的AFX_MSG块中说明消息处理函数:
class CMainFrame:public CMDIFrameWnd { ... // 一般消息映射函数 protected: // {{AFX_MSG(CMainFrame) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnTimer(UINT nIDEvent); afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //}}AFX_MSG DECLARE_MESSAGE_MAP() } |
第四步:在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消息处理函数中。
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_WM_TIMER() ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage) //}}AFX_MSG_MAP END_MESSAGE_MAP()
如果用户需要一个定义整个系统唯一的消息,可以调用SDK函数RegisterWindowMessage定义消息:
static UINT WM_MY_MESSAGE=RegisterWindowMessage("User"); |
并使用ON_REGISTERED_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步骤同上。
当需要使用自定义消息时,可以在相应类中的函数中调用函数PostMessage或SendMessage发送消息PoseMessage(WM_MY_MESSAGE,O,O); 如果向其他进程发送消息可通过如下方法发送消息:
DWORD result; SendMessageTimeout(wnd->m_hWnd, // 目标窗口 WM_MY_MESSAGE, // 消息 0, // WPARAM 0, // LPARAM SMTO_ABORTIFHUNG | SMTO_NORMAL, TIMEOUT_INTERVAL, &result); |
以避免其它进程如果被阻塞而造成系统死等状态。
可是如果需要向其它类(如主框架、子窗口、视类、对话框、状态条、工具条或其他控件等)发送消息时,上述方法显得无能为力,而在编程过程中往往需要获取其它类中的某个识别信号,MFC框架给我们造成了种种限制,但是可以通过获取某个类的指针而向这个类发送消息,而自定义消息的各种动作则在这个类中定义,这样就可以自由自在的向其它类发送消息了。
下面举的例子叙述了向视类和框架类发送消息的方法:
在主框架类中向视类发送消息:
视类中定义消息:
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //定义消息映射 视类定义消息处理函数:
// 消息处理函数 LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam) { // TODO: 处理用户自定义消息 ... return 0; }
//发送消息的测试函数 void CMainFrame::OnTest() { CView * active = GetActiveView();//获取当前视类指针 if(active != NULL) active->PostMessage(WM_MY_MESSAGE,0,0); } |
在其它类中向视类发送消息:
//发送消息的测试函数 void CMainFrame::OnTest() { CMDIFrameWnd *pFrame; CMDIChildWnd *pChild; CView *pView; //获取主窗口指针 pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd; // 获取子窗口指针 pChild = (CMDIChildWnd *) pFrame->GetActiveFrame(); //获取视类指针 pView = pChild->GetActiveView(); if(pView != NULL) pView->PostMessage(WM_MY_MESSAGE,0,0);//发送消息 } |
其余步骤同上。
在视类中向主框架发送消息:
首先在主框架中定义相关的消息,方法同上,然后在发送消息的函数中添加代码如下
//发送消息的测试函数 void CMessageView::OnTest() { CFrameWnd * active = GetActiveFrame();//获取当前主窗口框架指针 if(active != this) active->PostMessage(WM_MY_MESSAGE,0,0); return 0; } |
在其它类中向不同的类发送消息可依次方法类推,这样我们的程序就可以的不受限制向其它类和进程发送消息,而避免了种种意想不到的风险。
下面一个例子程序为多文档程序里在一对话框中向视类发送消息,详述了发送自定义消息的具体过程。
实现步骤:
第一步:在VC++中新建工程Message,所有ClassWizard步骤选项均为缺省,完成。
第二步:在主菜单中添加测试菜单为调出对话框,在框架类中建立相应函数OnTest()
第三步:在资源中建立对话框,通过ClassWizard添加新类TestDialog,添加测试按钮,
在对话框类中建立相应函数OnDialogTest()
//通过对话框按钮发送消息的函数 void TestDialog::OnDialogTest() { CMDIFrameWnd *pFrame; CMDIChildWnd *pChild; CView *pView; //获取主窗口指针 pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd; // 获取子窗口指针 pChild = (CMDIChildWnd *) pFrame->GetActiveFrame(); //获取视类指针 pView = pChild->GetActiveView(); if(active != NULL) active->PostMessage(WM_MY_MESSAGE,0,0);//发送消息 } |
在Message.h头文件中添加如下语句:
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message"); |
第四步:在视类中添加自定义消息:
在头文件MessageView.h中添加消息映射
protected: //{{AFX_MSG(CMessageView) //}}AFX_MSG afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //此行为添加代码 DECLARE_MESSAGE_MAP() 在视类文件MessageView.cpp中的消息映射中添加自定义消息映射 BEGIN_MESSAGE_MAP(CMessageView, CView) //{{AFX_MSG_MAP(CMessageView) //}}AFX_MSG_MAP // Standard printing commands ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //此行添加代码定义唯一消息 END_MESSAGE_MAP() |
添加相应的0消息处理函数
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam) { CRect rect; GetClientRect(&rect); InvalidateRect(&rect); test=!test; return 0; } |
在MessageView.h中添加布尔变量 public:BOOL test;
在视类构造函数中初始化 test变量:test=FALSE;
修改CMessageView::OnDraw()函数
void CMessageView::OnDraw(CDC* pDC) { CMessageDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // 以下程序显示消息响应效果 if(test) pDC->TextOut(0,0,"消息响应!"); } |
第五步:显示测试对话框
在MainFrame类中包含对话框头文件:
#include "TestDialog.h"; OnTest()函数中添加代码 void CMainFrame::OnTest() { TestDialog dialog; dialog.DoModal(); } |
运行程序,在测试菜单打开对话框,点击测试按钮即可看到结果。
|
分享到:
相关推荐
以下是如何在MFC中自由使用自定义消息的详细步骤: 1. **定义消息**: 自定义消息通常定义为`WM_USER`值之上,以避免与系统或已存在的控件消息冲突。例如,可以定义如下: ```cpp #define WM_MY_MESSAGE (WM_...
本文将深入探讨如何在MFC框架中利用`CToolBar`类来自定义工具栏,包括设置按钮的图片和文字,以及实现工具栏的自由停靠功能。 `CToolBar`是MFC中用于创建和管理工具栏的类,它包含了多个按钮,每个按钮可以包含图像...
首先,标题"好用的mfc自定义控件"暗示我们将讨论如何在MFC环境中创建和使用自定义控件。MFC自定义控件是开发者为了满足特定需求而设计的,它们可以扩展标准的Windows控件,或者完全原创。自定义控件通常涉及到继承...
文件"MFC中自由使用自定义消息.doc"可能涉及如何在MFC程序中添加和处理自定义消息。自定义消息可以扩展MFC的内置消息系统,使得开发者能根据需求创建特定的消息,以处理串口通信中的特殊事件。 总的来说,通过MFC...
这篇文章将深入探讨如何在Visual Studio C++环境中使用MFC来创建自定义按钮,以及相关的编程技术和策略。 首先,我们需要理解MFC的基本结构。MFC封装了Windows API,提供了类库来处理窗口、消息、控件等,使得C++...
3. **自定义消息处理**:除了使用默认的布局管理,还可以在OnSize()函数中添加自定义代码,根据需要调整控件的位置和大小。 4. **控件的最小和最大尺寸**:有时需要限制控件的最小和最大尺寸,以防止它们在窗口大小...
创建自定义窗口类时,应在BEGIN_MESSAGE_MAP宏中指定CWnd作为基类,并在窗口的构造函数中使用AfxRegisterWndClass来注册WNDCLASS,最后通过CreateEx方法创建窗口。这种方法摆脱了框架窗口的限制,适用于需要更灵活...
本篇将详细探讨如何使用MFC来实现自定义绘制ListControl控件,包括选中行颜色变化、行间距调整以及字体大小设置等功能。 ListControl控件,也称为ListView,是Windows GUI中常用的一种控件,用于展示多列数据,并可...
在MFC(Microsoft Foundation Class)库中,开发人员可以利用其强大的图形用户界面(GUI)功能来实现各种自定义的绘图操作。本教程将详细解释如何在MFC应用程序中实现点击鼠标自由绘制箭头的功能。 首先,我们需要...
在这个MFC项目中,我们讨论的是如何利用Bresenham算法来实现自定义的画线功能。 Bresenham算法是由Jack E. Bresenham于1965年提出的,它是一种快速且精确的在像素网格上绘制直线的方法。该算法主要适用于离散的、...
8. **多线程支持**:如果在多线程环境中使用自定义MessageBox,需要注意线程同步问题,以防止UI线程被阻塞。 9. **代码复用**:为了提高代码的可维护性和重用性,可以将自定义MessageBox封装成一个静态类或实例类,...
在MFC中,我们可以使用`CSplitterWnd`类来实现这种功能,这是一个预定义的控件,专用于创建可分割的窗口。然而,对话框中的分隔条控件可能需要一些额外的处理,因为对话框不直接支持`CSplitterWnd`。 步骤1:创建...
为了在对话框中使用这个自定义的`CEditEx`控件,我们需要在`EditDemoDlg.cpp`和`EditDemoDlg.h`中进行相应的修改。在`EditDemoDlg.h`中添加`CEditEx`的成员变量,并在`OnInitDialog()`中初始化: ```cpp class ...
我们可以通过重载CWnd类或自定义控件类的消息映射函数来处理这些消息。 1. **WM_LBUTTONDOWN**:当用户点击控件时,我们需要记录下鼠标点击时的坐标(ptStart),并设置一个标志位表示拖动开始。例如: ```cpp void...
在MFC(Microsoft Foundation Classes)框架中,`CStatic`控件是最常用的一种控件,通常用于显示静态文本。然而,MFC默认的`CStatic`控件的背景颜色是灰色,这可能不符合某些应用程序的设计需求。为了实现自定义背景...
6. **性能优化**:为了提高效率,你可以在自绘过程中使用内存位图缓存,先将绘制结果保存在内存中,然后在`WM_PAINT`消息处理中快速复制到屏幕,避免频繁的GDI操作。 在`testMyOwerTab`这个文件中,我们可以找到...
3. **事件通知**:使用MFC的`ON_NOTIFY`消息映射条目,可以当一个视图中的事件发生时通知其他视图。例如,一个视图可能触发一个通知,另一个视图接收到该通知后更新自身。 4. **数据对象和剪贴板**:通过创建一个...
在MFC中,我们通常使用对话框(Dialog)类和控件(Control)类来构建用户界面,而按钮(Button)是其中最常见的控件之一。本篇文章将深入探讨如何在MFC应用中实现一个形状非传统的按钮,特别是将其形状改变为三角形...
本话题聚焦于"MFC鼠标拖动按钮"这一技术,这通常涉及到自定义控件和消息处理,使得用户可以通过鼠标左键在界面上自由拖动一个按钮。 首先,实现鼠标拖动按钮的核心在于重载MFC中的几个关键函数。在MFC中,CButton类...
当窗口需要重绘时,系统会发送WM_PAINT消息,此时我们可以在这个消息的处理函数中进行自定义的绘制工作。`CProgressCtrl`是MFC中用于处理进度条控件的类,但默认情况下,它不支持颜色的自定义。为了改变这一情况,...