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