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 UStringVector _messageStrings; 156 157 #ifdef __ITaskbarList3_INTERFACE_DEFINED__ 158 CMyComPtr<ITaskbarList3> _taskbarList; 159 #endif 160 HWND _hwndForTaskbar; 161 162 UInt32 _prevTime; 163 UInt64 _elapsedTime; 164 165 UInt64 _prevPercentValue; 166 UInt64 _prevElapsedSec; 167 UInt64 _prevRemainingSec; 168 169 UInt64 _totalBytes_Prev; 170 UInt64 _processed_Prev; 171 UInt64 _packed_Prev; 172 UInt64 _ratio_Prev; 173 174 UString _filesStr_Prev; 175 UString _filesTotStr_Prev; 176 177 unsigned _prevSpeed_MoveBits; 178 UInt64 _prevSpeed; 179 180 bool _foreground; 181 182 unsigned _numReduceSymbols; 183 184 bool _wasCreated; 185 bool _needClose; 186 187 unsigned _numPostedMessages; 188 UInt32 _numAutoSizeMessages; 189 190 bool _errorsWereDisplayed; 191 192 bool _waitCloseByCancelButton; 193 bool _cancelWasPressed; 194 195 bool _inCancelMessageBox; 196 bool _externalCloseMessageWasReceived; 197 198 199 #ifdef __ITaskbarList3_INTERFACE_DEFINED__ SetTaskbarProgressState(TBPFLAG tbpFlags)200 void SetTaskbarProgressState(TBPFLAG tbpFlags) 201 { 202 if (_taskbarList && _hwndForTaskbar) 203 _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags); 204 } 205 #endif 206 void SetTaskbarProgressState(); 207 208 void UpdateStatInfo(bool showAll); 209 bool OnTimer(WPARAM timerID, LPARAM callback); 210 void SetProgressRange(UInt64 range); 211 void SetProgressPos(UInt64 pos); 212 virtual bool OnInit(); 213 virtual bool OnSize(WPARAM wParam, int xSize, int ySize); 214 virtual void OnCancel(); 215 virtual void OnOK(); 216 virtual bool OnNotify(UINT /* controlID */, LPNMHDR header); 217 void CopyToClipboard(); 218 219 NWindows::NSynchronization::CManualResetEvent _createDialogEvent; 220 NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; 221 #ifndef _SFX 222 void AddToTitle(LPCWSTR string); 223 #endif 224 225 void SetPauseText(); 226 void SetPriorityText(); 227 void OnPauseButton(); 228 void OnPriorityButton(); 229 bool OnButtonClicked(int buttonID, HWND buttonHWND); 230 bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); 231 232 void SetTitleText(); 233 void ShowSize(int id, UInt64 val, UInt64 &prev); 234 235 void UpdateMessagesDialog(); 236 237 void AddMessageDirect(LPCWSTR message, bool needNumber); 238 void AddMessage(LPCWSTR message); 239 240 bool OnExternalCloseMessage(); 241 void EnableErrorsControls(bool enable); 242 243 void ShowAfterMessages(HWND wndParent); 244 245 void CheckNeedClose(); 246 public: 247 CProgressSync Sync; 248 bool CompressingMode; 249 bool WaitMode; 250 bool ShowCompressionInfo; 251 bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. 252 int IconID; 253 254 HWND MainWindow; 255 #ifndef _SFX 256 UString MainTitle; 257 UString MainAddTitle; 258 ~CProgressDialog(); 259 #endif 260 261 CProgressDialog(); WaitCreating()262 void WaitCreating() 263 { 264 _createDialogEvent.Set(); 265 _dialogCreatedEvent.Lock(); 266 } 267 268 INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0); 269 270 271 /* how it works: 272 1) the working thread calls ProcessWasFinished() 273 that sends kCloseMessage message to CProgressDialog (GUI) thread 274 2) CProgressDialog (GUI) thread receives kCloseMessage message and 275 calls ProcessWasFinished_GuiVirt(); 276 So we can implement ProcessWasFinished_GuiVirt() and show special 277 results window in GUI thread with CProgressDialog as parent window 278 */ 279 280 void ProcessWasFinished(); ProcessWasFinished_GuiVirt()281 virtual void ProcessWasFinished_GuiVirt() {} 282 }; 283 284 285 class CProgressCloser 286 { 287 CProgressDialog *_p; 288 public: CProgressCloser(CProgressDialog & p)289 CProgressCloser(CProgressDialog &p) : _p(&p) {} ~CProgressCloser()290 ~CProgressCloser() { _p->ProcessWasFinished(); } 291 }; 292 293 294 class CProgressThreadVirt: public CProgressDialog 295 { 296 protected: 297 FStringVector ErrorPaths; 298 CProgressFinalMessage FinalMessage; 299 300 // error if any of HRESULT, ErrorMessage, ErrorPath 301 virtual HRESULT ProcessVirt() = 0; 302 public: 303 HRESULT Result; 304 bool ThreadFinishedOK; // if there is no fatal exception 305 306 void Process(); AddErrorPath(const FString & path)307 void AddErrorPath(const FString &path) { ErrorPaths.Add(path); } 308 309 HRESULT Create(const UString &title, HWND parentWindow = 0); CProgressThreadVirt()310 CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} 311 GetMessagePair(bool isError)312 CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; } 313 }; 314 315 UString HResultToMessage(HRESULT errorCode); 316 317 /* 318 how it works: 319 320 client code inherits CProgressThreadVirt and calls 321 CProgressThreadVirt::Create() 322 { 323 it creates new thread that calls CProgressThreadVirt::Process(); 324 it creates modal progress dialog window with ProgressDialog.Create() 325 } 326 327 CProgressThreadVirt::Process() 328 { 329 { 330 Result = ProcessVirt(); // virtual function that must implement real work 331 } 332 if (exceptions) or FinalMessage.ErrorMessage.Message 333 { 334 set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message 335 } 336 else if (FinalMessage.OkMessage.Message) 337 { 338 set message to ProgressDialog.Sync.FinalMessage.OkMessage 339 } 340 341 PostMsg(kCloseMessage); 342 } 343 344 345 CProgressDialog::OnExternalCloseMessage() 346 { 347 if (ProgressDialog.Sync.FinalMessage) 348 { 349 WorkWasFinishedVirt(); 350 Show (ProgressDialog.Sync.FinalMessage) 351 MessagesDisplayed = true; 352 } 353 } 354 355 */ 356 357 #endif 358