Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

969 lines
25 KiB

  1. // StatsDlg.cpp : Implementation of CStatusDlg
  2. #include "stdafx.h"
  3. #include "WizChain.h"
  4. #include "StatsDlg.h"
  5. // This is the thread that displays the status dialog
  6. DWORD WINAPI DialogThreadProc( LPVOID lpv )
  7. {
  8. HRESULT hr;
  9. CStatusDlg * pSD = (CStatusDlg *)lpv;
  10. // Increment the ref count so that the object does not disappear when the user releases it
  11. hr = pSD->AddRef();
  12. if( SUCCEEDED(hr) && pSD )
  13. {
  14. pSD->DoModal(NULL);
  15. }
  16. // Decrement the ref count
  17. pSD->Release();
  18. return 0;
  19. }
  20. STDMETHODIMP CStatusDlg::AddComponent( BSTR bstrComponent, long * plIndex )
  21. {
  22. HRESULT hr = S_OK;
  23. // If the dialog is already displayed
  24. // we are not accepting new components
  25. if( m_hThread )
  26. return E_UNEXPECTED;
  27. // Validate the arguments
  28. if( NULL == bstrComponent || NULL == plIndex )
  29. return E_INVALIDARG;
  30. // Get a new index
  31. long lNewIndex = m_mapComponents.size();
  32. if( m_mapComponents.find(lNewIndex) == m_mapComponents.end() )
  33. {
  34. // Add the new component
  35. BSTR bstrNewComponent = SysAllocString(bstrComponent);
  36. if( bstrNewComponent )
  37. {
  38. m_mapComponents.insert(COMPONENTMAP::value_type(lNewIndex, bstrNewComponent));
  39. }
  40. else
  41. {
  42. hr = E_OUTOFMEMORY;
  43. }
  44. }
  45. else
  46. {
  47. hr = E_UNEXPECTED; // This cannot happen!
  48. }
  49. if( SUCCEEDED(hr) )
  50. {
  51. *plIndex = lNewIndex;
  52. }
  53. return hr;
  54. }
  55. STDMETHODIMP CStatusDlg::Initialize( BSTR bstrWindowTitle, BSTR bstrWindowText, VARIANT varFlags )
  56. {
  57. HRESULT hr = S_OK;
  58. // If the dialog is already displayed
  59. // do not allow to reinitialize
  60. if( m_hThread ) return E_UNEXPECTED;
  61. if( !bstrWindowTitle || !bstrWindowText ) return E_INVALIDARG;
  62. if( VT_I2 != V_VT(&varFlags) && VT_I4 != V_VT(&varFlags) ) return E_INVALIDARG;
  63. if( VT_I2 == V_VT(&varFlags) )
  64. {
  65. m_lFlags = (long) varFlags.iVal;
  66. }
  67. else
  68. {
  69. m_lFlags = varFlags.lVal;
  70. }
  71. if( SUCCEEDED(hr) )
  72. {
  73. // Initialize the common control library
  74. INITCOMMONCONTROLSEX initCommonControlsEx;
  75. initCommonControlsEx.dwSize = sizeof(initCommonControlsEx);
  76. initCommonControlsEx.dwICC = ICC_PROGRESS_CLASS | ICC_LISTVIEW_CLASSES;
  77. if( !::InitCommonControlsEx(&initCommonControlsEx) )
  78. {
  79. hr = HRESULT_FROM_WIN32(GetLastError());
  80. }
  81. }
  82. if( SUCCEEDED(hr) )
  83. {
  84. if( bstrWindowTitle )
  85. {
  86. m_strWindowTitle = bstrWindowTitle; // Status Dialog Title
  87. }
  88. if( bstrWindowText )
  89. {
  90. m_strWindowText = bstrWindowText; // Status Dialog Text
  91. }
  92. }
  93. return hr;
  94. }
  95. STDMETHODIMP CStatusDlg::SetStatus(long lIndex, SD_STATUS lStatus)
  96. {
  97. HRESULT hr = S_OK;
  98. BOOL bToggleActive = FALSE;
  99. COMPONENTMAP::iterator compIterator;
  100. // Validate the arguments
  101. if( (SD_STATUS_NONE > lStatus) || (SD_STATUS_RUNNING < lStatus) )
  102. {
  103. return E_INVALIDARG;
  104. }
  105. compIterator = m_mapComponents.find(lIndex);
  106. if( compIterator == m_mapComponents.end() )
  107. {
  108. return E_INVALIDARG; // Cannot find the component
  109. }
  110. if( IsWindow() )
  111. {
  112. if( m_pProgressList )
  113. {
  114. CProgressItem * pPI;
  115. compIterator = m_mapComponents.begin();
  116. // Make sure that no component has status "running"
  117. while( compIterator != m_mapComponents.end() )
  118. {
  119. pPI = m_pProgressList->GetProgressItem(compIterator->first);
  120. if( pPI && pPI->m_bActive )
  121. {
  122. m_pProgressList->ToggleActive(compIterator->first);
  123. }
  124. compIterator++;
  125. }
  126. if( SD_STATUS_RUNNING == lStatus )
  127. {
  128. m_pProgressList->ToggleActive(lIndex); // New status is "running"
  129. }
  130. else
  131. {
  132. // Update the state of the component on the Listview
  133. m_pProgressList->SetItemState(lIndex, (ItemState) lStatus);
  134. // If the component's done, update the total progress
  135. if( (lStatus == SD_STATUS_SUCCEEDED) || (lStatus == SD_STATUS_FAILED) )
  136. {
  137. // TO DO: No need to do this, just send a message to the dialog to do that
  138. PBRANGE range;
  139. SendDlgItemMessage(IDC_PROGRESS1, PBM_GETRANGE, FALSE, (LPARAM) &range);
  140. SendDlgItemMessage(IDC_PROGRESS1, PBM_SETPOS, range.iHigh, 0);
  141. InterlockedExchangeAdd(&m_lTotalProgress, range.iHigh);
  142. }
  143. }
  144. }
  145. else
  146. {
  147. hr = E_UNEXPECTED;
  148. }
  149. if( SUCCEEDED(hr) )
  150. {
  151. SetupButtons( );
  152. }
  153. }
  154. else
  155. {
  156. hr = E_UNEXPECTED;
  157. }
  158. return hr;
  159. }
  160. void CStatusDlg::SetupButtons( )
  161. {
  162. HWND hWnd = NULL;
  163. HWND hWndOK = NULL;
  164. HWND hWndCancel = NULL;
  165. CString csText;
  166. BOOL bFailed = FALSE;
  167. BSTR bstrText = NULL;
  168. USES_CONVERSION;
  169. hWndOK = GetDlgItem(IDOK);
  170. hWndCancel = GetDlgItem(IDCANCEL);
  171. if( IsWindow() && hWndOK && hWndCancel )
  172. {
  173. if( AreAllComponentsDone(bFailed) )
  174. {
  175. // Enable OK button
  176. ::EnableWindow(hWndOK, TRUE);
  177. // Disable Cancel button
  178. ::EnableWindow(hWndCancel, FALSE);
  179. // Default button is the Close button
  180. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM) hWndOK, 1);
  181. //
  182. // When all components are done we will hide the progress bars to give the user
  183. // a visual clue to realize that the wizard is done. I know, that sounds stupid.
  184. //
  185. hWnd = GetDlgItem(IDC_STATIC2); // Component progress text
  186. if (NULL != hWnd)
  187. {
  188. ::ShowWindow(hWnd, SW_HIDE);
  189. }
  190. hWnd = GetDlgItem(IDC_PROGRESS1); // Component progress text
  191. if (NULL != hWnd)
  192. {
  193. ::ShowWindow(hWnd, SW_HIDE);
  194. }
  195. hWnd = GetDlgItem(IDC_STATIC3); // Overall progress text
  196. if (NULL != hWnd)
  197. {
  198. ::ShowWindow(hWnd, SW_HIDE);
  199. }
  200. hWnd = GetDlgItem(IDC_PROGRESS2); // Overall progress
  201. if (NULL != hWnd)
  202. {
  203. ::ShowWindow(hWnd, SW_HIDE);
  204. }
  205. if (FALSE == bFailed)
  206. {
  207. if (csText.LoadString(IDS_STATUS_SUCCESS))
  208. {
  209. bstrText = T2BSTR(csText);
  210. if (NULL != bstrText)
  211. {
  212. SetStatusText(bstrText);
  213. }
  214. }
  215. }
  216. else
  217. {
  218. if (csText.LoadString(IDS_STATUS_FAIL))
  219. {
  220. bstrText = T2BSTR(csText);
  221. if (NULL != bstrText)
  222. {
  223. SetStatusText(bstrText);
  224. }
  225. }
  226. }
  227. if (NULL != bstrText)
  228. {
  229. ::SysFreeString(bstrText);
  230. }
  231. }
  232. else
  233. {
  234. // Disable OK button
  235. ::EnableWindow( hWndOK, FALSE );
  236. if( m_lFlags & SD_BUTTON_CANCEL )
  237. {
  238. ::EnableWindow( hWndCancel, TRUE );
  239. }
  240. }
  241. }
  242. }
  243. STDMETHODIMP CStatusDlg::Display( BOOL bShow )
  244. {
  245. HRESULT hr = S_OK;
  246. if( bShow )
  247. {
  248. if( m_hThread != NULL )
  249. {
  250. if( !IsWindowVisible() ) // We are already on
  251. {
  252. ShowWindow(SW_SHOW);
  253. }
  254. }
  255. else
  256. {
  257. // Create a new thread which will DoModal the status dialog
  258. m_hThread = CreateThread( NULL, 0, DialogThreadProc, (void *) this, 0, NULL );
  259. if( NULL == m_hThread )
  260. {
  261. hr = HRESULT_FROM_WIN32(GetLastError());
  262. }
  263. else if( m_hDisplayedEvent ) // Wait till the dialog is displayed
  264. {
  265. if( WAIT_OBJECT_0 != WaitForSingleObject(m_hDisplayedEvent, INFINITE) )
  266. {
  267. hr = E_UNEXPECTED;
  268. }
  269. }
  270. }
  271. }
  272. else
  273. {
  274. // Will close the dialog
  275. if( m_hThread != NULL )
  276. {
  277. EndDialog(IDCANCEL);
  278. WaitForSingleObject(m_hThread, INFINITE);
  279. }
  280. }
  281. return hr;
  282. }
  283. // The wizard writer should call this function to wait on user response
  284. // If the user has already responded: clicked OK or Cancel
  285. // then this method will return immediately
  286. STDMETHODIMP CStatusDlg::WaitForUser( )
  287. {
  288. if( m_hThread )
  289. {
  290. WaitForSingleObject(m_hThread, INFINITE);
  291. }
  292. return S_OK;
  293. }
  294. STDMETHODIMP CStatusDlg::get_Cancelled( BOOL *pVal )
  295. {
  296. if( NULL == pVal )
  297. {
  298. return E_INVALIDARG;
  299. }
  300. if( m_lFlags & SD_BUTTON_CANCEL )
  301. {
  302. if( m_iCancelled == 0 )
  303. {
  304. *pVal = FALSE;
  305. }
  306. else
  307. {
  308. *pVal = TRUE;
  309. }
  310. }
  311. else
  312. {
  313. *pVal = FALSE;
  314. }
  315. return S_OK;
  316. }
  317. STDMETHODIMP CStatusDlg::get_ComponentProgress( IStatusProgress** pVal )
  318. {
  319. HRESULT hr = S_OK;
  320. if( NULL == pVal )
  321. {
  322. return E_INVALIDARG;
  323. }
  324. if( m_lFlags & SD_PROGRESS_COMPONENT )
  325. {
  326. // Create component progress object
  327. if( m_pComponentProgress == NULL )
  328. {
  329. hr = CComObject<CStatusProgress>::CreateInstance(&m_pComponentProgress);
  330. if( SUCCEEDED(hr) )
  331. {
  332. hr = m_pComponentProgress->AddRef();
  333. }
  334. if( SUCCEEDED(hr) && IsWindow() )
  335. {
  336. // Initialize the component progress with the progress bar handle
  337. hr = m_pComponentProgress->Initialize(this, GetDlgItem(IDC_PROGRESS1), FALSE);
  338. }
  339. }
  340. if( SUCCEEDED(hr) )
  341. {
  342. hr = (m_pComponentProgress->QueryInterface(IID_IStatusProgress, (void **) pVal));
  343. }
  344. }
  345. return hr;
  346. }
  347. LRESULT CStatusDlg::OnInitDialog( UINT uint, WPARAM wparam, LPARAM lparam, BOOL& bbool )
  348. {
  349. HWND hWndText = GetDlgItem(IDC_STATIC1);
  350. HWND hWndLV = GetDlgItem(IDC_LIST2);
  351. HWND hWndCompText = GetDlgItem(IDC_STATIC2);
  352. HWND hWndCompProgress = GetDlgItem(IDC_PROGRESS1);
  353. HWND hWndOverallText = GetDlgItem(IDC_STATIC3);
  354. HWND hWndOverallProgress = GetDlgItem(IDC_PROGRESS2);
  355. HWND hWndOK = GetDlgItem(IDOK);
  356. HWND hWndCancel = GetDlgItem(IDCANCEL);
  357. LOGFONT logFont;
  358. HIMAGELIST hILSmall;
  359. HBITMAP hBitmap;
  360. HDC hDC;
  361. TEXTMETRIC tm;
  362. RECT rect;
  363. CWindow wnd;
  364. int iResizeLV = 0;
  365. int iResize = 0;
  366. // Attach to the Listview
  367. wnd.Attach(hWndLV);
  368. wnd.GetWindowRect(&rect);
  369. hDC = GetDC();
  370. GetTextMetrics(hDC, &tm);
  371. ReleaseDC(hDC);
  372. // Check if size of the list view is OK enough to hold all the components
  373. iResizeLV = rect.bottom - rect.top - ((tm.tmHeight + 2) * (m_mapComponents.size() + 1));
  374. // Depending on the options selected, decide whether the stus dialog will shrink or expand
  375. if( (m_lFlags & SD_PROGRESS_COMPONENT) && !(m_lFlags & SD_PROGRESS_OVERALL) )
  376. {
  377. iResize = GetWindowLength(hWndOverallText, hWndOverallProgress);
  378. }
  379. else if( !(m_lFlags & SD_PROGRESS_COMPONENT) && (m_lFlags & SD_PROGRESS_OVERALL) )
  380. {
  381. iResize = GetWindowLength(hWndCompText, hWndCompProgress);
  382. }
  383. else if( !(m_lFlags & SD_PROGRESS_COMPONENT) && !(m_lFlags & SD_PROGRESS_OVERALL) )
  384. {
  385. iResize = GetWindowLength(hWndCompText, hWndOverallProgress);
  386. }
  387. // Hide component progress if necessary
  388. if( !(m_lFlags & SD_PROGRESS_COMPONENT) )
  389. {
  390. ::ShowWindow(hWndCompText, SW_HIDE);
  391. ::ShowWindow(hWndCompProgress, SW_HIDE);
  392. }
  393. // Hide overall progress if necessary
  394. if( !(m_lFlags & SD_PROGRESS_OVERALL) )
  395. {
  396. ::ShowWindow(hWndOverallText, SW_HIDE);
  397. ::ShowWindow(hWndOverallProgress, SW_HIDE);
  398. }
  399. if ((!(m_lFlags & SD_PROGRESS_OVERALL)) || (!(m_lFlags & SD_PROGRESS_COMPONENT)))
  400. {
  401. // We need to get rid of the space between the progress bars
  402. iResize -= GetWindowLength(hWndCompText, hWndOverallProgress) - GetWindowLength(hWndOverallText, hWndOverallProgress) - GetWindowLength(hWndCompText, hWndOverallProgress) + 4;
  403. }
  404. // Well, we may need to make LV bigger, but the dialog length could stay the same
  405. // if the user does not want component and/or overall progress
  406. if( iResizeLV < 0 ) // Will need to make the LV bigger
  407. {
  408. iResize += iResizeLV;
  409. }
  410. else
  411. {
  412. iResizeLV = 0; // We will not touch the LV
  413. }
  414. if( iResizeLV != 0 || iResize != 0 ) // We will need to do some moving and resizing
  415. {
  416. VerticalResizeWindow(m_hWnd, iResize);
  417. VerticalMoveWindow(hWndOK, iResize);
  418. VerticalMoveWindow(hWndCancel, iResize);
  419. // Location of progress bars completely depend on the resizing of the LV
  420. VerticalMoveWindow(hWndOverallText, iResizeLV);
  421. VerticalMoveWindow(hWndOverallProgress, iResizeLV);
  422. VerticalMoveWindow(hWndCompText, iResizeLV);
  423. VerticalMoveWindow(hWndCompProgress, iResizeLV);
  424. // Last, but not the least, resize the LV
  425. VerticalResizeWindow(hWndLV, iResizeLV);
  426. }
  427. if( !(m_lFlags & SD_BUTTON_CANCEL) ) // We will only have an OK button
  428. {
  429. LONG_PTR dwStyle = ::GetWindowLongPtr( m_hWnd, GWL_STYLE );
  430. if( 0 != dwStyle )
  431. {
  432. // Get rid of the System Menu (Close X) as well
  433. dwStyle &= ~WS_SYSMENU;
  434. ::SetWindowLongPtr( m_hWnd, GWL_STYLE, dwStyle );
  435. }
  436. ReplaceWindow(hWndCancel, hWndOK);
  437. }
  438. // if we only have overall progress, we need to move it up
  439. // so that it replaces the component progress
  440. if( (m_lFlags & SD_PROGRESS_OVERALL) && !(m_lFlags & SD_PROGRESS_COMPONENT) )
  441. {
  442. ReplaceWindow(hWndCompText, hWndOverallText);
  443. ReplaceWindow(hWndCompProgress, hWndOverallProgress);
  444. }
  445. // Set some style for the LV
  446. ::SendMessage(hWndLV, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_SUBITEMIMAGES);
  447. ::SendMessage(hWndLV, LVM_SETBKCOLOR, 0, (LPARAM) CLR_NONE);
  448. ::SendMessage(hWndLV, LVM_SETTEXTBKCOLOR, 0, (LPARAM) CLR_NONE);
  449. LVCOLUMN col;
  450. ZeroMemory (&col, sizeof(col));
  451. col.mask = LVCF_WIDTH;
  452. col.cx = 500;
  453. SendMessage( hWndLV, LVM_INSERTCOLUMN, 0, (LPARAM)&col );
  454. // Thanks to Jeffzi
  455. m_pProgressList->Attach( hWndLV );
  456. COMPONENTMAP::iterator compIterator;
  457. compIterator = m_mapComponents.begin();
  458. while( compIterator != m_mapComponents.end() )
  459. {
  460. // Add each component to the LV
  461. m_pProgressList->AddItem(compIterator->second);
  462. m_pProgressList->SetItemState(compIterator->first, IS_NONE, FALSE );
  463. compIterator++;
  464. }
  465. if( m_pComponentProgress )
  466. {
  467. // Initialize the component progress with the progress bar handle
  468. m_pComponentProgress->Initialize( this, hWndCompProgress, FALSE );
  469. }
  470. if (m_pOverallProgress)
  471. {
  472. // Initialize the overall progress with the progress bar handle
  473. m_pOverallProgress->Initialize( this, hWndOverallProgress, TRUE );
  474. }
  475. // Here comes the dialog title and text
  476. SetWindowText(m_strWindowTitle.c_str());
  477. ::SetWindowText(hWndText, m_strWindowText.c_str());
  478. SetupButtons();
  479. // Center the window, no Jeff this works just right if you have 2 monitors
  480. CenterWindow();
  481. if( m_hDisplayedEvent )
  482. {
  483. SetEvent(m_hDisplayedEvent);
  484. }
  485. return TRUE;
  486. }
  487. BOOL CStatusDlg::VerticalMoveWindow( HWND hWnd, int iResize )
  488. {
  489. BOOL bRet;
  490. CWindow wnd;
  491. RECT rect;
  492. wnd.Attach( hWnd ); // Returns void
  493. if(wnd.GetWindowRect(&rect) )
  494. {
  495. rect.top -= iResize;
  496. rect.bottom -= iResize;
  497. // GetWindowRect fills in RECT relative to the desktop
  498. // We need to make it relative to the dialog
  499. // as MoveWindow works that way
  500. if( ScreenToClient(&rect) )
  501. {
  502. bRet = wnd.MoveWindow(&rect);
  503. }
  504. else
  505. {
  506. bRet = FALSE;
  507. }
  508. }
  509. else
  510. {
  511. bRet = FALSE;
  512. }
  513. return bRet;
  514. }
  515. BOOL CStatusDlg::ReplaceWindow( HWND hWndOld, HWND hWndNew )
  516. {
  517. BOOL bRet;
  518. CWindow wnd;
  519. RECT rect;
  520. wnd.Attach(hWndOld);
  521. // Get the coordinates of the old Window
  522. if( wnd.GetWindowRect(&rect) )
  523. {
  524. // Hide it, we are trying to replace it
  525. wnd.ShowWindow(SW_HIDE);
  526. // Attach to the new one
  527. wnd.Attach(hWndNew);
  528. // Map the coordinates and move the window on top of the old one
  529. if( ScreenToClient(&rect) )
  530. {
  531. bRet = wnd.MoveWindow(&rect);
  532. }
  533. else
  534. {
  535. bRet = FALSE;
  536. }
  537. }
  538. else
  539. {
  540. bRet = FALSE;
  541. }
  542. return bRet;
  543. }
  544. BOOL CStatusDlg::VerticalResizeWindow( HWND hWnd, int iResize )
  545. {
  546. CWindow wnd;
  547. RECT rect;
  548. BOOL bRet = FALSE;
  549. if( iResize )
  550. {
  551. // Attach to the window
  552. wnd.Attach(hWnd);
  553. // Get the coordinates
  554. if( wnd.GetWindowRect(&rect) )
  555. {
  556. rect.bottom -= iResize; // Increase the bottom
  557. if( ScreenToClient(&rect) )
  558. {
  559. bRet = wnd.MoveWindow(&rect); // Resize
  560. }
  561. else
  562. {
  563. bRet= FALSE;
  564. }
  565. }
  566. else
  567. {
  568. bRet = FALSE;
  569. }
  570. }
  571. return bRet;
  572. }
  573. int CStatusDlg::GetWindowLength( HWND hWndTop, HWND hWndBottom )
  574. {
  575. CWindow wnd;
  576. RECT rect;
  577. int iTop;
  578. wnd.Attach(hWndTop);
  579. if( wnd.GetWindowRect(&rect) )
  580. {
  581. iTop = rect.top;
  582. wnd.Attach(hWndBottom);
  583. if( wnd.GetWindowRect(&rect) )
  584. {
  585. return rect.bottom - iTop;
  586. }
  587. }
  588. return 0;
  589. }
  590. STDMETHODIMP CStatusDlg::get_OverallProgress( IStatusProgress** pVal )
  591. {
  592. HRESULT hr = S_OK;
  593. if( NULL == pVal )
  594. {
  595. return E_INVALIDARG;
  596. }
  597. if( m_lFlags & SD_PROGRESS_OVERALL )
  598. {
  599. // Create component progress object
  600. if( m_pOverallProgress == NULL )
  601. {
  602. hr = CComObject<CStatusProgress>::CreateInstance(&m_pOverallProgress);
  603. if( SUCCEEDED(hr) )
  604. {
  605. hr = m_pOverallProgress->AddRef();
  606. }
  607. if( SUCCEEDED(hr) && IsWindow() )
  608. {
  609. // Initialize the overall progress with the progress bar handle
  610. hr = m_pOverallProgress->Initialize(this, GetDlgItem(IDC_PROGRESS2), TRUE);
  611. }
  612. }
  613. hr = m_pOverallProgress->QueryInterface(IID_IStatusProgress, (void **) pVal);
  614. }
  615. return hr;
  616. }
  617. BOOL CStatusDlg::AreAllComponentsDone( BOOL& bFailedComponent )
  618. {
  619. BOOL bComponentToRun = FALSE;
  620. COMPONENTMAP::iterator compIterator = m_mapComponents.begin();
  621. if( m_pProgressList )
  622. {
  623. // Look for a component that's not done
  624. while( m_pProgressList && !bComponentToRun && compIterator != m_mapComponents.end() )
  625. {
  626. CProgressItem * pPI = m_pProgressList->GetProgressItem(compIterator->first);
  627. if( NULL != pPI )
  628. {
  629. // Is the component done?
  630. if( IS_NONE == pPI->m_eState )
  631. {
  632. bComponentToRun = TRUE;
  633. }
  634. else if( IS_FAILED == pPI->m_eState )
  635. {
  636. bFailedComponent = TRUE;
  637. }
  638. }
  639. else
  640. {
  641. _ASSERT( pPI );
  642. }
  643. compIterator++;
  644. }
  645. }
  646. return !bComponentToRun;
  647. }
  648. LRESULT CStatusDlg::OnCloseCmd( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ )
  649. {
  650. EndDialog(wID);
  651. return 0;
  652. }
  653. LRESULT CStatusDlg::OnCancelCmd( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ )
  654. {
  655. HWND hWnd = NULL;
  656. if( 0 == m_iCancelled )
  657. {
  658. InterlockedIncrement((LONG *) &m_iCancelled);
  659. }
  660. // Disable the Cancel button
  661. hWnd = GetDlgItem(IDCANCEL);
  662. if( hWnd && ::IsWindow(hWnd) )
  663. {
  664. ::EnableWindow( hWnd, FALSE );
  665. }
  666. // EndDialog(wID);
  667. // Leaving it to the component to close the dialog
  668. return 0;
  669. }
  670. LRESULT CStatusDlg::OnDrawItem( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  671. {
  672. if( wParam == IDC_LIST2 )
  673. {
  674. if( m_pProgressList )
  675. {
  676. m_pProgressList->OnDrawItem( lParam );
  677. }
  678. }
  679. return 0;
  680. }
  681. LRESULT CStatusDlg::OnMeasureItem( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  682. {
  683. if( wParam == IDC_LIST2)
  684. {
  685. if( m_pProgressList )
  686. {
  687. m_pProgressList->OnMeasureItem( lParam );
  688. }
  689. }
  690. return 0;
  691. }
  692. LRESULT CStatusDlg::OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  693. {
  694. if( m_lFlags & SD_BUTTON_CANCEL ) // Cancel button?
  695. {
  696. if( ::IsWindowEnabled( GetDlgItem(IDCANCEL) ) ) // Is it enabled?
  697. {
  698. if( 0 == m_iCancelled )
  699. {
  700. InterlockedIncrement( (LONG*)&m_iCancelled );
  701. }
  702. EndDialog(0);
  703. }
  704. else if( ::IsWindowEnabled( GetDlgItem(IDOK) ) )
  705. {
  706. // it could be OK button sending WM_CLOSE or the user
  707. // As long as OK button is enabled we need to close the dialog
  708. EndDialog(1);
  709. }
  710. }
  711. else if( ::IsWindowEnabled( GetDlgItem(IDOK) ) )
  712. {
  713. EndDialog( 1 );
  714. }
  715. return 0;
  716. }
  717. LRESULT CStatusDlg::OnTimerProgress( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  718. {
  719. HRESULT hr;
  720. long lPosition;
  721. if( wParam && (m_lTimer == wParam) ) // Make sure that this is for our timer
  722. {
  723. lPosition = SendDlgItemMessage(IDC_PROGRESS1, PBM_GETPOS, 0, 0);
  724. if( lPosition < m_lMaxSteps ) // Do we still have room for progress?
  725. {
  726. SendDlgItemMessage(IDC_PROGRESS1, PBM_STEPIT, 0, 0); // Step 1
  727. SendMessage(WM_UPDATEOVERALLPROGRESS, 0, 0); // Update the overall progress
  728. }
  729. else
  730. {
  731. // There's no room to progress, we've reached the max
  732. // Let's kill the timer
  733. SendMessage(WM_KILLTIMER, 0);
  734. }
  735. }
  736. return 0;
  737. }
  738. LRESULT CStatusDlg::OnUpdateOverallProgress( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  739. {
  740. long lPosition = 0;
  741. if( m_lFlags & SD_PROGRESS_COMPONENT ) // Make sure that there's a component progress
  742. {
  743. lPosition = SendDlgItemMessage(IDC_PROGRESS1, PBM_GETPOS, 0, 0);
  744. // Update the overall progress
  745. SendDlgItemMessage(IDC_PROGRESS2, PBM_SETPOS, m_lTotalProgress + lPosition, 0);
  746. }
  747. return 0;
  748. }
  749. LRESULT CStatusDlg::OnStartTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  750. {
  751. if( !m_lTimer ) // There might be a timer already
  752. {
  753. m_lTimer = SetTimer(SD_TIMER_ID, wParam * 500); // Create a timer
  754. m_lMaxSteps = (long) lParam; // Max. not to exceed for the progress bar
  755. }
  756. return 0;
  757. }
  758. LRESULT CStatusDlg::OnKillTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  759. {
  760. if( m_lTimer ) // Is there a timer?
  761. {
  762. KillTimer( m_lTimer ); // Kill it
  763. m_lTimer = 0;
  764. m_lMaxSteps = 0;
  765. }
  766. return 0;
  767. }
  768. STDMETHODIMP CStatusDlg::SetStatusText(BSTR bstrText)
  769. {
  770. if( !bstrText ) return E_POINTER;
  771. HRESULT hr = S_OK;
  772. HWND hWnd = GetDlgItem(IDC_STATIC1);
  773. if( hWnd && ::IsWindow(hWnd) )
  774. {
  775. if( 0 == ::SetWindowText(hWnd, OLE2T(bstrText)) )
  776. {
  777. hr = HRESULT_FROM_WIN32(GetLastError());
  778. }
  779. }
  780. else
  781. {
  782. hr = E_FAIL;
  783. }
  784. return hr;
  785. }
  786. STDMETHODIMP CStatusDlg::DisplayError(BSTR bstrError, BSTR bstrTitle, DWORD dwFlags, long * pRet)
  787. {
  788. if( !bstrError || !bstrTitle || !pRet ) return E_POINTER;
  789. HRESULT hr = S_OK;
  790. *pRet = MessageBox( bstrError, bstrTitle, dwFlags );
  791. if( 0 == *pRet )
  792. {
  793. hr = HRESULT_FROM_WIN32(GetLastError());
  794. }
  795. return hr;
  796. }