[转]MFC子线程更改图像数据后更新主窗口图像显示方法

程序思路是由外部的输入输出控制卡发出采集图像信号,之后相机采集图像得到图像数据指针,接收图像数据指针创建成图像最后显示到MFC对话框应用程序的Picture Control控件上,同时,为了标定相机位置,在主对话框类CMyDlg的OnPaint函数中有对Picture Control的绘图操作(不改变图像数据,进行画线,画矩形等操作)。

设计时考虑到I/O卡何时发出采集信号或者相机何时得到图像数据指针是不确定的(不使用OnTime),同时考虑到I/O卡和相机的回调函数与主程序之间的数据交换会更加困难(不在回调函数里处理结果),所以创建多线程Dectect函数,I/O卡或者相机的回调函数仅负责向主程序发送全局的图像数据指针,调用自定义事件的SetEvent函数通知Dectect线程工作。

Dectect线程获得图像数据指针之后无法直接调用CMyDlg的OnPaint函数,Invalidate和Updatedata等函数。

采用自定义消息的方式间接实现功能。将来在工作中肯定会遇到更多的此类情况。实现分为下列七个步骤。

第一步:在stdafx.h增加一个自定义消息宏

#define WM_USER_POSTINVALIDATE WM_USER+500  

第二步:在MyDlg.h中声明一个public类型的成员函数(声明我们自己定义消息的处理函数)

afx_msg LRESULT MyMessage(WPARAM wParam, LPARAM lParam);  

第三步:在CMyDlg类(MyDlg.cpp)的 BEGIN_MESSAGE_MAP(CEE8000Dlg, CDialog) 和 END_MESSAGE_MAP()之间(即类的消息映射表)中添加自定义消息的映射项

ON_MESSAGE(WM_USER_POSTINVALIDATE,MyMessage)  

第四步:在CMyDlg类的实现文件MyDlg.cpp中添加自定义消息的处理函数

LRESULT CMyDlg::MyMessage(WPARAM wParam, LPARAM lParam)
{   

 } 

第五步:之前操作增加的自定义消息函数的目的是为了可以在Dectect线程中调用PostMessage函数,PostMessage作用是将一个指定的消息寄送到指定窗口创建的线程(窗口句柄)的消息队列中。消息已有,接下来需要在Dectect中获得主对话框的窗口句柄。
1、得到主对话框的窗口句柄。常规问题,在CMyDlg的OnInitDialog函数中添加

CWnd *pMainWnd=AfxGetMainWnd();
HWND hMainWnd=pMainWnd->GetSafeHwnd();  

2、将hMainWnd添加到Dectect。比较麻烦,初始尝试把hMainWnd定义成全局变量,调试运行发现hMainWnd在OnInitDialog中正确赋值,运行到Dectect线程函数值就又变为NULL。还尝试在Dectect函数中

CWnd *pMainWnd=AfxGetMainWnd();             //错误方法
HWND hMainWnd=pMainWnd->GetSafeHwnd();           //错误方法  

调试结果运行到Dectect线程函数hMainWnd就又变为NULL。正确的方法又要回到Dectect线程的创建过程中去。

3、Dectect线程创建函数

HANDLE hThreadDectect=CreateThread(NULL,NULL,&Dectect,NULL,NULL,&dwThreadId1);      //错误方法

修改后的Dectect线程创建函数

HANDLE hThreadDectect=CreateThread(NULL,NULL,&Dectect,hMainWnd,NULL,&dwThreadId1);//正确,第四个参数将hMain作为参数传入回调函数

经过这样3步就将主对话框的窗口句柄传递到Dectect线程中了。

第六步:Dectect线程图像数据处理操作完成之后向主对话框线程寄送完成消息,我的程序中相当于通知主对话框进行重绘操作。Dectect线程函数的合适位置:

PostMessage((HWND)pParam,WM_USER_POSTINVALIDATE,0,0);     //pParam就是CreateThread中传递到Dectect的窗口句柄  

第七步:在第四步的函数实现部分中可以直接调用CMyDlg的OnPaint函数,Invalidate和Updatedata等函数了。

记录的自我感觉很详细,方便以后再查阅。同时欢迎各位大神多提宝贵意见。

原文链接:MFC子线程更改图像数据后更新主窗口图像显示方法

参考文献:MFC新线程控制进度条

