1 // ProgressDialog2.h 2 3 #ifndef ZIP7_INC_PROGRESS_DIALOG_2_H 4 #define ZIP7_INC_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 bool _isDir; 40 UInt64 _totalBytes; 41 UInt64 _completedBytes; 42 UInt64 _totalFiles; 43 UInt64 _curFiles; 44 UInt64 _inSize; 45 UInt64 _outSize; 46 47 UString _titleFileName; 48 UString _status; 49 UString _filePath; 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 void AddError_Code_Name(HRESULT systemError, const wchar_t *name); 101 ThereIsMessage() const102 bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } 103 }; 104 105 class CProgressDialog: public NWindows::NControl::CModalDialog 106 { 107 UString _titleFileName; 108 UString _filePath; 109 UString _status; 110 bool _isDir; 111 112 UString _background_String; 113 UString _backgrounded_String; 114 UString _foreground_String; 115 UString _pause_String; 116 UString _continue_String; 117 UString _paused_String; 118 119 int _buttonSizeX; 120 int _buttonSizeY; 121 122 UINT_PTR _timer; 123 124 UString _title; 125 126 class CU64ToI32Converter 127 { 128 unsigned _numShiftBits; 129 UInt64 _range; 130 public: CU64ToI32Converter()131 CU64ToI32Converter(): _numShiftBits(0), _range(1) {} Init(UInt64 range)132 void Init(UInt64 range) 133 { 134 _range = range; 135 // Windows CE doesn't like big number for ProgressBar. 136 for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++) 137 range >>= 1; 138 } Count(UInt64 val)139 int Count(UInt64 val) 140 { 141 int res = (int)(val >> _numShiftBits); 142 if (val == _range) 143 res++; 144 return res; 145 } 146 }; 147 148 CU64ToI32Converter _progressConv; 149 UInt64 _progressBar_Pos; 150 UInt64 _progressBar_Range; 151 152 NWindows::NControl::CProgressBar m_ProgressBar; 153 NWindows::NControl::CListView _messageList; 154 155 unsigned _numMessages; 156 UStringVector _messageStrings; 157 158 // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ 159 CMyComPtr<ITaskbarList3> _taskbarList; 160 // #endif 161 HWND _hwndForTaskbar; 162 163 UInt32 _prevTime; 164 UInt64 _elapsedTime; 165 166 UInt64 _prevPercentValue; 167 UInt64 _prevElapsedSec; 168 UInt64 _prevRemainingSec; 169 170 UInt64 _totalBytes_Prev; 171 UInt64 _processed_Prev; 172 UInt64 _packed_Prev; 173 UInt64 _ratio_Prev; 174 175 UString _filesStr_Prev; 176 UString _filesTotStr_Prev; 177 178 unsigned _prevSpeed_MoveBits; 179 UInt64 _prevSpeed; 180 181 bool _foreground; 182 183 unsigned _numReduceSymbols; 184 185 bool _wasCreated; 186 bool _needClose; 187 188 unsigned _numPostedMessages; 189 UInt32 _numAutoSizeMessages; 190 191 bool _errorsWereDisplayed; 192 193 bool _waitCloseByCancelButton; 194 bool _cancelWasPressed; 195 196 bool _inCancelMessageBox; 197 bool _externalCloseMessageWasReceived; 198 199 200 // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ SetTaskbarProgressState(TBPFLAG tbpFlags)201 void SetTaskbarProgressState(TBPFLAG tbpFlags) 202 { 203 if (_taskbarList && _hwndForTaskbar) 204 _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags); 205 } 206 // #endif 207 void SetTaskbarProgressState(); 208 209 void UpdateStatInfo(bool showAll); 210 void SetProgressRange(UInt64 range); 211 void SetProgressPos(UInt64 pos); 212 virtual bool OnTimer(WPARAM timerID, LPARAM callback) Z7_override; 213 virtual bool OnInit() Z7_override; 214 virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override; 215 virtual void OnCancel() Z7_override; 216 virtual void OnOK() Z7_override; 217 virtual bool OnNotify(UINT /* controlID */, LPNMHDR header) Z7_override; 218 void CopyToClipboard(); 219 220 NWindows::NSynchronization::CManualResetEvent _createDialogEvent; 221 NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; 222 #ifndef Z7_SFX 223 void AddToTitle(LPCWSTR string); 224 #endif 225 226 void SetPauseText(); 227 void SetPriorityText(); 228 void OnPauseButton(); 229 void OnPriorityButton(); 230 bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; 231 bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override; 232 233 void SetTitleText(); 234 void ShowSize(unsigned id, UInt64 val, UInt64 &prev); 235 236 void UpdateMessagesDialog(); 237 238 void AddMessageDirect(LPCWSTR message, bool needNumber); 239 void AddMessage(LPCWSTR message); 240 241 bool OnExternalCloseMessage(); 242 void EnableErrorsControls(bool enable); 243 244 void ShowAfterMessages(HWND wndParent); 245 246 void CheckNeedClose(); 247 public: 248 CProgressSync Sync; 249 bool CompressingMode; 250 bool WaitMode; 251 bool ShowCompressionInfo; 252 bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. 253 int IconID; 254 255 HWND MainWindow; 256 #ifndef Z7_SFX 257 UString MainTitle; 258 UString MainAddTitle; 259 ~CProgressDialog() Z7_DESTRUCTOR_override; 260 #endif 261 262 CProgressDialog(); WaitCreating()263 void WaitCreating() 264 { 265 _createDialogEvent.Set(); 266 _dialogCreatedEvent.Lock(); 267 } 268 269 INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = NULL); 270 271 272 /* how it works: 273 1) the working thread calls ProcessWasFinished() 274 that sends kCloseMessage message to CProgressDialog (GUI) thread 275 2) CProgressDialog (GUI) thread receives kCloseMessage message and 276 calls ProcessWasFinished_GuiVirt(); 277 So we can implement ProcessWasFinished_GuiVirt() and show special 278 results window in GUI thread with CProgressDialog as parent window 279 */ 280 281 void ProcessWasFinished(); ProcessWasFinished_GuiVirt()282 virtual void ProcessWasFinished_GuiVirt() {} 283 }; 284 285 286 class CProgressCloser 287 { 288 CProgressDialog *_p; 289 public: CProgressCloser(CProgressDialog &p)290 CProgressCloser(CProgressDialog &p) : _p(&p) {} ~CProgressCloser()291 ~CProgressCloser() { _p->ProcessWasFinished(); } 292 }; 293 294 295 class CProgressThreadVirt: public CProgressDialog 296 { 297 protected: 298 FStringVector ErrorPaths; 299 CProgressFinalMessage FinalMessage; 300 301 // error if any of HRESULT, ErrorMessage, ErrorPath 302 virtual HRESULT ProcessVirt() = 0; 303 public: 304 HRESULT Result; 305 bool ThreadFinishedOK; // if there is no fatal exception 306 307 void Process(); AddErrorPath(const FString &path)308 void AddErrorPath(const FString &path) { ErrorPaths.Add(path); } 309 310 HRESULT Create(const UString &title, HWND parentWindow = NULL); CProgressThreadVirt()311 CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} 312 GetMessagePair(bool isError)313 CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; } 314 }; 315 316 UString HResultToMessage(HRESULT errorCode); 317 318 /* 319 how it works: 320 321 client code inherits CProgressThreadVirt and calls 322 CProgressThreadVirt::Create() 323 { 324 it creates new thread that calls CProgressThreadVirt::Process(); 325 it creates modal progress dialog window with ProgressDialog.Create() 326 } 327 328 CProgressThreadVirt::Process() 329 { 330 { 331 Result = ProcessVirt(); // virtual function that must implement real work 332 } 333 if (exceptions) or FinalMessage.ErrorMessage.Message 334 { 335 set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message 336 } 337 else if (FinalMessage.OkMessage.Message) 338 { 339 set message to ProgressDialog.Sync.FinalMessage.OkMessage 340 } 341 342 PostMsg(kCloseMessage); 343 } 344 345 346 CProgressDialog::OnExternalCloseMessage() 347 { 348 if (ProgressDialog.Sync.FinalMessage) 349 { 350 WorkWasFinishedVirt(); 351 Show (ProgressDialog.Sync.FinalMessage) 352 MessagesDisplayed = true; 353 } 354 } 355 356 */ 357 358 #endif 359