1 // ProgressDialog2.h 2 3 #ifndef __PROGRESS_DIALOG_2_H 4 #define __PROGRESS_DIALOG_2_H 5 6 #include "../../../Common/MyCom.h" 7 8 #include "../../../Windows/ErrorMsg.h" 9 #include "../../../Windows/Synchronization.h" 10 #include "../../../Windows/Thread.h" 11 12 #include "../../../Windows/Control/Dialog.h" 13 #include "../../../Windows/Control/ListView.h" 14 #include "../../../Windows/Control/ProgressBar.h" 15 16 #include "MyWindowsNew.h" 17 18 struct CProgressMessageBoxPair 19 { 20 UString Title; 21 UString Message; 22 }; 23 24 struct CProgressFinalMessage 25 { 26 CProgressMessageBoxPair ErrorMessage; 27 CProgressMessageBoxPair OkMessage; 28 ThereIsMessageCProgressFinalMessage29 bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); } 30 }; 31 32 class CProgressSync 33 { 34 bool _stopped; 35 bool _paused; 36 37 public: 38 bool _bytesProgressMode; 39 UInt64 _totalBytes; 40 UInt64 _completedBytes; 41 UInt64 _totalFiles; 42 UInt64 _curFiles; 43 UInt64 _inSize; 44 UInt64 _outSize; 45 46 UString _titleFileName; 47 UString _status; 48 UString _filePath; 49 bool _isDir; 50 51 UStringVector Messages; 52 CProgressFinalMessage FinalMessage; 53 54 NWindows::NSynchronization::CCriticalSection _cs; 55 56 CProgressSync(); 57 Get_Stopped()58 bool Get_Stopped() 59 { 60 NWindows::NSynchronization::CCriticalSectionLock lock(_cs); 61 return _stopped; 62 } Set_Stopped(bool val)63 void Set_Stopped(bool val) 64 { 65 NWindows::NSynchronization::CCriticalSectionLock lock(_cs); 66 _stopped = val; 67 } 68 69 bool Get_Paused(); Set_Paused(bool val)70 void Set_Paused(bool val) 71 { 72 NWindows::NSynchronization::CCriticalSectionLock lock(_cs); 73 _paused = val; 74 } 75 Set_BytesProgressMode(bool bytesProgressMode)76 void Set_BytesProgressMode(bool bytesProgressMode) 77 { 78 NWindows::NSynchronization::CCriticalSectionLock lock(_cs); 79 _bytesProgressMode = bytesProgressMode; 80 } 81 82 HRESULT CheckStop(); 83 HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false); 84 85 HRESULT Set_NumFilesTotal(UInt64 val); 86 void Set_NumBytesTotal(UInt64 val); 87 void Set_NumFilesCur(UInt64 val); 88 HRESULT Set_NumBytesCur(const UInt64 *val); 89 HRESULT Set_NumBytesCur(UInt64 val); 90 void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize); 91 92 void Set_TitleFileName(const UString &fileName); 93 void Set_Status(const UString &s); 94 HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false); 95 void Set_FilePath(const wchar_t *path, bool isDir = false); 96 97 void AddError_Message(const wchar_t *message); 98 void AddError_Message_Name(const wchar_t *message, const wchar_t *name); 99 void AddError_Code_Name(DWORD systemError, const wchar_t *name); 100 ThereIsMessage()101 bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } 102 }; 103 104 class CProgressDialog: public NWindows::NControl::CModalDialog 105 { 106 UString _titleFileName; 107 UString _filePath; 108 UString _status; 109 bool _isDir; 110 111 UString _background_String; 112 UString _backgrounded_String; 113 UString _foreground_String; 114 UString _pause_String; 115 UString _continue_String; 116 UString _paused_String; 117 118 int _buttonSizeX; 119 int _buttonSizeY; 120 121 UINT_PTR _timer; 122 123 UString _title; 124 125 class CU64ToI32Converter 126 { 127 unsigned _numShiftBits; 128 UInt64 _range; 129 public: CU64ToI32Converter()130 CU64ToI32Converter(): _numShiftBits(0), _range(1) {} Init(UInt64 range)131 void Init(UInt64 range) 132 { 133 _range = range; 134 // Windows CE doesn't like big number for ProgressBar. 135 for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++) 136 range >>= 1; 137 } Count(UInt64 val)138 int Count(UInt64 val) 139 { 140 int res = (int)(val >> _numShiftBits); 141 if (val == _range) 142 res++; 143 return res; 144 } 145 }; 146 147 CU64ToI32Converter _progressConv; 148 UInt64 _progressBar_Pos; 149 UInt64 _progressBar_Range; 150 151 NWindows::NControl::CProgressBar m_ProgressBar; 152 NWindows::NControl::CListView _messageList; 153 154 int _numMessages; 155 156 #ifdef __ITaskbarList3_INTERFACE_DEFINED__ 157 CMyComPtr<ITaskbarList3> _taskbarList; 158 #endif 159 HWND _hwndForTaskbar; 160 161 UInt32 _prevTime; 162 UInt64 _elapsedTime; 163 164 UInt64 _prevPercentValue; 165 UInt64 _prevElapsedSec; 166 UInt64 _prevRemainingSec; 167 168 UInt64 _totalBytes_Prev; 169 UInt64 _processed_Prev; 170 UInt64 _packed_Prev; 171 UInt64 _ratio_Prev; 172 UString _filesStr_Prev; 173 174 unsigned _prevSpeed_MoveBits; 175 UInt64 _prevSpeed; 176 177 bool _foreground; 178 179 unsigned _numReduceSymbols; 180 181 bool _wasCreated; 182 bool _needClose; 183 184 unsigned _numPostedMessages; 185 UInt32 _numAutoSizeMessages; 186 187 bool _errorsWereDisplayed; 188 189 bool _waitCloseByCancelButton; 190 bool _cancelWasPressed; 191 192 bool _inCancelMessageBox; 193 bool _externalCloseMessageWasReceived; 194 195 196 #ifdef __ITaskbarList3_INTERFACE_DEFINED__ SetTaskbarProgressState(TBPFLAG tbpFlags)197 void SetTaskbarProgressState(TBPFLAG tbpFlags) 198 { 199 if (_taskbarList && _hwndForTaskbar) 200 _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags); 201 } 202 #endif 203 void SetTaskbarProgressState(); 204 205 void UpdateStatInfo(bool showAll); 206 bool OnTimer(WPARAM timerID, LPARAM callback); 207 void SetProgressRange(UInt64 range); 208 void SetProgressPos(UInt64 pos); 209 virtual bool OnInit(); 210 virtual bool OnSize(WPARAM wParam, int xSize, int ySize); 211 virtual void OnCancel(); 212 virtual void OnOK(); 213 NWindows::NSynchronization::CManualResetEvent _createDialogEvent; 214 NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; 215 #ifndef _SFX 216 void AddToTitle(LPCWSTR string); 217 #endif 218 219 void SetPauseText(); 220 void SetPriorityText(); 221 void OnPauseButton(); 222 void OnPriorityButton(); 223 bool OnButtonClicked(int buttonID, HWND buttonHWND); 224 bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); 225 226 void SetTitleText(); 227 void ShowSize(int id, UInt64 val, UInt64 &prev); 228 229 void UpdateMessagesDialog(); 230 231 void AddMessageDirect(LPCWSTR message, bool needNumber); 232 void AddMessage(LPCWSTR message); 233 234 bool OnExternalCloseMessage(); 235 void EnableErrorsControls(bool enable); 236 237 void ShowAfterMessages(HWND wndParent); 238 239 void CheckNeedClose(); 240 public: 241 CProgressSync Sync; 242 bool CompressingMode; 243 bool WaitMode; 244 bool ShowCompressionInfo; 245 bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. 246 int IconID; 247 248 HWND MainWindow; 249 #ifndef _SFX 250 UString MainTitle; 251 UString MainAddTitle; 252 ~CProgressDialog(); 253 #endif 254 255 CProgressDialog(); WaitCreating()256 void WaitCreating() 257 { 258 _createDialogEvent.Set(); 259 _dialogCreatedEvent.Lock(); 260 } 261 262 INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0); 263 264 265 /* how it works: 266 1) the working thread calls ProcessWasFinished() 267 that sends kCloseMessage message to CProgressDialog (GUI) thread 268 2) CProgressDialog (GUI) thread receives kCloseMessage message and 269 calls ProcessWasFinished_GuiVirt(); 270 So we can implement ProcessWasFinished_GuiVirt() and show special 271 results window in GUI thread with CProgressDialog as parent window 272 */ 273 274 void ProcessWasFinished(); ProcessWasFinished_GuiVirt()275 virtual void ProcessWasFinished_GuiVirt() {} 276 }; 277 278 279 class CProgressCloser 280 { 281 CProgressDialog *_p; 282 public: CProgressCloser(CProgressDialog & p)283 CProgressCloser(CProgressDialog &p) : _p(&p) {} ~CProgressCloser()284 ~CProgressCloser() { _p->ProcessWasFinished(); } 285 }; 286 287 288 class CProgressThreadVirt: public CProgressDialog 289 { 290 protected: 291 FStringVector ErrorPaths; 292 CProgressFinalMessage FinalMessage; 293 294 // error if any of HRESULT, ErrorMessage, ErrorPath 295 virtual HRESULT ProcessVirt() = 0; 296 public: 297 HRESULT Result; 298 bool ThreadFinishedOK; // if there is no fatal exception 299 300 void Process(); AddErrorPath(const FString & path)301 void AddErrorPath(const FString &path) { ErrorPaths.Add(path); } 302 303 HRESULT Create(const UString &title, HWND parentWindow = 0); CProgressThreadVirt()304 CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} 305 GetMessagePair(bool isError)306 CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; } 307 }; 308 309 UString HResultToMessage(HRESULT errorCode); 310 311 /* 312 how it works: 313 314 client code inherits CProgressThreadVirt and calls 315 CProgressThreadVirt::Create() 316 { 317 it creates new thread that calls CProgressThreadVirt::Process(); 318 it creates modal progress dialog window with ProgressDialog.Create() 319 } 320 321 CProgressThreadVirt::Process() 322 { 323 { 324 ProcessVirt(); // virtual function that must implement real work 325 } 326 if (exceptions) or FinalMessage.ErrorMessage.Message 327 { 328 set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message 329 } 330 else if (FinalMessage.OkMessage.Message) 331 { 332 set message to ProgressDialog.Sync.FinalMessage.OkMessage 333 } 334 335 PostMsg(kCloseMessage); 336 } 337 338 339 CProgressDialog::OnExternalCloseMessage() 340 { 341 if (ProgressDialog.Sync.FinalMessage) 342 { 343 WorkWasFinishedVirt(); 344 Show (ProgressDialog.Sync.FinalMessage) 345 MessagesDisplayed = true; 346 } 347 } 348 349 */ 350 351 #endif 352