时间: 2024-11-06 09:17:08

[转]MFC子线程更改图像数据后更新主窗口图像显示方法的相关文章

vc/mfc获取rgb图像数据后动态显示及保存图片的方法

vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw32.lib  链接库 [cpp] view plaincopy //------------------------------设置位图头结构信息---------------------------------------------------------------------- // Setup bm

MFC获取rgb图像数据后动态显示及保存图片的方法

该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw32.lib  链接库 //------------------------------设置位图头结构信息---------------------------------------------------------------------- // Setup bmpinfo structure yourself m_bmpinfo=new BITMAPINFO;

第七章 KinectV2结合MFC显示和处理图像数据(下)

第七章  KinectV2结合MFC显示和处理图像数据(下) 首先声明一下,本系统所使用的开发环境版本是计算机系统Windows 10.Visual Studio 2013.Opencv3.0和Kinect SDK v2.0.这些都可以在百度上找到,download下来安装一下即可. 一.在MFC中如何显示OpenCV的图像Mat 前段时间一直在学习opencv,但学习过程中写的例子都是基于控制台的.今天打算把之前写的一些例子都移植到MFC中,基本上就是复制以前的代码,唯一的区别在于在控制台中,

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

一.概述 每个系统中都有线程(至少都有一个主线程),而线程最重要的作用就是并行处理,提高软件的并发率.针对界面来说,还能提高界面的响应能力.一般的,为了应用的稳定性,在数据处理等耗时操作会单独在一个线程中运行,而所有与主UI线程有关的控件数据刷新应该到主UI线程中处理.也就是数据处理线程发消息,让界面UI去更新控件.在MFC中线程分为界面线程和工作者线程,界面实际就是一个线程画出来的东西,这个线程维护一个"消息队列","消息队列"也是界面线程和工作者线程的最大区别,

多线程 创建子父线程 保证一件事 子线程执行三次后 父线程执行5次 循环10次

package Thread; /** * 创建子父线程 保证一件事 子线程执行三次后 父线程执行5次 循环10次 * 父线程main线程则为Console台项目的主线程 * 在main线程中调用了start线程则为子线程 * */ public class FatherAndSonTest { public static void main(String[] args) { final FatherAndSon fs = new FatherAndSon(); new Thread(new R

Mybatis 插入数据后返回主键值

Oracle中获取刚刚插入记录的主键值: <insert id="insertSelective" parameterType="com.jxxx.p2pp.model.UUserInfo">     <selectKey resultType="java.math.BigDecimal" order="BEFORE" keyProperty="id">    SELECT U_US

Laravel 5 插入数据后返回主键ID

方法一: $info = DB::table('表名')->insertGetId(['imgName' => $fileName]);//图片名入库后返回添加数据行的主键ID 方法二:(适用于Mysql数据库) 执行原生SQL,然后返回新添加的主键ID值 语法:INSERT INTO 表名(字段1, 字段2, 字段3) VALUES (值1, 值2, 值3);SELECT @@IDENTITY AS returnName; #返回刚插入的数据的主键ID并起别名为 "returnNa

RDS for MySQL 删除数据后空间没有减少处理方法

公司的程序和数据库部署在阿里云上,数据库使用的是阿里云的RDS,这天,经理在开发群中发了一个信息: 您的RDS实例rm********0oq的磁盘在过去一周平均使用率已超过80.0%,建议您对实例规格进行升级,以免磁盘资源不足,影响业务运行.详情请您查看您阿里云注册邮箱中的邮件. 1.首先我在Navicat上远程delete阿里云RDS数据表中的数据, 找到对应的表,然后delete 删除部分数据,单个表中的数据达五千万条,所以操作起来很笨重.(懊恼啊,为什么当初没有做分表操作..) 按照产品经

QT多线程的简单使用,主线程发一份数据,子线程收两份数据

先看效果图,示例发送数据“Hello World” 主线程:0x16f54aeda20,另两个子线程分别是0x4f1baff690.0x4f1baff6a0 因为在子线程中加了200ms.400ms延迟,所以打印是有先后顺序的 核心代码也就一丢丢.代码逻辑就是使用信号与槽使用线程之间产生联系 1 MfBusiness::MfBusiness(QObject *parent) : QObject(parent) 2 { 3 connect(&se,&MfSendData::Sgl_Send,