头文件:CPictureEx用于显示一个等待动画

#pragma once
#include "afxwin.h" #include "resource.h" #include "PictureEx.h" #include <thread> // CWaitDlg 对话框
class CWaitSingleEvent {
public:
CWaitSingleEvent()
: handle_(nullptr){
handle_ = CreateEvent(nullptr, TRUE, FALSE, nullptr);
} ~CWaitSingleEvent(){
if(handle_) {
CloseHandle(handle_);
}
} operator bool()const{
return handle_ != nullptr;
} int Wait(const DWORD wait_time) {
DWORD retval = ;
if(handle_) {
retval = WaitForSingleObject(handle_, wait_time);
ResetEvent(handle_); }
return retval;
} void Notify() {
if(handle_) {
SetEvent(handle_);
}
} protected:
CWaitSingleEvent(const CWaitSingleEvent& rhs){ } CWaitSingleEvent& operator=(const CWaitSingleEvent& rhs){
return *this;
}
private:
HANDLE handle_;
}; typedef UINT32 (CDialogEx::*WaitToExec)(void* param); class CWaitDlg : public CDialogEx
{
DECLARE_DYNAMIC(CWaitDlg) public:
CWaitDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CWaitDlg(); // 对话框数据
enum { IDD = IDD_DIALOG4 }; //设置执行等待函数
void SetWaitToExec(CWnd* pParent, void* pInnerParam, CDialogEx* pThis, WaitToExec pWaitToExec); private:
void* exec_inner_param_;
CDialogEx* dialog_this;
WaitToExec wait_to_exec_func_pt_; volatile bool is_quit_thread_;
std::thread* wait_to_exec_thread_;
CWaitSingleEvent wait_to_exec_condition_; void wait_to_exec_callback(); protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
CPictureEx m_show_gif_;
virtual void OnCancel();
virtual void OnOK();
};

代码实现:

