PageRenderTime 50ms CodeModel.GetById 16ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 0ms

/reporting/crashsender/ProgressDlg.cpp

http://crashrpt.googlecode.com/
C++ | 499 lines | 332 code | 84 blank | 83 comment | 51 complexity | 5b5178d878f24ca03b8f5f40683f2335 MD5 | raw file
  1/************************************************************************************* 
  2This file is a part of CrashRpt library.
  3Copyright (c) 2003-2013 The CrashRpt project authors. All Rights Reserved.
  4
  5Use of this source code is governed by a BSD-style license
  6that can be found in the License.txt file in the root of the source
  7tree. All contributing project authors may
  8be found in the Authors.txt file in the root of the source tree.
  9***************************************************************************************/
 10
 11#include "stdafx.h"
 12#include "ProgressDlg.h"
 13#include "Utility.h"
 14#include "CrashInfoReader.h"
 15
 16
 17LRESULT CProgressDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 18{   
 19    // Check if current UI language is an RTL language
 20	CErrorReportSender* pSender = CErrorReportSender::GetInstance();
 21	CString sRTL = pSender->GetLangStr(_T("Settings"), _T("RTLReading"));
 22    if(sRTL.CompareNoCase(_T("1"))==0)
 23    {
 24        // Mirror this window
 25        Utility::SetLayoutRTL(m_hWnd);
 26    }
 27
 28    HICON hIcon = NULL;
 29
 30    // Try to load custom icon
 31    hIcon = pSender->GetCrashInfo()->GetCustomIcon();
 32    // If there is no custom icon, load the default one
 33    if(hIcon==NULL)
 34        hIcon = ::LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME));
 35
 36    // Set dialog icon
 37    SetIcon(hIcon, FALSE);
 38    SetIcon(hIcon, TRUE);
 39
 40    // Set status text
 41    m_statText = GetDlgItem(IDC_TEXT);
 42	m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("CollectingCrashInfo")));        
 43
 44    // Set progress bar style
 45    m_prgProgress = GetDlgItem(IDC_PROGRESS);  
 46    m_prgProgress.SetRange(0, 100);
 47    m_prgProgress.ModifyStyle(0, PBS_MARQUEE);
 48
 49    // Set up list view
 50    m_listView = GetDlgItem(IDC_LIST); 
 51    m_listView.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
 52    m_listView.InsertColumn(0, _T("Status"), LVCFMT_LEFT, 2048);
 53
 54    // Set up Cancel button
 55    m_btnCancel = GetDlgItem(IDCANCEL);
 56	m_btnCancel.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Cancel")));
 57
 58	// Init flags
 59    m_ActionOnCancel = DONT_CLOSE;
 60    m_ActionOnClose = CLOSE_MYSELF;  
 61
 62    // Init dialog resize functionality
 63    DlgResize_Init();
 64
 65    return TRUE;
 66}
 67
 68LRESULT CProgressDlg::OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 69{   
 70	// This method is called when user clicks the close (x) button
 71	// on the dialog.
 72
 73    if(m_ActionOnClose==CLOSE_MYSELF_AND_PARENT)
 74    {
 75        // Hide this window smoothly
 76        AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND); 
 77
 78        // Request parent window to close
 79        HWND hWndParent = ::GetParent(m_hWnd);
 80        ::PostMessage(hWndParent, WM_CLOSE, 0, 0);
 81        return 0;
 82    }
 83    else if(m_ActionOnClose==CLOSE_MYSELF)
 84    {
 85        // Hide this window smoothly
 86        AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND); 	  
 87        return 0;
 88    }
 89
 90    return 0;
 91}
 92
 93
 94LRESULT CProgressDlg::OnCancel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
 95{ 
 96	// This method is called when user clicks the "Cancel" button
 97	// on the dialog.
 98
 99    if(m_ActionOnCancel==CLOSE_MYSELF_AND_PARENT)
100    {
101        // Hide this window smoothly
102        AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND); 
103
104        // Request parent window to close
105        HWND hWndParent = ::GetParent(m_hWnd);
106        ::PostMessage(hWndParent, WM_CLOSE, 0, 0);
107        return 0;
108    }
109    else if(m_ActionOnCancel==CLOSE_MYSELF)
110    {
111        // Hide this window smoothly
112        AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND); 	  
113        return 0;
114    }
115
116    // Start cancelling the worker thread
117	CErrorReportSender* pSender = CErrorReportSender::GetInstance();
118    pSender->Cancel();  
119
120    // Disable Cancel button
121    m_btnCancel.EnableWindow(0);
122
123    return 0;
124}
125
126void CProgressDlg::Start(BOOL bCollectInfo, BOOL bMakeVisible)
127{   
128	// This method displays the progress dialog and starts the timer
129	// that will update the dialog periodically and react on 
130	// incoming events.
131
132	CErrorReportSender* pSender = CErrorReportSender::GetInstance();
133
134	// Set up correct dialog caption
135    if(bCollectInfo)
136    {
137        CString sCaption;
138		sCaption.Format(pSender->GetLangStr(_T("ProgressDlg"), _T("DlgCaption2")), pSender->GetCrashInfo()->m_sAppName);
139        SetWindowText(sCaption);    
140    }
141    else
142    {
143        CString sCaption;
144		sCaption.Format(pSender->GetLangStr(_T("ProgressDlg"), _T("DlgCaption")), pSender->GetCrashInfo()->m_sAppName);
145        SetWindowText(sCaption);    
146    }
147
148    // Show the window on top of other windows
149    SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
150
151    // Center the dialog on the screen
152    CenterWindow();
153
154	// Check if we need to make the dialog visible
155    if(bMakeVisible)
156    {
157		// Show the dialog and set focus on it
158        ShowWindow(SW_SHOW); 
159        SetFocus();    
160    }
161
162    if(!bCollectInfo)
163    {
164		// If we are not collecting crash information now, than hide this dialog in 3 sec.
165        SetTimer(1, 3000); 
166    }
167
168	// Update this dialog each 200 ms.
169    SetTimer(0, 200); 
170
171	// If user clicks the Close button (x), do not close the window.
172    m_ActionOnCancel = DONT_CLOSE;
173}
174
175void CProgressDlg::Stop()
176{
177    // Stop timers
178    KillTimer(0);
179    KillTimer(1);
180}
181
182LRESULT CProgressDlg::OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
183{
184	// This method is called when a timer ticks.
185
186    WORD wTimerId = (WORD)wParam;
187	CErrorReportSender* pSender = CErrorReportSender::GetInstance();
188
189    if(wTimerId==0) // Dialog update timer
190    {
191        // Get current progress
192        int nProgressPct = 0;
193        std::vector<CString> messages;
194        pSender->GetCurOpStatus(nProgressPct, messages);
195
196        // Update progress bar
197        m_prgProgress.SetPos(nProgressPct);
198
199        int attempt = 0; // Sending attempt
200
201        // Walk through incoming messages and look for special ones (enclosed in [ ])
202        unsigned i;
203        for(i=0; i<messages.size(); i++)
204        {  
205            if(messages[i].CompareNoCase(_T("[creating_dump]"))==0)
206            { 
207                // Creating minidump
208                m_ActionOnCancel = DONT_CLOSE;
209                m_ActionOnClose = CLOSE_MYSELF_AND_PARENT;
210				m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("CollectingCrashInfo")));        
211            }
212            else if(messages[i].CompareNoCase(_T("[copying_files]"))==0)
213            { 
214                // Copying files
215                m_ActionOnCancel = DONT_CLOSE;
216                m_ActionOnClose = CLOSE_MYSELF_AND_PARENT;
217                // Remove marquee style from progress bar
218                m_prgProgress.ModifyStyle(PBS_MARQUEE, 0);        
219            }
220            else if(messages[i].CompareNoCase(_T("[confirm_send_report]"))==0)
221            {
222                // User should consent to send error report, so we hide this dialog
223				// and send a message to our parent dialog that will receive user input.
224                m_ActionOnCancel = CLOSE_MYSELF_AND_PARENT;
225
226				ShowWindow(SW_HIDE);
227
228                HWND hWndParent = ::GetParent(m_hWnd);        
229                ::PostMessage(hWndParent, WM_COMPLETECOLLECT, 0, 0);
230            }
231            else if(messages[i].CompareNoCase(_T("[exporting_report]"))==0)
232            {
233                // Exporting error report as a ZIP archive
234                m_ActionOnCancel = DONT_CLOSE;
235                m_ActionOnClose = DONT_CLOSE;
236                CString sCaption;
237				sCaption.Format(pSender->GetLangStr(_T("ProgressDlg"), _T("DlgCaptionExport")), 
238					pSender->GetCrashInfo()->m_sAppName);
239                SetWindowText(sCaption);    
240
241				m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("CompressingFiles")));        
242
243				m_btnCancel.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Cancel")));
244
245                ShowWindow(SW_SHOW);
246            }
247            else if(messages[i].CompareNoCase(_T("[end_exporting_report_ok]"))==0)
248            { 
249                // End exporting error report
250                m_ActionOnCancel = CLOSE_MYSELF;
251                ShowWindow(SW_HIDE);
252            }
253            else if(messages[i].CompareNoCase(_T("[end_exporting_report_failed]"))==0)
254            { 
255                // Failed to export error report
256                m_ActionOnCancel = CLOSE_MYSELF;
257                m_ActionOnClose = CLOSE_MYSELF;
258				m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("ExportedWithErrors")));        
259                m_btnCancel.EnableWindow(1);
260				m_btnCancel.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Close")));
261            }
262            else if(messages[i].CompareNoCase(_T("[compressing_files]"))==0)
263            {         
264                // Compressing error report files
265                m_ActionOnCancel = DONT_CLOSE; 
266                m_ActionOnClose = CLOSE_MYSELF;
267				m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("CompressingFiles")));        
268				m_btnCancel.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Cancel")));
269            }      
270            else if(messages[i].CompareNoCase(_T("[end_compressing_files]"))==0)
271            { 
272                // File compression finished
273				if(!pSender->GetCrashInfo()->m_bSendErrorReport && pSender->GetCrashInfo()->m_bStoreZIPArchives)
274                {
275                    m_ActionOnCancel = CLOSE_MYSELF;
276                    m_ActionOnClose = CLOSE_MYSELF;
277                    HWND hWndParent = ::GetParent(m_hWnd);        
278                    ::PostMessage(hWndParent, WM_CLOSE, 0, 0);
279                }
280            }
281            else if(messages[i].CompareNoCase(_T("[status_success]"))==0)
282            {         
283                // Error report has been delivered ok
284                m_ActionOnCancel = CLOSE_MYSELF_AND_PARENT;        
285                m_ActionOnClose = CLOSE_MYSELF_AND_PARENT;        
286
287				// Close the parent dialog.
288                HWND hWndParent = ::GetParent(m_hWnd);        
289                ::PostMessage(hWndParent, WM_CLOSE, 0, 0);
290            }
291            else if(messages[i].CompareNoCase(_T("[status_failed]"))==0)
292            {         
293                // Error report delivery has failed
294                m_ActionOnCancel = CLOSE_MYSELF_AND_PARENT;
295                m_ActionOnClose = CLOSE_MYSELF_AND_PARENT;        
296                
297				// Stop timer
298				KillTimer(1);
299
300				// Update status text.
301				m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("CompletedWithErrors")));
302
303				// Enable "Close" button
304                m_btnCancel.EnableWindow(1);
305				m_btnCancel.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Close")));
306
307				// Show the dialog
308				ShowWindow(SW_SHOW);        
309            }
310            else if(messages[i].CompareNoCase(_T("[exit_silently]"))==0)
311            {         
312                // Silent exit
313                m_ActionOnCancel = CLOSE_MYSELF_AND_PARENT;
314                m_ActionOnClose = CLOSE_MYSELF_AND_PARENT;
315
316				// Stop timer
317                KillTimer(1);        
318
319				// Close the parent dialog.
320                HWND hWndParent = ::GetParent(m_hWnd);        
321                ::PostMessage(hWndParent, WM_CLOSE, 0, 0);
322            }
323            else if(messages[i].CompareNoCase(_T("[cancelled_by_user]"))==0)
324            { 
325                // The operation was cancelled by user
326				m_statText.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Cancelling")));
327            }
328            else if(messages[i].CompareNoCase(_T("[sending_attempt]"))==0)
329            {
330                // Trying to send error report using another method
331                attempt ++;      
332                CString str;
333				str.Format(pSender->GetLangStr(_T("ProgressDlg"), _T("StatusText")), attempt);
334                m_statText.SetWindowText(str);
335            }
336            else if(messages[i].CompareNoCase(_T("[confirm_launch_email_client]"))==0)
337            {       
338                // User should confirm he allows to launch email client
339                KillTimer(1);        
340                
341				// Show the dialog
342				ShowWindow(SW_SHOW);
343
344				// Determine window mirroring settings.
345                DWORD dwFlags = 0;
346				CString sRTL = pSender->GetLangStr(_T("Settings"), _T("RTLReading"));
347                if(sRTL.CompareNoCase(_T("1"))==0)
348                    dwFlags = MB_RTLREADING;
349
350				// Display the message box, so user to be able to confirm.
351                CString sMailClientName;        
352                CMailMsg::DetectMailClient(sMailClientName);
353                CString msg;
354				msg.Format(pSender->GetLangStr(_T("ProgressDlg"), _T("ConfirmLaunchEmailClient")), sMailClientName);
355
356				CString sCaption = pSender->GetLangStr(_T("ProgressDlg"), _T("DlgCaption"));
357                CString sTitle;
358				sTitle.Format(sCaption, pSender->GetCrashInfo()->m_sAppName);
359                INT_PTR result = MessageBox(msg, 
360                    sTitle,
361                    MB_OKCANCEL|MB_ICONQUESTION|dwFlags);
362
363				// Unblock worker thread.
364                pSender->FeedbackReady(result==IDOK?0:1);       
365
366				// Hide the dialog
367                ShowWindow(SW_HIDE);                
368            }
369
370            // Ensure the last item of the log is visible
371            int count = m_listView.GetItemCount();
372            int indx = m_listView.InsertItem(count, messages[i]);
373            m_listView.EnsureVisible(indx, TRUE);
374
375        }
376    }
377    else if(wTimerId==1) // The timer that hides this window
378    {
379		// Hide the window smoothly
380		AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND); 
381		// Stop the timer
382        KillTimer(1);
383    }
384
385    return 0;
386}
387
388LRESULT CProgressDlg::OnListRClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
389{  
390	// User right-clicks the log area. We should display context menu.
391
392	CErrorReportSender* pSender = CErrorReportSender::GetInstance();
393    LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) pnmh;
394
395    POINT pt;
396    GetCursorPos(&pt);
397
398    CMenu popup_menu;
399    popup_menu.LoadMenu(IDR_POPUPMENU);
400
401    CMenu submenu = popup_menu.GetSubMenu(0);  
402
403    if(lpnmitem->iItem<0)
404    {    
405        submenu.EnableMenuItem(ID_MENU1_COPYSEL, MF_BYCOMMAND|MF_GRAYED);
406    }
407
408    CString sCopySelLines = pSender->GetLangStr(_T("ProgressDlg"), _T("CopySelectedLines"));
409	CString sCopyWholeLog = pSender->GetLangStr(_T("ProgressDlg"), _T("CopyTheWholeLog"));
410
411    MENUITEMINFO mii;
412    memset(&mii, 0, sizeof(MENUITEMINFO));
413    mii.cbSize = sizeof(MENUITEMINFO);
414    mii.fMask = MIIM_STRING;
415
416    mii.dwTypeData = sCopySelLines.GetBuffer(0);
417    mii.cch = sCopySelLines.GetLength();
418    submenu.SetMenuItemInfo(ID_MENU1_COPYSEL, FALSE, &mii);
419
420    mii.dwTypeData = sCopyWholeLog.GetBuffer(0);
421    mii.cch = sCopyWholeLog.GetLength();
422    submenu.SetMenuItemInfo(ID_MENU1_COPYLOG, FALSE, &mii);
423
424    submenu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, m_hWnd); 
425    return 0;
426}
427
428LRESULT CProgressDlg::OnCopySel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
429{
430	// User wants to copy selected lines to clipboard.
431
432    CString sData;
433    int i;
434    for(i=0; i<m_listView.GetItemCount(); i++)
435    {
436        DWORD dwState = m_listView.GetItemState(i, LVIS_SELECTED);
437        if(dwState==0)
438            continue;
439
440        TCHAR buf[4096];
441        buf[0]=0;
442        int n = m_listView.GetItemText(i, 0, buf, 4095);
443        sData += CString(buf,n);
444        sData += "\r\n";
445    }
446
447    SetClipboard(sData);  
448
449    return 0;
450}
451
452LRESULT CProgressDlg::OnCopyLog(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
453{
454	// User wants to copy the entire log to clipboard.
455
456    CString sData;
457    int i;
458    for(i=0; i<m_listView.GetItemCount(); i++)
459    {
460        TCHAR buf[4096];
461        buf[0]=0;
462        int n = m_listView.GetItemText(i, 0, buf, 4095);
463        sData += CString(buf,n);
464        sData += "\r\n";
465    }
466
467    SetClipboard(sData);  
468
469    return 0;
470}
471
472int CProgressDlg::SetClipboard(CString& sData)
473{
474	// This method places the data to clipboard.
475
476    if (OpenClipboard())
477    {
478        EmptyClipboard();
479        HGLOBAL hClipboardData;
480        DWORD dwSize = (sData.GetLength()+1)*sizeof(TCHAR);
481        hClipboardData = GlobalAlloc(GMEM_DDESHARE, dwSize);
482        TCHAR* pszData = (TCHAR*)GlobalLock(hClipboardData);
483        if(pszData!=NULL)
484        {      
485            _TCSNCPY_S(pszData, dwSize/sizeof(TCHAR), sData, sData.GetLength()*sizeof(TCHAR));
486            GlobalUnlock(hClipboardData);
487#ifdef _UNICODE
488            SetClipboardData(CF_UNICODETEXT, hClipboardData);
489#else
490            SetClipboardData(CF_TEXT, hClipboardData);    
491#endif
492            CloseClipboard();
493            return 0;
494        }
495        CloseClipboard();
496    }
497
498    return 1;
499}