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