zoukankan      html  css  js  c++  java
  • 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 = 0;
            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[0] != 0x47 && pBuffer[1] != 0x49 && pBuffer[2] != 0x46 && pBuffer[3] != 0x38){
            return FALSE;
        }
    
        //读取宽高
        for(DWORD i = 4; i < dwSize ; i++)
        {
            if(pBuffer[i] == 0x00 && pBuffer[i+1] == 0x2c)
            {
                *lnWidth = (pBuffer[i+7]<<8) | pBuffer[i+6];
                *lnHeight = (pBuffer[i+9]<<8) | pBuffer[i+8];
                UnlockResource(hGlobal);
                FreeResource(hGlobal);
                return TRUE;
            }
        }
    
        UnlockResource(hGlobal);
        FreeResource(hGlobal);
    
        return FALSE;
    }
    
    BOOL CWaitDlg::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
    
        //设置窗口大小
        long nGifWidth = 75;
        long nGifHeight = 75;
        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 > 64) || (rt.bottom - rt.top - nGifHeight > 64) ||
             (rt.right - rt.left < nGifWidth) || (rt.bottom - rt.top < nGifHeight) ) {
            RECT rtWin;
            GetWindowRect(&rtWin);
    
            //调整窗口大小
            rtWin.right = rtWin.left + nGifWidth + 64;
            rtWin.bottom = rtWin.top + nGifHeight + 64;
            MoveWindow(&rtWin);
    
            //重新获取客户区大小
            GetClientRect(&rt);
        }
    
        CenterWindow();
    
        //计算位置
        rt.left = (rt.right - rt.left - nGifWidth)/2;
        rt.right = rt.left + nGifWidth;
        rt.top = (rt.bottom - rt.top - nGifHeight)/2;
        rt.bottom = rt.left + nGifHeight;
    
        //转化成屏幕坐标
        //ClientToScreen(&rt);
        m_show_gif_.MoveWindow(&rt, TRUE);
    
        SetBackgroundColor(RGB(240,240,240), TRUE);
        m_show_gif_.SetBkColor(RGB(240,240,240));
        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() + 1;
        inn_param->strXxxInfo.Append(strXxxC);
    
        //调用线程接口去获取
        m_wait_dlg_.SetWaitToExec(GetParent(), inn_param, this, (WaitToExec)&CXXXParamDlg::WaitToExecSetXXXInfo);
    }
    
    UINT32 CXXXParamDlg::WaitToExecSetXXXInfo(void* inn_param)
    {
        UINT32 ulRet = -1;
    
        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 0;
    }
  • 相关阅读:
    hihoCoder#1128 二分·二分查找
    hihoCoder#1127 二分图三·二分图最小点覆盖和最大独立集
    hihoCoder#1122 二分图二•二分图最大匹配之匈牙利算法
    hihoCoder#1105 题外话·堆
    Ajax详细剖析
    web框架之--Tornado
    web框架之--先来个介绍
    前端之--Jquery-玩穿它!
    前端之--DOM详解应用
    前端之--JavaScript作用域--超细讲解
  • 原文地址:https://www.cnblogs.com/eaglexmw/p/11404965.html
Copyright © 2011-2022 走看看