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