// WaitDlg.cpp : 实现文件
// #include "stdafx.h"
#include "WaitDlg.h"
#include "afxdialogex.h" // CWaitDlg 对话框 IMPLEMENT_DYNAMIC(CWaitDlg, CDialogEx) CWaitDlg::CWaitDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CWaitDlg::IDD, pParent), wait_to_exec_func_pt_(nullptr), dialog_this(nullptr)
{
is_quit_thread_ = false;
exec_inner_param_ = NULL;
wait_to_exec_thread_ = nullptr;
} CWaitDlg::~CWaitDlg()
{
is_quit_thread_ = true;
wait_to_exec_condition_.Notify(); if (nullptr != wait_to_exec_thread_){
if(wait_to_exec_thread_->joinable()) {
wait_to_exec_thread_->join();
} wait_to_exec_thread_ = nullptr;
}
} void CWaitDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SHOW_GIF, m_show_gif_);
} BEGIN_MESSAGE_MAP(CWaitDlg, CDialogEx)
END_MESSAGE_MAP() // CWaitDlg 消息处理程序
BOOL GetResGifSize(long nResId, LPCTSTR name, long *lnWidth, long *lnHeight)
{
HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(nResId), name);
if (NULL == hRsrc) {
return FALSE;
} DWORD dwSize = SizeofResource(NULL, hRsrc);
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
if (NULL == hGlobal) {
CloseHandle(hRsrc);
return FALSE;
} unsigned char* pBuffer = (unsigned char*)LockResource(hGlobal);
if (NULL == pBuffer) {
CloseHandle(hRsrc);
FreeResource(hGlobal);
return FALSE;
} //判断是否为GIF文件
if(pBuffer[] != 0x47 && pBuffer[] != 0x49 && pBuffer[] != 0x46 && pBuffer[] != 0x38){
return FALSE;
} //读取宽高
for(DWORD i = ; i < dwSize ; i++)
{
if(pBuffer[i] == 0x00 && pBuffer[i+] == 0x2c)
{
*lnWidth = (pBuffer[i+]<<) | pBuffer[i+];
*lnHeight = (pBuffer[i+]<<) | pBuffer[i+];
UnlockResource(hGlobal);
FreeResource(hGlobal);
return TRUE;
}
} UnlockResource(hGlobal);
FreeResource(hGlobal); return FALSE;
} BOOL CWaitDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); //设置窗口大小
long nGifWidth = ;
long nGifHeight = ;
if (!GetResGifSize(IDR_WAIT_GIF_1, _T("GIF"), &nGifWidth, &nGifHeight)){
MessageBox(_T("内部错误"),_T("错误"), MB_OK | MB_ICONERROR);
} RECT rt;
GetClientRect(&rt); //判断窗口是否太大,或者太小,放不下
if ( (rt.right - rt.left - nGifWidth > ) || (rt.bottom - rt.top - nGifHeight > ) ||
(rt.right - rt.left < nGifWidth) || (rt.bottom - rt.top < nGifHeight) ) {
RECT rtWin;
GetWindowRect(&rtWin); //调整窗口大小
rtWin.right = rtWin.left + nGifWidth + ;
rtWin.bottom = rtWin.top + nGifHeight + ;
MoveWindow(&rtWin); //重新获取客户区大小
GetClientRect(&rt);
} CenterWindow(); //计算位置
rt.left = (rt.right - rt.left - nGifWidth)/;
rt.right = rt.left + nGifWidth;
rt.top = (rt.bottom - rt.top - nGifHeight)/;
rt.bottom = rt.left + nGifHeight; //转化成屏幕坐标
//ClientToScreen(&rt);
m_show_gif_.MoveWindow(&rt, TRUE); SetBackgroundColor(RGB(,,), TRUE);
m_show_gif_.SetBkColor(RGB(,,));
if (m_show_gif_.Load(MAKEINTRESOURCE(IDR_WAIT_GIF_1),_T("GIF"))){
m_show_gif_.Draw();
} return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
} void CWaitDlg::wait_to_exec_callback()
{
if(is_quit_thread_) {
return ;
}
while (!is_quit_thread_){ //等待事件是否过来
wait_to_exec_condition_.Wait(INFINITE);
if(is_quit_thread_) {break;} //判断参数是否OK
if ((nullptr != dialog_this) && (nullptr != wait_to_exec_func_pt_)){
(dialog_this ->*wait_to_exec_func_pt_)(exec_inner_param_); //执行完一次,那就隐藏一下
if (NULL != m_hWnd)
{
ShowWindow(SW_HIDE);
}
}
}
} //设置执行等待函数
void CWaitDlg::SetWaitToExec(CWnd* pParent, void* pInnerParam, CDialogEx* pThis, WaitToExec pWaitToExec)
{
exec_inner_param_ = pInnerParam;
dialog_this = pThis;
wait_to_exec_func_pt_ = pWaitToExec; //通知线程执行
is_quit_thread_ = false; if (wait_to_exec_thread_ == nullptr) {
wait_to_exec_thread_ = new std::thread;
}
if(!wait_to_exec_thread_->joinable()) {
*wait_to_exec_thread_ = std::move(std::thread(&CWaitDlg::wait_to_exec_callback, this));
}
//显示本窗口
if (NULL == m_hWnd) {
Create(IDD_DIALOG4, pParent);
} ShowWindow(SW_SHOW); //触发事件
wait_to_exec_condition_.Notify();
} void CWaitDlg::OnCancel()
{
// TODO: 在此添加专用代码和/或调用基类 //CDialogEx::OnCancel();
} void CWaitDlg::OnOK()
{
// TODO: 在此添加专用代码和/或调用基类 //暂时允许关闭
CDialogEx::OnOK();
}

使用示例:

typedef struct set_xxx_info_st {
int index;
CString strXxxInfo;
}set_xxx_info_st; void CXXXParamDlg::OnClickedBtnWriteXxx()
{
CString strXxxC = _T("strXxxC"); // 必须使用堆内存,调用会立即返回,但对象的使用,却在线程中
set_xxx_info_st* inn_param = new set_xxx_info_st;
inn_param->index = m_set_cert_index_combo_.GetCurSel() + ;
inn_param->strXxxInfo.Append(strXxxC); //调用线程接口去获取
m_wait_dlg_.SetWaitToExec(GetParent(), inn_param, this, (WaitToExec)&CXXXParamDlg::WaitToExecSetXXXInfo);
} UINT32 CXXXParamDlg::WaitToExecSetXXXInfo(void* inn_param)
{
UINT32 ulRet = -; set_xxx_info_st* set_param = (set_xxx_info_st*)(inn_param); //禁止父窗口控件
GetParent()->GetParent()->EnableWindow(FALSE); //设置进去
ExecSetXXX(set_param->index, set_param->strXxxInfo); //禁止父窗口控件
GetParent()->GetParent()->EnableWindow(TRUE); if (nullptr != set_param) {
delete set_param;
} return ;
}

