MFC自定义消息传递,实现子线程更新主窗口数据

最近在写贴吧分布式爬虫项目的客户端,采用了MFC来写。

其中需要后台连接服务器更新在线爬虫列表。这里使用多线程是肯定的,但是如何实现在工作线程里操作主对话框里的数据。

当时想的是在开辟新线程的时候,将主对话框的this指针传递给子线程。

但事实证明,在VS 2015环境下,这种方法并不行,会引发运行时错误(Assertion Failed)。

后面在网上查了一翻关于MFC子线程如何操作主对话框数据的资料,了解到,可以通过在子线程里面传递消息来实现。但是原文里面的方法,在消息映射那里并不行。

后来在MSDN上查了下,终于正确实现子线程传递消息到主对话框,然后,调用相应的函数更新数据。

首先,我们要自定义一个我们要传递的消息,在对话框类的头文件中声明:

#define WM_MY_MESSAGE WM_USER+100

然后,我们要声明对应的消息处理函数,即,触发该消息的时候要调用的函数:

//根据MSDN
//函数原型必须如下(对于ON_MESSAGE来说):
afx_msg LRESULT OnMyMessage(WPARAM, LPARAM)
{
//在这里添加处理方法
}

然后,我们当然要实现这个函数,假设读者已经实现了这个函数。

紧接着,我们需要在相应源文件中的消息映射里面添加对应的消息映射,把我们刚刚自定义的消息映射到那个函数去:

BEGIN_MESSAGE_MAP(CLmsTestDlg, CDialog)
……………
……………
ON_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //这是我们添加的消息映射
//消息映射一定要添加到BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间
END_MESSAGE_MAP()

关于为什么用ON_MESSAGE,这个宏是可以处理一切消息的。具体请查阅MSDN

然后,我们在线程函数里面调用PostMessage方法传递消息即可:

//线程函数
UINT myThreadProc(LPRARM lPram)
{
…….
…….
WHAND whand = (WHAND)lPram; //由于PostMessage第一个参数为窗口句柄,所以我们要得到主窗口句柄
::PostMessage(whand,WM_MY_MESSAGE,NULL,NULL); //传递消息

}
在线程函数里面,我们需要传递一个主窗口句柄给PostMessage函数,所以,在调用AfxBeginThread的时候,我们需要传递主窗口的句柄给它。可以通过以下方法获取主窗口句柄:

//在任何位置都可以通过这个方法来取得主窗口句柄
AfxGetMainWnd()->m_hWnd;

至此,我们已经成功的实现了在子线程中完成主窗口数据的更新。

 

参考:

MSDN:https://msdn.microsoft.com/zh-cn/library/k35k2bfs.aspx

CSDN BLOG:http://blog.csdn.net/npu_wy/article/details/28625085

0%