利用SendMessage()函数从Frame类向View类发送自定义消息

 

Windows程序是事件驱动的,操作系统将每个事件记录在一条消息中。Windows程序必须包含专门处理这些消息的函数。在VC下,消息响应函数一般是通过找到相应的message,添加现成的消息相应函数实现的。但至少两种情况下,无法实现这样的处理。1、系统没有你需要的这种消息;2、产生消息和处理消息不在同一个线程里。比如你想在CView类里处理一条在CFrame类里产生的Edit控件发生改变的消息,并得到Edit中的文本内容。通常是利用GetWindowText ()函数来实现,但是这个函数GetWindowText cannot retrieve the text of a control in another application.

这时我们就可以利用SendMessage()函数从框架里发送消息,然后在视图中接收并处理。函数原型为:

LRESULT SendMessage(      

    HWND hWnd,

    UINT Msg,

    WPARAM wParam,

    LPARAM lParam

);

其中hWnd :Handle to the window whose window procedure will receive the message.就是目标视图CView的句柄。

Msg: Specifies the message to be sent.

wParam:Specifies additional message-specific information.

lParam: Specifies additional message-specific information.

 

Msg是消息类型,可以是自定义的和。wParamlParam是消息的附加信息。

这样,我们首先要做的,就是在框架里得到目标视图的句柄。

 view类属于框架管理的窗口类,构造函数是受保护的,无法直接创建实例。即使要在框架类里使用试图类对象的功能,也应该定义一个指针,并为其赋值。即先通过AfxGetMainWnd()函数获得主框架的指针pMainFrame, 然后从pMainFrame->GetActiveView()得到当前视图的指针(如果是SDI的话)。有了当前视图指针,就可以利用这个指针调用SendMessage()函数。注意,这时调用的SendMessage只有三个参数:Msg、wParamlParam默认句柄为调用该函数的指针所带句柄,即当前视图句柄。语句如下:

CMainFrame*   pMainFrame   =   dynamic_cast<CMainFrame*>(::AfxGetMainWnd());  

if   (pMainFrame   !=   NULL)  

{  

          CGLEasyView *pIFView   =   dynamic_cast<CGLEasyView*>(pMainFrame->GetActiveView()); 

          pIFView->SendMessageA(WM_INTEGRATION_TIME_CHANGE, 0L, 0L);

 }

这里利用了类和类的指针间转化用的C++风格转化符dynamic_cast。

其中WM_INTEGRATION_TIME_CHANGE就是自定义的消息,需要在视图类头文件里添加宏定义

#define WM_INTEGRATION_TIME_CHANGE WM_USER+1

当然,如有更多的自定义消息,也可接着

#define WM_YOUR_MESSAGE WM_USER+2

然后,在框架类的cpp文件中添加包含视图类头文件,我这里是

#include "gleasvw.h"

这时如果编译的话,会出现类似以下编译错误。

error C2065: 'CGLEasyDoc' : undeclared identifier

说明文档类未知。这时需要在视图类头文件中包含文档类,由于这不是继承关系,而且是互相包含,所以,在视图类头文件中要以声明的方式取代头文件包含,添加这样一条语句以加入文档类:

class CGLEasyDoc;

具体可参见reference webpages中的“C++中基础类互相引用带来的问题”。这样就告诉编译器,这是文档类的一个实际调用,不用再次进行包含和编译。

此时,发消息的工作完成,该做消息接受处理的工作。

消息处理函数经常被称作WndProc()或WindowProc(),不过该函数不必拥有特定的名称,因为Windows是利用我们提供的函数指针访问该函数的。所以这里有两种方法进行消息接收处理。

一、重写WindowProc虚函数,即首先在视图类头文件中添加声明:

            protected:

            virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam);

然后在cpp文件中加入该虚函数的实现:

LRESULT CGLEasyView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

            switch(message)

            {

            case WM_INTEGRATION_TIME_CHANGE:

                        //add your code here

                        return 0;

            default:

                        LRESULT lResult = 0;

                        if (!OnWndMsg(message, wParam, lParam, & lResult))

                        lResult = DefWindowProc(message, wParam, lParam);

                        return lResult;

            }

}

这里要注意,在我们筛选自己要处理的消息后,记着把其余消息回传给Windows,仍以其原来默认的方式去处理,否则将发现应用程序没有了诸如最小化、响应鼠标等功能。这是靠调用DefWindowProc()函数实现的。即上段代码中的

lResult = DefWindowProc(message, wParam, lParam);

二、或者用第二种方法,自己添加消息响应函数。先在视图类头文件中声明消息响应函数:

protected:

            //{{AFX_MSG(CGLEasyView)

            afx_msg LRESULT IntegrationTimeChange(WPARAM wParam,LPARAM lParam);

            //}}AFX_MSG

            DECLARE_MESSAGE_MAP()

然后在视图类cpp文件中BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间插入以下代码

BEGIN_MESSAGE_MAP(CGLEasyView, CView)

            //{{AFX_MSG_MAP(CGLEasyView)

            //指定自定义消息WM_INTEGRATION_TIME_CHANGE的消息响应函数指针

            ON_MESSAGE(WM_INTEGRATION_TIME_CHANGE,IntegrationTimeChange)

            //}}AFX_MSG_MAP

END_MESSAGE_MAP()

最后在视图类cpp文件中添加函数定义即可:

LRESULT CGLEasyView::IntegrationTimeChange(WPARAM wParam,LPARAM lParam)

{

            //add your code here

            return 0;

}

Reference webpages:

SDI中如何获得视图VIEW的句柄?http://topic.csdn.net/t/20040908/09/3350490.html

在MFC类中各种类的指针的获取和应用: http://www.chinaitpower.com/A/2005-04-26/133533.html

MDI中使用GetActiveView:http://topic.csdn.net/t/20060222/09/4569740.html

http://topic.csdn.net/t/20020328/16/606708.html

如何使用SendMessage自定义消息函数:http://winterisnotcold.blog.hexun.com/30151239_d.html

C++中基础类互相引用带来的问题:http://blog.csdn.net/sumless/articles/855694.aspx

对于VC++中的头文件包含值得注意的一点:http://blog.csdn.net/sumless/archive/2006/05/07/711965.aspx

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值