MFC下一个通用非阻塞的等待执行结束的对话框类的更多相关文章

  1. CompletionService异步非阻塞获取并行任务执行结果

    第1部分 问题引入 <Java并发编程实践>一书6.3.5节CompletionService:Executor和BlockingQueue,有这样一段话: "如果向Execut ...

  2. 正常断开连接情况下,判断非阻塞模式socket连接是否断开

    摘自:http://blog.chinaunix.net/uid-15014334-id-3429627.html 在UNIX/LINUX下, 1,对于主动关闭的SOCKET, recv返回-1,而且 ...

  3. epoll水平/边缘触发模式下阻塞/非阻塞EPOLLOUT事件触发条件及次数

    在IO多路复用技术中,epoll默认的事件触发模式为Level_triggered(水平触发)模式,即当被监控的文件描述符上有可读/写事件发生时,epoll_wait()会通知处理程序去读写.如果这次 ...

  4. 【MPI学习4】MPI并行程序设计模式:非阻塞通信MPI程序设计

    这一章讲了MPI非阻塞通信的原理和一些函数接口,最后再用非阻塞通信方式实现Jacobi迭代,记录学习中的一些知识. (1)阻塞通信与非阻塞通信 阻塞通信调用时,整个程序只能执行通信相关的内容,而无法执 ...

  5. C#学习笔记之线程 - 高级主题:非阻塞同步

    非阻塞同步 - Nonblock Synchronization 前面提到,即使在简单的赋值和增加一个字段的情况下也需要处理同步.尽管,使用锁可以完成这个功能,但是锁必定会阻塞线程,需要线程切换,在高 ...

  6. php非阻塞执行系统命令

    大家都知道php调用系统命令常用的主要有以下几种方法: 如exec(), system(), passthru(), shell_exec() 这几个函数的用法在此不做说明,有需要的请查阅php相关手 ...

  7. Verilog HDL中阻塞语句和非阻塞语句的区别

    在Verilog中有两种类型的赋值语句:阻塞赋值语句(“=”)和非阻塞赋值语句(“<=”).正确地使用这两种赋值语句对于Verilog的设计和仿真非常重要. Verilog语言中讲的阻塞赋值与非 ...

  8. java并发之非阻塞算法介绍

    在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的. 为了更好的理解阻塞算 ...

  9. Socket阻塞模式和非阻塞模式的区别

    简单点说: 阻塞就是干不完不准回来,    非组赛就是你先干,我现看看有其他事没有,完了告诉我一声 我们拿最常用的send和recv两个函数来说吧... 比如你调用send函数发送一定的Byte,在系 ...

随机推荐

  1. python 二分法实现

    # -*- coding: utf-8 -*- def BinarySearch(arr, key): # 记录数组的最高位和最低位 min = 0 max = len(arr) - 1 if key ...

  2. vscode 黑屏及类名报错解决方案

    1.安装vscode之后打开黑屏,解决方案如下图,右键--属性--兼容性--勾选上 2.vscode 类名总报错 是ES2017的语法修饰器引起vscode警告. 解除的方法如果你使用的typescr ...

  3. ids

    https://www.cnblogs.com/wyt007/p/8309377.html

  4. ID学习一 Basic

    Assignment 作用:定义变量并赋值 变量可以是新定义的也可以是已经存在的: 值可以是另一个变量的值.一个文本值.一个复杂的表达式(利用表达式编辑助手构造): 注意:一旦变量被定义,你不能删除变 ...

  5. Codeforces 931 概率DP

    A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...

  6. GUI学习之三十二—QLCDNumber学习总结

    下面我们来总结一下QLCDNumber的用法 一.描述 QLCDNumber主要用来展示LCD样式的数字,他可以显示几乎任何大小的数字,可以显示十进制,十六进制,八进制或二进制数,也可以展示一些简单的 ...

  7. php 强制类型转换

      123 123.01 array("123",123) true false null (string)  "123" "123.01" ...

  8. 安装后jdk1.8 配置环境变量以后 版本显示还是1.7

    配置图如下   1.7版本不用卸载  不用就可以了

  9. 高考数学九大超纲内容(1)wffc

    我校2016$\thicksim$2017学年度(上期)半期高三(理科)考试第12题 已知奇函数\(f(x)\)的定义域是\((-1,0)\bigcup\hspace{0.05cm}(0,1)\),\ ...

  10. webpack中require.context 用法

    1.require.context(directory, useSubdirectories = false, regExp = /^\.\//) Examples: require.context( ...