MFC下一个通用非阻塞的等待执行结束的对话框类
头文件: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下一个通用非阻塞的等待执行结束的对话框类的更多相关文章
- CompletionService异步非阻塞获取并行任务执行结果
第1部分 问题引入 <Java并发编程实践>一书6.3.5节CompletionService:Executor和BlockingQueue,有这样一段话: "如果向Execut ...
- 正常断开连接情况下,判断非阻塞模式socket连接是否断开
摘自:http://blog.chinaunix.net/uid-15014334-id-3429627.html 在UNIX/LINUX下, 1,对于主动关闭的SOCKET, recv返回-1,而且 ...
- epoll水平/边缘触发模式下阻塞/非阻塞EPOLLOUT事件触发条件及次数
在IO多路复用技术中,epoll默认的事件触发模式为Level_triggered(水平触发)模式,即当被监控的文件描述符上有可读/写事件发生时,epoll_wait()会通知处理程序去读写.如果这次 ...
- 【MPI学习4】MPI并行程序设计模式:非阻塞通信MPI程序设计
这一章讲了MPI非阻塞通信的原理和一些函数接口,最后再用非阻塞通信方式实现Jacobi迭代,记录学习中的一些知识. (1)阻塞通信与非阻塞通信 阻塞通信调用时,整个程序只能执行通信相关的内容,而无法执 ...
- C#学习笔记之线程 - 高级主题:非阻塞同步
非阻塞同步 - Nonblock Synchronization 前面提到,即使在简单的赋值和增加一个字段的情况下也需要处理同步.尽管,使用锁可以完成这个功能,但是锁必定会阻塞线程,需要线程切换,在高 ...
- php非阻塞执行系统命令
大家都知道php调用系统命令常用的主要有以下几种方法: 如exec(), system(), passthru(), shell_exec() 这几个函数的用法在此不做说明,有需要的请查阅php相关手 ...
- Verilog HDL中阻塞语句和非阻塞语句的区别
在Verilog中有两种类型的赋值语句:阻塞赋值语句(“=”)和非阻塞赋值语句(“<=”).正确地使用这两种赋值语句对于Verilog的设计和仿真非常重要. Verilog语言中讲的阻塞赋值与非 ...
- java并发之非阻塞算法介绍
在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的. 为了更好的理解阻塞算 ...
- Socket阻塞模式和非阻塞模式的区别
简单点说: 阻塞就是干不完不准回来, 非组赛就是你先干,我现看看有其他事没有,完了告诉我一声 我们拿最常用的send和recv两个函数来说吧... 比如你调用send函数发送一定的Byte,在系 ...
随机推荐
- wamp2.5最简单的虚拟主机配置
1.配置host文件 2.配置httpd.conf 去掉# LoadModule rewrite_module modules/mod_rewrite.so Include conf/extra/ht ...
- 远程连接mysql出现1130的错误
数据库权限不足 连接数据以后执行以下命令 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '您的数据库密码' WITH GRANT OP ...
- CentOS 7 环境下部署 SVN 并实现自动更新(版本库放在Tomcat下)
1.安装 SVN 1.1先检查是否有安装 svn rpm -qa subversion #没有什么显示就说明没有安装过yum remove subversion #如果有安装就运行删除老版本yum i ...
- 034-openstack中虚拟机启动后主机名设置问题
openstack中虚拟机启动后主机名设置问题,在centos7中设置hostname后怎么都是原来的hostname,根本无效. 方法一: 在centos7中除了修改hosts文件和network文 ...
- CPU指令重排序与MESI缓存一致性
一.重排序场景 class ResortDemo { int a = 0; boolean flag = false; public void writer() { a = 1; //1 flag = ...
- css3-文字与字体
1. 给文字添加阴影---text-shadow 语法: text-shadow: X-Offset Y-Offset blur color; X-Offset:表示阴影的水平偏移距离,其值为正值时阴 ...
- MYSQL数据导出与导入,secure_file_priv参数设置
https://www.imooc.com/article/41883 MySQL 报错 [Code: 1290, SQL State: HY000] The MySQL server is run ...
- MySQL数据库的自动备份与数据库被破坏后的恢复(3)
[2] 当数据库被修改后的恢复方法 数据库被修改,可能存在着多方面的原因,被入侵.以及相应程序存在Bug等等,这里不作详细介绍.这里将只介绍在数据库被修改后,如果恢复到被修改前状态的方法. 具体和上面 ...
- RN组件的生命周期
来自:http://www.devio.org/tags/#React%20Native
- 使用distinct消除重复记录的同时又能选取多个字段值
需求是:我要消除name字段值重复的记录,同时又要得到id字段的值,其中id是自增字段. select distinct name from t1 能消除重复记录,但只能取一个字段,现在要同时取id, ...