1、创建子线程

C++创建线程的方式比较多

1)最简单易用的<thread>头文件,但是这种方法创建的子线程中无法给主线程PostMessage消息(也可能是我操作有误,总之没成功)

2)3)4)参见VC创建线程的三种方法https://blog.csdn.net/u014568921/article/details/44262645

第3、4种用在MFC程序中貌似也不行,多次尝试之下我用了AfxBeginThread()方法成功了

void CMFCDLLTestDlg::OnBnClickedMessage()
{
// TODO: 在此添加控件通知处理程序代码
// 启动websocket线程
AfxBeginThread((AFX_THREADPROC)MsgThread, (VOID*)this, THREAD_PRIORITY_NORMAL, , , NULL);
}

我这里是在一个按钮点击事件中启动了一个websocket线程,全局线程函数MsgThread()

2、通过自定义消息创建窗口

在MFC程序中,在子线程中直接调用Create()方法无法创建非模态窗口,貌似子线程的循环阻塞了创建过程,所以需要用自定义消息方法通知主线程来创建

2.1 自定义消息

MFC自定义消息其实不难,分三个步骤

1、定义一个消息ID

我的程序名叫MFCDLLTestDlg,所以在MFCDLLTestDlg.cpp中定义下一个消息ID

#define TEST_SENDMSG WM_USER+200//给消息一个ID

2、定义消息处理函数

消息处理函数是用来处理收到的自定义消息的,这个有两种方法,可以通过类向导添加一个自定义消息处理,或者自己手写也行,使用类向导可以直接绑定,省了第三步

类向导方式:切换到类试图--->类向导--->消息--->添加自定义消息,然后输入自定义的消息ID和处理函数名称就好了

手写方式和类向导一样,反正消息ID必须是自己定义的,固定WM_USER+一个数,不重复就行

然后再头文件中声明消息处理函数,注意在对话框主类中写

afx_msg LRESULT OnTestSendmsg(WPARAM wParam, LPARAM lParam);

然后在cpp中定义

LRESULT CMFCDLLTestDlg::OnTestSendmsg(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case TEST_SENDMSG:
CMsgWindow * p_MsgWindow = new CMsgWindow();
p_MsgWindow->SetSkin(MAKEINTRESOURCE(IDB_BITMAP1));
//p_MsgWindow->SetSkin(MAKEINTRESOURCE(IDB_BITMAP2));
//p_MsgWindow->SetSkin(MAKEINTRESOURCE(IDB_BITMAP3)); CString *cmsg = (CString *)lParam; if (!p_MsgWindow->Create(m_hWnd, _T("通知")))
{
AfxMessageBox(L"Create Failed!"); return -;
}
p_MsgWindow->SetMsg(L"高仿QQ新闻右下角弹窗", *cmsg, L"http://blog.csdn.net/jackystudio");
p_MsgWindow->Show();
break;
} return LRESULT();
}

这里我是在收到消息后弹了个窗,有兴趣的访问一下这个 http://blog.csdn.net/jackystudio 博客,我从这里找的漂亮的弹窗程序

注意这个函数的两个参数[ WPARAM wParam, LPARAM lParam ],这个是可以自己类型转换的,常用的可能就是这种,第一个参数为消息类型,第二个参数为字符串,整数等其他参数,这里是个Cstring字符串

这两个参数是在PostMessage函数中传进来的,下面会看到

3、添加消息处理映射

有了消息ID和处理函数,还要把两者关联起来,这就是消息映射同样是在主类中操作,找到MESSAGE_MAP

BEGIN_MESSAGE_MAP(CMFCDLLTestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_WIN_TEXT, &CMFCDLLTestDlg::OnBnClickedWinText)
ON_BN_CLICKED(IDC_NEW_DLG, &CMFCDLLTestDlg::OnBnClickedNewDlg)
ON_BN_CLICKED(IDC_MESSAGE, &CMFCDLLTestDlg::OnBnClickedMessage) ON_MESSAGE(TEST_SENDMSG, &CMFCDLLTestDlg::OnTestSendmsg)
END_MESSAGE_MAP()

可以看到系统消息和按钮点击事件的映射都是在这里的,需要注意的是看清楚是主类的消息映射 BEGIN_MESSAGE_MAP(CMFCDLLTestDlg, CDialogEx) ,我就第一次写在了About类的里面

2.2 发送消息

在子线程函数中用PostMessage发送消息,一般用这个,SendMessage也行,一个同步一个异步

// 省略线程函数其他逻辑
// ...
// 发送消息
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), TEST_SENDMSG, (WPARAM)TEST_SENDMSG, (LPARAM)cmsg);

这里需要注意PostMessage函数加了作用域限定符,否则这个函数有好几个,调用方法不同

第一个参数是主窗口句柄,第二个参数是消息ID,第三、四个参数对应上面消息处理函数的两个参数

然后当发送消息函数被执行的时候,窗口主线程就会收到消息,执行创建窗口函数

当然只要把消息ID和参数一换,比如说换成某个按钮的点击事件ID或者系统消息ID,就可以做些其他事情了

3、参考文章

C++ Part8 MFC中的AfxBeginThread的使用方法(代码实例)

