MFC自定义消息发送机制及CString对象作为消息发送(我误认为PostMessage发了多次,其实没有)
发布日期:2021-06-30 18:20:44 浏览次数:2 分类:技术文章

本文共 2220 字,大约阅读时间需要 7 分钟。

MFC编程中经常需要在不同的对话框(类)之间发送消息以实现数据共享或流程控制,最简单的方法当然是使用全局变量在不同的类之间共享数据,但如果数据量很大的话,这种方法显得不是那么高效;特别是当我们需要在不同的对话框之间实现逻辑流程控制的时候,首选的方法应该是发送自定义消息。这周的项目里用到了这部分知识,做个总结。

MFC中使用自定义消息需要经过以下步骤;

  1. 在B类的头文件(B.h)中定义消息

    1

    #define WM_MY_UPDATE WM_USER+100

    网上的帖子说自定义消息至少是WM_USER+100,因为100以内可能是VC中很多控件的消息使用。

  2.  在B的实现文件(B.cpp)中实现消息处理函数

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    LRESULT CShowResult::OnMyUpdate(WPARAM wParam, LPARAM lParam)

     

    {

     

    CString strUpdate = _T("");

     

    wchar_t * pChar = (wchar_t*)wParam;

     

    strUpdate = CString(pChar);

     

    m_ListBox.AddString(strUpdate);

     

    UpdateData(false);

     

    return 0;

     

    }

    其中CShowResult就是B的类名。

  3. 在类头文件的AFX_MSG块中声明消息处理函数

    1

    afx_msg LRESULT OnMyUpdate(WPARAM wParam, LPARAM lParam);

  4. 在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消息处理函数中。

    1

    2

    3

    4

    5

    BEGIN_MESSAGE_MAP(CShowResult, CDialog)

     

    ON_MESSAGE(WM_MY_UPDATE, OnMyUpdate)

     

    END_MESSAGE_MAP()

完成以上步骤之后,就可以在A.cpp中给B.cpp发送消息了,需要注意的是,消息发送函数是作为B的成员函数出现的。需要在A中定义B类对象的指针,代码如下。

1

pShowRst->SendMessageW(WM_MY_UPDATE,(WPARAM)strRst.GetBuffer(0), 0);

MFC中消息发送函数有两个,SendMessage和PostMessage函数。最好是使用SendMessage函数。

因为PostMessage函数是在发送完消息后立刻返回的,而SendMessage是等待接收消息的窗口处理玩消息后才返回。

如果自定义消息不发送数据,只作为控制指令的话,使用两者没有区别,但是如果通过消息共享数据的话,最好使用

SendMessage函数。因为通过消息机制共享数据的实质是共享某块内存,将内存的指针作为SendMessage函数的参数

进行发送。因此如果使用PostMessage函数,消息发送完毕后函数立即返回,等到消息得到处理时,指针所指的内容

可能已经发生变化,使用SendMessage函数则不会有此问题。

还有一点需要注意的是,如何得到CString对象的指针?需要使用CString对象的GetBuffer函数。

网上讲解该函数的帖子很多,比如

GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。不是什么好地编程习惯,之类的原因。

如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不掉用ReleaseBuffer没什么意义了。

对一个CString变量,你可以使用的唯一合法转换符是LPCTSTR,直接转换成非常量指针(LPTSTR-[const] char*)是错误的。正确的得到一个指向缓冲区的非常量指针的方法是调用GetBuffer()方法。

应用程序里有两个对话框A和B,B是A的非模态子对话框,当A中满足特定条件(比如按下某一按钮)时,弹出对话框B,那么在B的实现类中需要使用A中定义的一些数据。以下是写的代码,A中完成对数据库的查询,B中将查询到的数据进行显示。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

while(!con.pRst->adoEOF)

 

{

 

CString strRst = (_bstr_t)con.pRst->GetCollect("GZFS");

 

//给子对话框发送消息用于显示查询结果

 

pShowRst->SendMessageW(WM_MY_UPDATE,(WPARAM)strRst.GetBuffer(0), 0);

 

strRst.ReleaseBuffer();

 

con.pRst->MoveNext();

 

}

firecat注:

本人在项目实践中,采取PostMessage发送CString,后来发现很多重复的数据,一开始误认为是MFC的bug,PostMessage多发了几次,其实不是的,是因为CString覆盖了前面消息的CString,导致listctrl控件栏显示的数据出现重复的现象。

 

 

转载地址:https://libaineu2004.blog.csdn.net/article/details/90607741 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:开源项目推荐:POCO C++ Libraries大全,含MFC的编译及使用
下一篇:VC++ PreTranslateMessage和WindowProc的使用总结

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月13日 17时12分39秒