📄 pshit.cpp
字号:
#include "stdafx.h"
#include "resource.h"
#include "PShit.h"
#include "PictureEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Pass structure shit to worker threads
class CProgressInfo : public CObject
{
public:
CProgressInfo();
CProgressDlg* m_pStatusDlg;
FUNCTION_WITH_PROGRESS* m_pfnFunction;
void* m_pData;
CEvent* m_pDialogInitComplete;
DECLARE_DYNAMIC(CProgressInfo)
};
UINT ProgressDialogWorkerThread(LPVOID pParam);
IMPLEMENT_DYNAMIC(CProgressInfo, CObject)
CProgressInfo::CProgressInfo()
{
m_pStatusDlg = NULL;
m_pfnFunction = NULL;
m_pData = NULL;
m_pDialogInitComplete = NULL;
}
IMPLEMENT_DYNAMIC(CProgressDlg, CDialog)
CProgressDlg::CProgressDlg(BOOL bShowCancelButton, BOOL bConfirmCancel, CWnd* pParent)
: CDialog(IDD_PROGRESS_DLG, pParent)
{
//{{AFX_DATA_INIT(CProgressDlg)
//}}AFX_DATA_INIT
m_nCurrentPercentage = 0;
m_bReady = FALSE;
m_bCancelled = FALSE;
m_bShowCancelButton = bShowCancelButton;
if (bConfirmCancel)
ASSERT(m_bShowCancelButton);
m_bConfirmCancel = bConfirmCancel;
m_bOkToClose = FALSE;
m_pThread = NULL;
m_pDialogInitCompleted = NULL;
}
void CProgressDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CProgressDlg)
DDX_Control(pDX, IDC_PIC_PROGRESS, m_PicProgress);
DDX_Control(pDX, IDC_PROGRESS, m_ctrlProgress);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CProgressDlg, CDialog)
//{{AFX_MSG_MAP(CProgressDlg)
ON_BN_CLICKED(IDC_CANCEL, OnCancelled)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CProgressDlg::OnInitDialog()
{
//Let parent class do its thing
CDialog::OnInitDialog();
//Too short a process for animation!
//if (m_PicProgress.Load(MAKEINTRESOURCE(IDR_GIF2),_T("GIF"))) {
// m_PicProgress.Draw();
//}
//Initialise progress control and remember the start time
m_ctrlProgress.SetRange(0, 100);
m_ctrlProgress.SetPos(0);
m_TimeCreation = CTime::GetCurrentTime();
m_bReady = TRUE;
//Set caption if need be
if (!m_sCaption.IsEmpty())
SetWindowText(m_sCaption);
//Signal event to signify that dialog has initialized
ASSERT(m_pDialogInitCompleted);
m_pDialogInitCompleted->SetEvent();
return TRUE;
}
void CProgressDlg::OnCancel()
{
m_PicProgress.Stop();
if (m_bOkToClose)
CDialog::OnCancel();
else if (m_bShowCancelButton)
{
if (m_bConfirmCancel)
{
//Worker thread needs to be suspended while we are displaying confirm cancel message box
ASSERT(m_pThread);
m_pThread->SuspendThread();
if (AfxMessageBox(m_sConfirmPrompt, MB_YESNO) == IDYES)
m_bCancelled = TRUE;
m_pThread->ResumeThread();
}
else
m_bCancelled = TRUE;
}
}
void CProgressDlg::OnOK()
{
//deliberately do nothing
}
void CProgressDlg::Close()
{
m_PicProgress.Stop();
m_bOkToClose = TRUE;
PostMessage(WM_CLOSE);
}
void CProgressDlg::OnCancelled()
{
m_PicProgress.Stop();
OnCancel();
}
void CProgressDlg::SetPercentageDone(int Percentage)
{
if (!m_bReady || m_nCurrentPercentage == Percentage)
return;
m_ctrlProgress.SetPos(Percentage);
m_nCurrentPercentage = Percentage;
if (Percentage) //avoid division by 0
{
long lSecondsLeft = ((CTime::GetCurrentTime() - m_TimeCreation).GetTotalSeconds() * (100 - Percentage)) / Percentage;
CTimeSpan TimeLeft = CTimeSpan(lSecondsLeft);
int Minutes = TimeLeft.GetMinutes();
int Seconds = TimeLeft.GetSeconds();
CString sVal;
CString sText;
if (Minutes)
{
sVal.Format(_T("%d"), Minutes);
AfxFormatString1(sText, IDS_PSHIT_TIMELEFT_IN_MINUTES, sVal);
}
else
{
if (Seconds)
{
sVal.Format(_T("%d"), Seconds);
AfxFormatString1(sText, IDS_PSHIT_TIMELEFT_IN_SECONDS, sVal);
}
else
{
//if 0 seconds are left then display no text
sText = CString(_T(""));
}
}
ASSERT(GetDlgItem(IDC_TIMELEFT));
GetDlgItem(IDC_TIMELEFT)->SetWindowText(sText);
}
}
BOOL ShowProgressDlg( FUNCTION_WITH_PROGRESS* pfnFunction,
const CString& sProgressTitle,
void* pData, DWORD dwFlags,
const CString& sConfirmPrompt,
int nPriority,
CWnd* pParent )
{
BOOL bShowCancel = (dwFlags & PSHIT_CANCEL);
BOOL bConfirmCancel = (dwFlags & PSHIT_CONFIRMCANCEL);
//Create progress dialog and set its various flags
CProgressDlg dlg(bShowCancel, bConfirmCancel, pParent);
dlg.m_sCaption = sProgressTitle;
dlg.m_sConfirmPrompt = sConfirmPrompt;
CProgressInfo Info;
Info.m_pStatusDlg = &dlg;
Info.m_pfnFunction = pfnFunction;
Info.m_pData = pData;
CEvent DialogInitCompleted;
Info.m_pDialogInitComplete = &DialogInitCompleted;
dlg.m_pDialogInitCompleted = &DialogInitCompleted;
//Create worker thread (initally suspended)
CWinThread* pThread = AfxBeginThread(ProgressDialogWorkerThread,
&Info,
nPriority,
0,
CREATE_SUSPENDED);
//Fail if thread failed to create itself
if (!pThread)
{
ASSERT(FALSE);
return FALSE;
}
//We are in charge of deletion of thread
pThread->m_bAutoDelete = FALSE;
//Store away worker thread pointer in dialog
dlg.m_pThread = pThread;
//Resume wortker thread
pThread->ResumeThread();
//bring up dialog modal (thread will close it for us)
dlg.DoModal();
//Wait for worker thread to exit immediately
ASSERT(pThread);
WaitForSingleObject(pThread->m_hThread, INFINITE);
delete pThread;
return !dlg.HasBeenCancelled();
}
UINT ProgressDialogWorkerThread(LPVOID pParam)
{
CProgressInfo* pInfo = (CProgressInfo*) pParam;
ASSERT(pInfo);
ASSERT(pInfo->IsKindOf(RUNTIME_CLASS(CProgressInfo)));
//Call user defined function
ASSERT(pInfo->m_pfnFunction);
pInfo->m_pfnFunction(pInfo->m_pData, pInfo->m_pStatusDlg);
//Wait until progress dialog is initialised before we try to close it
ASSERT(pInfo->m_pDialogInitComplete);
WaitForSingleObject(*pInfo->m_pDialogInitComplete, INFINITE);
//Close progress dialog
ASSERT(pInfo->m_pStatusDlg);
pInfo->m_pStatusDlg->Close();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -