头文件: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. There are multiple modules with names that only differ in casing. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.

    There are multiple modules with names that only differ in casing.This can lead to unexpected behavio ...

  2. [易学易懂系列|golang语言|零基础|快速入门|(三)]

    接下来,我们主要讲讲package. 先列举下go的package的一些核心特性: 1.go的package不局限于一个文件,组成一个package的多个文件,编译后实际上和一个文件类似,组成包的不同 ...

  3. git如何将本地文件关联到远程服务器

    很多时候,当我们关联git服务器的时候,本地都有可能会有一些开发的东西需要同步上去.那怎么样设置同步呢!跟我来做,简易配置: git本地关联远程项目:      第一步:选择目录           ...

  4. 爱奇艺免费vip观看地址

    本人qq群也有许多的技术文档,希望可以为你提供一些帮助(非技术的勿加). QQ群:   281442983 (点击链接加入群:http://jq.qq.com/?_wv=1027&k=29Lo ...

  5. 借用的对vue-cli配置对解析

  6. div拖拽到iframe上方 导致 缩放和拖拽的不平滑和鼠标事件未放开 解决方法

    思路一:用在开始进行缩放(触发了resizable的start事件)为iframe添加z-index属性,将iframe放置在最下层. $("#draggable").resiza ...

  7. R 画散点图

    ggplot(data=df, aes(x=n, y=rt, group=kernel, shape=kernel, colour=kernel)) + geom_point(fill="w ...

  8. centos apache2.4.6 apache https配置

    错误描述: SSL 接收到一个超出最大准许长度的记录. 错误代码:SSL_ERROR_RX_RECORD_TOO_LONG 原因: root@iZwz93telmwbh624e5zetqZ:~# ap ...

  9. nginx 缓存设置

    浏览器缓存原理 浏览器缓存 HTTP协议定义的缓存机制(如:Expires:Cache-control等) 2.浏览器无缓存 3.客户端有缓存 校验过期机制 校验是否过期                ...

  10. .NET(c#) 移动APP开发平台 - Smobiler(2) - 平台介绍

    看到大家很多人在后台问我一些问题,所以准备写一个系列了,下面给个目录 目录: .NET(c#) 移动APP开发平台 - Smobiler(1) 环境的搭建及上手第一个应用 类似开发WinForm的方式 ...