Skip to content

Instantly share code, notes, and snippets.

@nibasya
Created May 4, 2020 15:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nibasya/f786b2c36c0a9573f4acb9249bf9b469 to your computer and use it in GitHub Desktop.
Save nibasya/f786b2c36c0a9573f4acb9249bf9b469 to your computer and use it in GitHub Desktop.
A dialog with independent User Interface thread (CWinThread)
void CFactorioFactoryCalculatorDlg::OnCbnSelchangeComboTarget()
{
InitData();
CStatusDlgThread* pThread = DYNAMIC_DOWNCAST(CStatusDlgThread, AfxBeginThread(RUNTIME_CLASS(CStatusDlgThread) , 0, 0, CREATE_SUSPENDED));
// 初期化が必要ならResumeThread()までの間に追加
pThread->m_bAutoDelete = false; // 無効なアクセス防止のため自動削除は無効化
pThread->ResumeThread();
while (pThread->m_Dlg.m_hWnd == 0) { // m_Dlgのウィンドウが生成されるまで待機
Sleep(0);
}
pThread->UpdateStatus(_T("Start adding item to the tree"));
AddNode(pThread); // すごく重い処理
if (!pThread->m_Valid) { // キャンセルボタンが押された場合
InitData();
}
else {
ShowData(); // 正常終了時の軽い処理
pThread->m_Dlg.PostMessage(WM_COMMAND, IDOK); // Statusダイアログを閉じる
}
WaitForSingleObject(pThread->m_hThread, 30000); // スレッドの終了を30秒だけ待ってやる(ほぼ0秒のはず
delete pThread;
}
void CFactorioFactoryCalculatorDlg::AddNode(CStatusDlgThread* pStatus)
{
if (!pStatus->m_Valid) { // キャンセルボタンが押された場合は何もせずに終了
return;
}
for each (auto child in pItem->matName)
{
// 何か処理
AddNode(&m_Item[child], hTree, pStatus); // 再帰呼び出し(重い処理の原因)
}
// Statusを表示
CString buff;
buff.Format(_T("Adding item to tree: %d"), m_CtrlTree.GetCount());
pStatus->UpdateStatus(buff);
}
}
#pragma once
const int ID_UPDATE_STATUS = 40000;
class CStatusDlg : public CDialogEx
{
DECLARE_DYNAMIC(CStatusDlg)
public:
CStatusDlg(CWnd* pParent = nullptr);
virtual ~CStatusDlg();
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG_STATUS };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV Support
DECLARE_MESSAGE_MAP()
public:
CString m_Status;
afx_msg void UpdateStatus();
private:
CEdit m_CtrlEditStatus;
};
#include "pch.h"
#include "FactorioFactoryCalculator.h"
#include "CStatusDlg.h"
#include "CStatusDlgThread.h"
// CStatusDlgThread
IMPLEMENT_DYNCREATE(CStatusDlgThread, CWinThread)
CStatusDlgThread::CStatusDlgThread() : m_Valid(true)
{
}
BOOL CStatusDlgThread::InitInstance()
{
m_pMainWnd = &m_Dlg;
m_Dlg.DoModal();
m_Valid = false; // ダイアログが閉じられたことを通知。m_Dlg.m_hWndでも代用可能か。
return TRUE;
}
void CStatusDlgThread::UpdateStatus(CString status)
{
m_Dlg.m_Status = status;
if (m_Dlg.m_hWnd) { // Statusダイアログが閉じられてしまっていないかチェック後post
m_Dlg.PostMessage(WM_COMMAND, ID_UPDATE_STATUS);
}
}
BEGIN_MESSAGE_MAP(CStatusDlgThread, CWinThread)
END_MESSAGE_MAP()
#pragma once
// CStatusDlgThread
class CStatusDlgThread : public CWinThread
{
DECLARE_DYNCREATE(CStatusDlgThread)
public:
CStatusDlgThread();
virtual BOOL InitInstance();
void UpdateStatus(CString status);
CStatusDlg m_Dlg;
bool m_Valid;
protected:
DECLARE_MESSAGE_MAP()
};
#include "pch.h"
#include "FactorioFactoryCalculator.h"
#include "CStatusDlg.h"
#include "afxdialogex.h"
IMPLEMENT_DYNAMIC(CStatusDlg, CDialogEx)
CStatusDlg::CStatusDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG_STATUS, pParent)
{
}
CStatusDlg::~CStatusDlg()
{
}
void CStatusDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_STATUS, m_CtrlEditStatus);
}
BEGIN_MESSAGE_MAP(CStatusDlg, CDialogEx)
ON_COMMAND(ID_UPDATE_STATUS, UpdateStatus)
END_MESSAGE_MAP()
void CStatusDlg::UpdateStatus()
{
m_CtrlEditStatus.SetWindowText(m_Status);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment