VC/MFC中如何自定义消息 |
定义一个自定义 信息号:const UINT WM_MYMESSAGE = WM_USER + n; // 自定义 信息一般大于WM_USER, 而后就 可 认为该 信息增加映射了 。 afx_msg LRESULT OnMyMessage ( WPARAM wParam, LPARAM lParam ); ON_MESSAGE ( WM_MYMESSAGE, OnMyMessage ) LRESULT cxx::OnMyMessage ( WPARAM wParma, LPARAM lParam ) { ... } 假如该 信息不需求返回值,也不需求参数,那么 可以 使用宏ON_MESSAGE_VOID来映射 afx_msg void OnMyMessage (); ON_MESSAGE_VOID ( WM_MYMESSAGE, OnMyMessage ) void cxx::OnMyMessage () { ... } 复杂全面版本: 信息映射、循环机制是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(); } 运行程序,在测试菜单 打开对话框,点击测试按钮即可看到 后果 。 |