// ProgressDialog.h
#ifndef __PROGRESS_DIALOG_H
#define __PROGRESS_DIALOG_H
#include "../../../Windows/Synchronization.h"
#include "../../../Windows/Thread.h"
#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/ProgressBar.h"
#include "ProgressDialogRes.h"
class CProgressSync
{
NWindows::NSynchronization::CCriticalSection _cs;
bool _stopped;
bool _paused;
UInt64 _total;
UInt64 _completed;
public:
CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {}
HRESULT ProcessStopAndPause();
bool GetStopped()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
return _stopped;
}
void SetStopped(bool value)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
_stopped = value;
}
bool GetPaused()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
return _paused;
}
void SetPaused(bool value)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
_paused = value;
}
void SetProgress(UInt64 total, UInt64 completed)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
_total = total;
_completed = completed;
}
void SetPos(UInt64 completed)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
_completed = completed;
}
void GetProgress(UInt64 &total, UInt64 &completed)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
total = _total;
completed = _completed;
}
};
class CU64ToI32Converter
{
UInt64 _numShiftBits;
public:
void Init(UInt64 range)
{
// Windows CE doesn't like big number here.
for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)
range >>= 1;
}
int Count(UInt64 value) { return int(value >> _numShiftBits); }
};
class CProgressDialog: public NWindows::NControl::CModalDialog
{
private:
UINT_PTR _timer;
UString _title;
CU64ToI32Converter _converter;
UInt64 _peviousPos;
UInt64 _range;
NWindows::NControl::CProgressBar m_ProgressBar;
int _prevPercentValue;
bool _wasCreated;
bool _needClose;
bool _inCancelMessageBox;
bool _externalCloseMessageWasReceived;
bool OnTimer(WPARAM timerID, LPARAM callback);
void SetRange(UInt64 range);
void SetPos(UInt64 pos);
virtual bool OnInit();
virtual void OnCancel();
virtual void OnOK();
NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
#ifndef _SFX
void AddToTitle(LPCWSTR string);
#endif
bool OnButtonClicked(int buttonID, HWND buttonHWND);
void WaitCreating() { _dialogCreatedEvent.Lock(); }
void CheckNeedClose();
bool OnExternalCloseMessage();
public:
CProgressSync Sync;
int IconID;
#ifndef _SFX
HWND MainWindow;
UString MainTitle;
UString MainAddTitle;
~CProgressDialog();
#endif
CProgressDialog(): _timer(0)
#ifndef _SFX
,MainWindow(0)
#endif
{
IconID = -1;
_wasCreated = false;
_needClose = false;
_inCancelMessageBox = false;
_externalCloseMessageWasReceived = false;
if (_dialogCreatedEvent.Create() != S_OK)
throw 1334987;
}
INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0)
{
_title = title;
INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent);
thread.Wait();
return res;
}
enum
{
kCloseMessage = WM_APP + 1
};
virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
void ProcessWasFinished()
{
WaitCreating();
if (_wasCreated)
PostMessage(kCloseMessage);
else
_needClose = true;
};
};
class CProgressCloser
{
CProgressDialog *_p;
public:
CProgressCloser(CProgressDialog &p) : _p(&p) {}
~CProgressCloser() { _p->ProcessWasFinished(); }
};
#endif