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