• [转]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新线程控制进度条

  • 相关阅读:
    从一个故障说说Java的三个BlockingQueue
    kafka producer源码
    Mock方法介绍
    async4j 普通用法、整合spring用法
    Spring中属性文件properties的读取与使用
    异步框架asyn4j的原理
    如何从线程返回信息——轮询、回调、Callable
    jdk 1.8 Executors
    java Iterator Fail-fast机制
    java的几种对象(PO,VO,DAO,BO,POJO)解释
  • 原文地址:https://www.cnblogs.com/rainbow70626/p/8035162.html
Copyright © 2020-2023  润新知