使用MFC中的AfxBeginThread创建多线程

建立非模态对话框与在线程中建立非模态对话框

MFC SendMessage()函数传递字符串

MFC在子线程中创建窗口(PostMessage方法)的更多相关文章

  1. Windows:子线程中创建窗口

    一般来讲,UI的所有操作都必须在主线程,否则会出现未知错误.但有时候我们会需要一个功能比较单一的窗口,同时希望他在一个单独的线程运行.并不影响主线程的效率. 下面说明一下新建子线程创建的新窗口的方法, ...

  2. C# 在窗体的子线程中创建新窗体

    在子线程中如果简单的调用新窗体的话,新出来的窗体会直接一闪而过.没有停留.效果很差 具体解决方法 如下: 在母窗体中建立委托 public delegate void setShowChartForm ...

  3. C# 在子线程中创建不会阻塞执行窗体

    可以参考”C# 对 Windows 窗体控件进行线程安全调用“一文来看. 在做网络连接程序的时候碰到一个问题:每当连接到来时,都创建一个新的接收线程,而该接收线程在接收到消息时,可以创建一个新的对话窗 ...

  4. 业务代码中(java class)中如何实现多线程,并且将子线程中的值随方法返回返回值

    转载自http://bbs.csdn.net/topics/390731832 问题: public static String getAddress(final InputStream inputS ...

  5. android 不能在子线程中更新ui的讨论和分析

    问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...

  6. Android--Handler的用法:在子线程中更新界面

    本文主要介绍Android的Handler的用法.Handler能够发送Messsage和Runnable对象到与其相关联的线程的消息队列. 每一个Handler对象与创建它的线程相关联.而且每一个H ...

  7. [转]MFC子线程中更新控件内容的两种办法

    一.概述 每个系统中都有线程(至少都有一个主线程),而线程最重要的作用就是并行处理,提高软件的并发率.针对界面来说,还能提高界面的响应能力.一般的,为了应用的稳定性,在数据处理等耗时操作会单独在一个线 ...

  8. 【转载】Delphi7从子线程中发送消息到主线程触发事件执行

    在对数据库的操作时,有时要用一个子线程来进行后台的数据操作.比如说数据备份,转档什么的.在主窗口还能同是进行其它操作.而有时后台每处理一个数据文件,要向主窗口发送消息,让主窗口实时显示处理进度在窗口上 ...

  9. Android中不能在子线程中更新View视图的原因

    这是一条规律,很多coder知道,但原因是什么呢? 如下: When a process is created for your application, its main thread is ded ...

随机推荐

  1. linux 内核模块开发相关的文章搜集和模块开发过程中的小技巧

    最近需要开发一些内核模块,进行探究linux内核的一些特征,现在把一些遇到的比较好的文章和知识点,进行简要记录和备忘: 内核模块开发相关链接: https://www.thegeekstuff.com ...

  2. fish 设置环境变量;fish shell 相关使用说明记录;

    最近使用 fish进行工作,发现环境变量忘记如何设置: fish 环境变量保存在两个地方: ~ 目录下,.config/fish 目录下: /etc/fish/ 目录下 如果配置所有用户都能用的环境变 ...

  3. Android开发之adt bundle安装

    这个学期开了一门手机游戏开发的课,所以就接触到了adt bundle,Android开发环境有三种方式,分别是JDK+SDK+Eclipse+ADT.JDK+adt-bundle与JDK+Androi ...

  4. OpenCV检测Marker位姿

    Marker检测采用小觅相机,可以实时检测Marker的位置和姿态,效果如下: 参考代码如下: #include "pch.h" #include <Eigen/Dense& ...

  5. tp 框架 文本编辑器 不解析HTML标签

    解析 文本编辑器  空格 {$vo.content|htmlspecialchars_decode|stripslashes|html_entity_decode}

  6. C语言 putchar

    C语言 putchar putchar主要功能是输出一个char.可以根据ASLL号码输出对应字符 案例 #define _CRT_SECURE_NO_WARNINGS #include <st ...

  7. P1832题解 A+B Problem(再升级)

    万能的打表 既然说到素数,必须先打素数表筛出素数, 每个素数可以无限取,这就是完全背包了. 这次打个质数表: bool b[1001]={1,1,0,0,1,0,1,0,1,1,1,0,1,0,1,1 ...

  8. 工作中遇到的js跨域问题总结

    起因:之前在做一个项目的时候有这样一个问题,127.0.0.1域名上的一个页面A.html,需要访问127.0.0.2域名上B.html页面中的一个方法.这就涉及到JS跨域访问了,通过查阅资料,得以解 ...

  9. 8组 上课啦(Class BUddy Pro)使用体验

    下载上课啦app 进入页面显示的是一个第1周的课表,和可以看到本周为第几周,点击周可以调整第几周显示课表 ,课表内容为整周内容,本周内容一目了然.点击右上角可以进入主设置页面,设置页面可以设置静音模式 ...

  10. 破解版 Teamver 安装

    一 .下载安装包 百度网盘链接:https://pan.baidu.com/s/18nEKAMmHEqU66Dq_aCnEYQ 提取码:2x2q 二.解压缩后,直接运行红框内绿色文件即可