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.

1845 lines
46 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // DetailsDlg.cpp
  7. //
  8. // Maintained By:
  9. // David Potter (DavidP) 27-MAR-2001
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. #include "Pch.h"
  13. #include "TaskTreeView.h"
  14. #include "DetailsDlg.h"
  15. #include "WizardUtils.h"
  16. #include "WizardHelp.h"
  17. DEFINE_THISCLASS("DetailsDlg");
  18. //////////////////////////////////////////////////////////////////////////////
  19. // Context-sensitive help table.
  20. //////////////////////////////////////////////////////////////////////////////
  21. const DWORD g_rgidDetailsDlgHelpIDs[] =
  22. {
  23. IDC_DETAILS_S_DATE, IDH_DETAILS_S_DATE,
  24. IDC_DETAILS_E_DATE, IDH_DETAILS_S_DATE,
  25. IDC_DETAILS_S_TIME, IDH_DETAILS_S_TIME,
  26. IDC_DETAILS_E_TIME, IDH_DETAILS_S_TIME,
  27. IDC_DETAILS_S_COMPUTER, IDH_DETAILS_S_COMPUTER,
  28. IDC_DETAILS_E_COMPUTER, IDH_DETAILS_S_COMPUTER,
  29. IDC_DETAILS_S_MAJOR_ID, IDH_DETAILS_S_MAJOR_ID,
  30. IDC_DETAILS_E_MAJOR_ID, IDH_DETAILS_S_MAJOR_ID,
  31. IDC_DETAILS_S_MINOR_ID, IDH_DETAILS_S_MINOR_ID,
  32. IDC_DETAILS_E_MINOR_ID, IDH_DETAILS_S_MINOR_ID,
  33. IDC_DETAILS_S_PROGRESS, IDH_DETAILS_S_PROGRESS,
  34. IDC_DETAILS_E_PROGRESS, IDH_DETAILS_S_PROGRESS,
  35. IDC_DETAILS_S_PROGRESS_UNITS, IDH_DETAILS_S_PROGRESS,
  36. IDC_DETAILS_S_STATUS, IDH_DETAILS_S_STATUS,
  37. IDC_DETAILS_RE_STATUS, IDH_DETAILS_S_STATUS,
  38. IDC_DETAILS_S_DESCRIPTION, IDH_DETAILS_S_DESCRIPTION,
  39. IDC_DETAILS_RE_DESCRIPTION, IDH_DETAILS_S_DESCRIPTION,
  40. IDC_DETAILS_S_REFERENCE, IDH_DETAILS_S_REFERENCE,
  41. IDC_DETAILS_RE_REFERENCE, IDH_DETAILS_S_REFERENCE,
  42. IDC_DETAILS_PB_PREV, IDH_DETAILS_PB_PREV,
  43. IDC_DETAILS_PB_NEXT, IDH_DETAILS_PB_NEXT,
  44. IDC_DETAILS_PB_COPY, IDH_DETAILS_PB_COPY,
  45. 0, 0
  46. };
  47. //////////////////////////////////////////////////////////////////////////////
  48. // Static Function Prototypes
  49. //////////////////////////////////////////////////////////////////////////////
  50. static
  51. BOOL
  52. ButtonFaceColorIsDark( void );
  53. static
  54. void
  55. SetButtonImage(
  56. HWND hwndBtnIn
  57. , ULONG idIconIn
  58. );
  59. static
  60. void
  61. FreeButtonImage(
  62. HWND hwndBtnIn
  63. );
  64. static
  65. HRESULT
  66. HrAppendStringToClipboardString(
  67. BSTR * pbstrClipboard
  68. , UINT idsLabelIn
  69. , LPCWSTR pszDataIn
  70. , bool fNewlineBeforeTextIn
  71. );
  72. //////////////////////////////////////////////////////////////////////////////
  73. //++
  74. //
  75. // CDetailsDlg::S_HrDisplayModalDialog
  76. //
  77. // Description:
  78. // Display the dialog box.
  79. //
  80. // Arguments:
  81. // hwndParentIn - Parent window for the dialog box.
  82. // pttvIn - Task tree view control.
  83. // htiSelectedIn - Handle to the selected item.
  84. //
  85. // Return Values:
  86. // S_OK - Operation completed successfully.
  87. //
  88. // Remarks:
  89. //
  90. //--
  91. //////////////////////////////////////////////////////////////////////////////
  92. HRESULT
  93. CDetailsDlg::S_HrDisplayModalDialog(
  94. HWND hwndParentIn
  95. , CTaskTreeView * pttvIn
  96. , HTREEITEM htiSelectedIn
  97. )
  98. {
  99. TraceFunc( "" );
  100. Assert( pttvIn != NULL );
  101. Assert( htiSelectedIn != NULL );
  102. HRESULT hr = S_OK;
  103. CDetailsDlg dlg( pttvIn, htiSelectedIn );
  104. DialogBoxParam(
  105. g_hInstance
  106. , MAKEINTRESOURCE( IDD_DETAILS )
  107. , hwndParentIn
  108. , CDetailsDlg::S_DlgProc
  109. , (LPARAM) &dlg
  110. );
  111. HRETURN( hr );
  112. } //*** CDetailsDlg::S_HrDisplayModalDialog()
  113. //////////////////////////////////////////////////////////////////////////////
  114. //++
  115. //
  116. // CDetailsDlg::CDetailsDlg
  117. //
  118. // Description:
  119. // Constructor.
  120. //
  121. // Arguments:
  122. // pttvIn - Tree view to traverse.
  123. // htiSelectedIn - Handle to the selected item in the tree control.
  124. //
  125. // Return Values:
  126. // None.
  127. //
  128. //--
  129. //////////////////////////////////////////////////////////////////////////////
  130. CDetailsDlg::CDetailsDlg(
  131. CTaskTreeView * pttvIn
  132. , HTREEITEM htiSelectedIn
  133. )
  134. {
  135. TraceFunc( "" );
  136. Assert( pttvIn != NULL );
  137. Assert( htiSelectedIn != NULL );
  138. // m_hwnd
  139. m_hiconWarn = NULL;
  140. m_hiconError = NULL;
  141. m_pttv = pttvIn;
  142. m_htiSelected = htiSelectedIn;
  143. m_fControlDown = FALSE;
  144. m_fAltDown = FALSE;
  145. TraceFuncExit();
  146. } //*** CDetailsDlg::CDetailsDlg()
  147. //////////////////////////////////////////////////////////////////////////////
  148. //++
  149. //
  150. // CDetailsDlg::~CDetailsDlg
  151. //
  152. // Description:
  153. // Destructor.
  154. //
  155. // Arguments:
  156. // None.
  157. //
  158. // Return Values:
  159. // None.
  160. //
  161. //--
  162. //////////////////////////////////////////////////////////////////////////////
  163. CDetailsDlg::~CDetailsDlg( void )
  164. {
  165. TraceFunc( "" );
  166. if ( m_hiconWarn != NULL )
  167. {
  168. DeleteObject( m_hiconWarn );
  169. }
  170. if ( m_hiconError != NULL )
  171. {
  172. DeleteObject( m_hiconError );
  173. }
  174. TraceFuncExit();
  175. } //*** CDetailsDlg::~CDetailsDlg()
  176. //////////////////////////////////////////////////////////////////////////////
  177. //++
  178. //
  179. // CDetailsDlg::S_DlgProc
  180. //
  181. // Description:
  182. // Dialog proc for the Details dialog box.
  183. //
  184. // Arguments:
  185. // hwndDlgIn - Dialog box window handle.
  186. // nMsgIn - Message ID.
  187. // wParam - Message-specific parameter.
  188. // lParam - Message-specific parameter.
  189. //
  190. // Return Values:
  191. // TRUE - Message was processed by this procedure.
  192. // FALSE - Message was NOT processed by this procedure.
  193. //
  194. // Remarks:
  195. // It is expected that this dialog box is invoked by a call to
  196. // DialogBoxParam() with the lParam argument set to the address of the
  197. // instance of this class.
  198. //
  199. //--
  200. //////////////////////////////////////////////////////////////////////////////
  201. INT_PTR
  202. CALLBACK
  203. CDetailsDlg::S_DlgProc(
  204. HWND hwndDlgIn
  205. , UINT nMsgIn
  206. , WPARAM wParam
  207. , LPARAM lParam
  208. )
  209. {
  210. // Don't do TraceFunc because every mouse movement
  211. // will cause this function to be called.
  212. WndMsg( hwndDlgIn, nMsgIn, wParam, lParam );
  213. LRESULT lr = FALSE;
  214. CDetailsDlg * pdlg;
  215. //
  216. // Get a pointer to the class.
  217. //
  218. if ( nMsgIn == WM_INITDIALOG )
  219. {
  220. SetWindowLongPtr( hwndDlgIn, GWLP_USERDATA, lParam );
  221. pdlg = reinterpret_cast< CDetailsDlg * >( lParam );
  222. pdlg->m_hwnd = hwndDlgIn;
  223. }
  224. else
  225. {
  226. pdlg = reinterpret_cast< CDetailsDlg * >( GetWindowLongPtr( hwndDlgIn, GWLP_USERDATA ) );
  227. }
  228. if ( pdlg != NULL )
  229. {
  230. Assert( hwndDlgIn == pdlg->m_hwnd );
  231. switch( nMsgIn )
  232. {
  233. case WM_INITDIALOG:
  234. lr = pdlg->OnInitDialog();
  235. break;
  236. case WM_DESTROY:
  237. pdlg->OnDestroy();
  238. break;
  239. case WM_SYSCOLORCHANGE:
  240. pdlg->OnSysColorChange();
  241. break;
  242. case WM_NOTIFY:
  243. lr = pdlg->OnNotify( wParam, reinterpret_cast< LPNMHDR >( lParam ) );
  244. break;
  245. case WM_COMMAND:
  246. lr = pdlg->OnCommand( HIWORD( wParam ), LOWORD( wParam ), reinterpret_cast< HWND >( lParam ) );
  247. break;
  248. case WM_KEYDOWN:
  249. lr = pdlg->OnKeyDown( lParam );
  250. break;
  251. case WM_KEYUP:
  252. lr = pdlg->OnKeyUp( lParam );
  253. break;
  254. case WM_HELP:
  255. WinHelp(
  256. (HWND)((LPHELPINFO) lParam)->hItemHandle,
  257. CLUSCFG_HELP_FILE,
  258. HELP_WM_HELP,
  259. (ULONG_PTR) g_rgidDetailsDlgHelpIDs
  260. );
  261. break;
  262. case WM_CONTEXTMENU:
  263. WinHelp(
  264. (HWND)wParam,
  265. CLUSCFG_HELP_FILE,
  266. HELP_CONTEXTMENU,
  267. (ULONG_PTR) g_rgidDetailsDlgHelpIDs
  268. );
  269. break;
  270. default:
  271. lr = FALSE;
  272. } // switch: nMsgIn
  273. } // if: page is specified
  274. return lr;
  275. } //*** CDetailsDlg::S_DlgProc()
  276. //////////////////////////////////////////////////////////////////////////////
  277. //++
  278. //
  279. // CDetailsDlg::OnInitDialog
  280. //
  281. // Description:
  282. // Handler for the WM_INITDIALOG message.
  283. //
  284. // Arguments:
  285. // None.
  286. //
  287. // Return Values:
  288. // TRUE Focus has been set.
  289. // FALSE Focus has not been set.
  290. //--
  291. //////////////////////////////////////////////////////////////////////////////
  292. LRESULT
  293. CDetailsDlg::OnInitDialog( void )
  294. {
  295. TraceFunc( "" );
  296. LRESULT lr = TRUE; // did set focus
  297. HWND hwnd;
  298. //
  299. // Tell the rich edit controls we want to receive notifications of clicks
  300. // on text that has the link (hyperlink, aka URL) format. Also, set the
  301. // background color of the rich edit to match the background color of
  302. // the dialog.
  303. //
  304. hwnd = GetDlgItem( m_hwnd, IDC_DETAILS_RE_DESCRIPTION );
  305. SendMessage( hwnd, EM_SETEVENTMASK, 0, ENM_LINK );
  306. SendMessage( hwnd, EM_SETBKGNDCOLOR, 0, GetSysColor( COLOR_BTNFACE ) );
  307. SendMessage( hwnd, EM_AUTOURLDETECT, TRUE, 0 );
  308. hwnd = GetDlgItem( m_hwnd, IDC_DETAILS_RE_STATUS );
  309. SendMessage( hwnd, EM_SETEVENTMASK, 0, ENM_LINK );
  310. SendMessage( hwnd, EM_SETBKGNDCOLOR, 0, GetSysColor( COLOR_BTNFACE ) );
  311. SendMessage( hwnd, EM_AUTOURLDETECT, TRUE, 0 );
  312. hwnd = GetDlgItem( m_hwnd, IDC_DETAILS_RE_REFERENCE );
  313. SendMessage( hwnd, EM_SETEVENTMASK, 0, ENM_LINK );
  314. SendMessage( hwnd, EM_SETBKGNDCOLOR, 0, GetSysColor( COLOR_BTNFACE ) );
  315. SendMessage( hwnd, EM_AUTOURLDETECT, TRUE, 0 );
  316. //
  317. // Set the icons for the icon pushbuttons
  318. //
  319. OnSysColorChange();
  320. SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_COPY ), IDI_COPY );
  321. //
  322. // Load the status icons.
  323. //
  324. m_hiconWarn = (HICON) LoadImage(
  325. g_hInstance
  326. , MAKEINTRESOURCE( IDI_WARN )
  327. , IMAGE_ICON
  328. , 16
  329. , 16
  330. , LR_SHARED
  331. );
  332. Assert( m_hiconWarn != NULL );
  333. m_hiconError = (HICON) LoadImage(
  334. g_hInstance
  335. , MAKEINTRESOURCE( IDI_FAIL )
  336. , IMAGE_ICON
  337. , 16
  338. , 16
  339. , LR_SHARED
  340. );
  341. Assert( m_hiconError != NULL );
  342. //
  343. // Display the selected item.
  344. //
  345. THR( HrDisplayItem( m_htiSelected ) );
  346. //
  347. // Update the buttons based on what is selected.
  348. //
  349. UpdateButtons();
  350. //
  351. // Set focus to the OK button.
  352. //
  353. SetFocus( GetDlgItem( m_hwnd, IDOK ) );
  354. RETURN( lr );
  355. } //*** CDetailsDlg::OnInitDialog()
  356. //////////////////////////////////////////////////////////////////////////////
  357. //++
  358. //
  359. // CDetailsDlg::OnDestroy
  360. //
  361. // Description:
  362. // Handler for the WM_DESTROY message.
  363. //
  364. // Arguments:
  365. // None.
  366. //
  367. // Return Values:
  368. // None.
  369. //
  370. //--
  371. //////////////////////////////////////////////////////////////////////////////
  372. void
  373. CDetailsDlg::OnDestroy( void )
  374. {
  375. TraceFunc( "" );
  376. //
  377. // Destroy the images loaded for the icon pushbuttons
  378. //
  379. FreeButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ) );
  380. FreeButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ) );
  381. FreeButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_COPY ) );
  382. TraceFuncExit();
  383. } //*** CDetailsDlg::OnDestroy()
  384. //////////////////////////////////////////////////////////////////////////////
  385. //++
  386. //
  387. // CDetailsDlg::OnSysColorChange
  388. //
  389. // Description:
  390. // Handler for the WM_SYSCOLORCHANGE message.
  391. //
  392. // Arguments:
  393. // None.
  394. //
  395. // Return Values:
  396. // None.
  397. //
  398. //--
  399. //////////////////////////////////////////////////////////////////////////////
  400. void
  401. CDetailsDlg::OnSysColorChange( void )
  402. {
  403. TraceFunc( "" );
  404. if ( ButtonFaceColorIsDark() )
  405. {
  406. SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ), IDI_PREVIOUS_HC );
  407. SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ), IDI_NEXT_HC );
  408. }
  409. else
  410. {
  411. SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ), IDI_PREVIOUS );
  412. SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ), IDI_NEXT );
  413. }
  414. SendDlgItemMessage(
  415. m_hwnd
  416. , IDC_DETAILS_RE_DESCRIPTION
  417. , EM_SETBKGNDCOLOR
  418. , 0
  419. , GetSysColor( COLOR_BTNFACE )
  420. );
  421. TraceFuncExit();
  422. } //*** CDetailsDlg::OnSysColorChange()
  423. //////////////////////////////////////////////////////////////////////////////
  424. //++
  425. //
  426. // CDetailsDlg::OnKeyDown
  427. //
  428. // Description:
  429. // Handler for the WM_KEYDOWN message.
  430. //
  431. // Arguments:
  432. // lParamIn - Parameter containing information about the key.
  433. //
  434. // Return Values:
  435. // TRUE - Message was processed.
  436. // FALSE - Message was not processed.
  437. //
  438. //--
  439. //////////////////////////////////////////////////////////////////////////////
  440. LRESULT
  441. CDetailsDlg::OnKeyDown(
  442. LPARAM lParamIn
  443. )
  444. {
  445. TraceFunc( "" );
  446. LRESULT lr = FALSE;
  447. union
  448. {
  449. LPARAM lParam;
  450. struct
  451. {
  452. BYTE cRepeat;
  453. BYTE nScanCode;
  454. unsigned fExtendedKey : 1;
  455. unsigned reserved : 4;
  456. unsigned fIsAltKeyDown : 1; // always 0 for WM_KEYDOWN
  457. unsigned fKeyDownBefore : 1;
  458. unsigned fKeyReleased : 1; // always 0 for WM_KEYDOWN
  459. };
  460. } uFlags;
  461. uFlags.lParam = lParamIn;
  462. switch ( uFlags.nScanCode )
  463. {
  464. case VK_CONTROL:
  465. m_fControlDown = TRUE;
  466. lr = TRUE;
  467. break;
  468. case VK_MENU: // ALT
  469. m_fAltDown = TRUE;
  470. lr = TRUE;
  471. break;
  472. case 'c':
  473. case 'C':
  474. if ( m_fControlDown )
  475. {
  476. OnCommandBnClickedCopy();
  477. lr = TRUE;
  478. }
  479. break;
  480. } // switch: scan code
  481. RETURN( lr );
  482. } //*** CDetailsDlg::OnKeyDown()
  483. //////////////////////////////////////////////////////////////////////////////
  484. //++
  485. //
  486. // CDetailsDlg::OnKeyUp
  487. //
  488. // Description:
  489. // Handler for the WM_KEYUP message.
  490. //
  491. // Arguments:
  492. // lParamIn - Parameter containing information about the key.
  493. //
  494. // Return Values:
  495. // TRUE - Message was processed.
  496. // FALSE - Message was not processed.
  497. //
  498. //--
  499. //////////////////////////////////////////////////////////////////////////////
  500. LRESULT
  501. CDetailsDlg::OnKeyUp(
  502. LPARAM lParamIn
  503. )
  504. {
  505. TraceFunc( "" );
  506. LRESULT lr = FALSE;
  507. union
  508. {
  509. LPARAM lParam;
  510. struct
  511. {
  512. BYTE cRepeat;
  513. BYTE nScanCode;
  514. unsigned fExtendedKey : 1;
  515. unsigned reserved : 4;
  516. unsigned fIsAltKeyDown : 1; // always 0 for WM_KEYDOWN
  517. unsigned fKeyDownBefore : 1;
  518. unsigned fKeyReleased : 1; // always 0 for WM_KEYDOWN
  519. };
  520. } uFlags;
  521. uFlags.lParam = lParamIn;
  522. switch ( uFlags.nScanCode )
  523. {
  524. case VK_CONTROL:
  525. m_fControlDown = FALSE;
  526. lr = TRUE;
  527. break;
  528. case VK_MENU: // ALT
  529. m_fAltDown = FALSE;
  530. lr = TRUE;
  531. break;
  532. } // switch: scan code
  533. RETURN( lr );
  534. } //*** CDetailsDlg::OnKeyUp()
  535. //////////////////////////////////////////////////////////////////////////////
  536. //++
  537. //
  538. // CDetailsDlg::OnCommand
  539. //
  540. // Description:
  541. // Handler for the WM_COMMAND message.
  542. //
  543. // Arguments:
  544. // idNotificationIn - Notification code.
  545. // idControlIn - Control ID.
  546. // hwndSenderIn - Handle for the window that sent the message.
  547. //
  548. // Return Values:
  549. // TRUE - Message has been handled.
  550. // FALSE - Message has not been handled yet.
  551. //
  552. //--
  553. //////////////////////////////////////////////////////////////////////////////
  554. LRESULT
  555. CDetailsDlg::OnCommand(
  556. UINT idNotificationIn
  557. , UINT idControlIn
  558. , HWND hwndSenderIn
  559. )
  560. {
  561. TraceFunc( "" );
  562. LRESULT lr = FALSE;
  563. switch ( idControlIn )
  564. {
  565. case IDC_DETAILS_PB_PREV:
  566. if ( idNotificationIn == BN_CLICKED )
  567. {
  568. lr = OnCommandBnClickedPrev();
  569. }
  570. break;
  571. case IDC_DETAILS_PB_NEXT:
  572. if ( idNotificationIn == BN_CLICKED )
  573. {
  574. lr = OnCommandBnClickedNext();
  575. }
  576. break;
  577. case IDC_DETAILS_PB_COPY:
  578. if ( idNotificationIn == BN_CLICKED )
  579. {
  580. lr = OnCommandBnClickedCopy();
  581. }
  582. break;
  583. case IDCANCEL:
  584. EndDialog( m_hwnd, IDCANCEL );
  585. break;
  586. } // switch: idControlIn
  587. RETURN( lr );
  588. } //*** CDetailsDlg::OnCommand()
  589. //////////////////////////////////////////////////////////////////////////////
  590. //++
  591. //
  592. // CDetailsDlg::OnCommandBnClickedPrev
  593. //
  594. // Description:
  595. // Handler for the BN_CLICKED notification on the Prev button.
  596. //
  597. // Arguments:
  598. // None.
  599. //
  600. // Return Values:
  601. // TRUE - Message has been handled.
  602. // FALSE - Message has not been handled yet.
  603. //
  604. //--
  605. //////////////////////////////////////////////////////////////////////////////
  606. LRESULT
  607. CDetailsDlg::OnCommandBnClickedPrev( void )
  608. {
  609. TraceFunc( "" );
  610. LRESULT lr = FALSE;
  611. HRESULT hr;
  612. HTREEITEM htiPrev;
  613. //
  614. // Find the previous item.
  615. //
  616. hr = STHR( m_pttv->HrFindPrevItem( &htiPrev ) );
  617. if ( FAILED( hr ) )
  618. {
  619. goto Cleanup;
  620. }
  621. //
  622. // Select that item.
  623. //
  624. hr = THR( m_pttv->HrSelectItem( htiPrev ) );
  625. if ( FAILED( hr ) )
  626. {
  627. goto Cleanup;
  628. }
  629. //
  630. // Display the newly selected item.
  631. //
  632. if ( htiPrev != NULL )
  633. {
  634. hr = THR( HrDisplayItem( htiPrev ) );
  635. }
  636. //
  637. // Update the buttons based on our new position.
  638. //
  639. UpdateButtons();
  640. lr = TRUE;
  641. Cleanup:
  642. RETURN( lr );
  643. } //*** CDetailsDlg::OnCommandBnClickedPrev()
  644. //////////////////////////////////////////////////////////////////////////////
  645. //++
  646. //
  647. // CDetailsDlg::OnCommandBnClickedNext
  648. //
  649. // Description:
  650. // Handler for the BN_CLICKED notification on the Next button.
  651. //
  652. // Arguments:
  653. // None.
  654. //
  655. // Return Values:
  656. // TRUE - Message has been handled.
  657. // FALSE - Message has not been handled yet.
  658. //
  659. //--
  660. //////////////////////////////////////////////////////////////////////////////
  661. LRESULT
  662. CDetailsDlg::OnCommandBnClickedNext( void )
  663. {
  664. TraceFunc( "" );
  665. LRESULT lr = FALSE;
  666. HRESULT hr;
  667. HTREEITEM htiNext;
  668. //
  669. // Find the next item.
  670. //
  671. hr = STHR( m_pttv->HrFindNextItem( &htiNext ) );
  672. if ( FAILED( hr ) )
  673. {
  674. goto Cleanup;
  675. }
  676. //
  677. // Select that item.
  678. //
  679. hr = THR( m_pttv->HrSelectItem( htiNext ) );
  680. if ( FAILED( hr ) )
  681. {
  682. goto Cleanup;
  683. }
  684. //
  685. // Display the newly selected item.
  686. //
  687. if ( htiNext != NULL )
  688. {
  689. hr = THR( HrDisplayItem( htiNext ) );
  690. }
  691. //
  692. // Update the buttons based on our new position.
  693. //
  694. UpdateButtons();
  695. lr = TRUE;
  696. Cleanup:
  697. RETURN( lr );
  698. } //*** CDetailsDlg::OnCommandBnClickedNext()
  699. //////////////////////////////////////////////////////////////////////////////
  700. //++
  701. //
  702. // CDetailsDlg::OnCommandBnClickedCopy
  703. //
  704. // Description:
  705. // Handler for the BN_CLICKED notification on the Copy button.
  706. //
  707. // Arguments:
  708. // None.
  709. //
  710. // Return Values:
  711. // TRUE - Message has been handled.
  712. // FALSE - Message has not been handled yet.
  713. //
  714. //--
  715. //////////////////////////////////////////////////////////////////////////////
  716. LRESULT
  717. CDetailsDlg::OnCommandBnClickedCopy( void )
  718. {
  719. TraceFunc( "" );
  720. LRESULT lr = FALSE;
  721. HRESULT hr;
  722. DWORD sc;
  723. BSTR bstrClipboard = NULL;
  724. HGLOBAL hgbl = NULL;
  725. LPWSTR pszGlobal = NULL;
  726. BOOL fOpenedClipboard;
  727. //
  728. // Open the clipboard.
  729. //
  730. fOpenedClipboard = OpenClipboard( m_hwnd );
  731. if ( ! fOpenedClipboard )
  732. {
  733. sc = TW32( GetLastError() );
  734. hr = HRESULT_FROM_WIN32( sc );
  735. TraceFlow2( "Can't open clipboard (error = %#08x), currently owned by %#x", sc, GetClipboardOwner() );
  736. goto Cleanup;
  737. }
  738. if ( ! EmptyClipboard() )
  739. {
  740. sc = TW32( GetLastError() );
  741. hr = HRESULT_FROM_WIN32( sc );
  742. goto Cleanup;
  743. }
  744. //
  745. // Construct the text to put on the clipboard.
  746. //
  747. hr = THR( HrAppendControlStringToClipboardString(
  748. &bstrClipboard
  749. , IDS_DETAILS_CLP_DATE
  750. , IDC_DETAILS_E_DATE
  751. , false // fNewlineBeforeTextIn
  752. ) );
  753. if ( FAILED( hr ) )
  754. {
  755. goto Cleanup;
  756. }
  757. hr = THR( HrAppendControlStringToClipboardString(
  758. &bstrClipboard
  759. , IDS_DETAILS_CLP_TIME
  760. , IDC_DETAILS_E_TIME
  761. , false // fNewlineBeforeTextIn
  762. ) );
  763. if ( FAILED( hr ) )
  764. {
  765. goto Cleanup;
  766. }
  767. hr = THR( HrAppendControlStringToClipboardString(
  768. &bstrClipboard
  769. , IDS_DETAILS_CLP_COMPUTER
  770. , IDC_DETAILS_E_COMPUTER
  771. , false // fNewlineBeforeTextIn
  772. ) );
  773. if ( FAILED( hr ) )
  774. {
  775. goto Cleanup;
  776. }
  777. hr = THR( HrAppendControlStringToClipboardString(
  778. &bstrClipboard
  779. , IDS_DETAILS_CLP_MAJOR
  780. , IDC_DETAILS_E_MAJOR_ID
  781. , false // fNewlineBeforeTextIn
  782. ) );
  783. if ( FAILED( hr ) )
  784. {
  785. goto Cleanup;
  786. }
  787. hr = THR( HrAppendControlStringToClipboardString(
  788. &bstrClipboard
  789. , IDS_DETAILS_CLP_MINOR
  790. , IDC_DETAILS_E_MINOR_ID
  791. , false // fNewlineBeforeTextIn
  792. ) );
  793. if ( FAILED( hr ) )
  794. {
  795. goto Cleanup;
  796. }
  797. hr = THR( HrAppendControlStringToClipboardString(
  798. &bstrClipboard
  799. , IDS_DETAILS_CLP_PROGRESS
  800. , IDC_DETAILS_E_PROGRESS
  801. , false // fNewlineBeforeTextIn
  802. ) );
  803. if ( FAILED( hr ) )
  804. {
  805. goto Cleanup;
  806. }
  807. hr = THR( HrAppendControlStringToClipboardString(
  808. &bstrClipboard
  809. , IDS_DETAILS_CLP_DESC
  810. , IDC_DETAILS_RE_DESCRIPTION
  811. , true // fNewlineBeforeTextIn
  812. ) );
  813. if ( FAILED( hr ) )
  814. {
  815. goto Cleanup;
  816. }
  817. hr = THR( HrAppendControlStringToClipboardString(
  818. &bstrClipboard
  819. , IDS_DETAILS_CLP_STATUS
  820. , IDC_DETAILS_E_STATUS
  821. , false // fNewlineBeforeTextIn
  822. ) );
  823. if ( FAILED( hr ) )
  824. {
  825. goto Cleanup;
  826. }
  827. hr = THR( HrAppendControlStringToClipboardString(
  828. &bstrClipboard
  829. , 0
  830. , IDC_DETAILS_RE_STATUS
  831. , false // fNewlineBeforeTextIn
  832. ) );
  833. if ( FAILED( hr ) )
  834. {
  835. goto Cleanup;
  836. }
  837. hr = THR( HrAppendControlStringToClipboardString(
  838. &bstrClipboard
  839. , IDS_DETAILS_CLP_INFO
  840. , IDC_DETAILS_RE_REFERENCE
  841. , true // fNewlineBeforeTextIn
  842. ) );
  843. if ( FAILED( hr ) )
  844. {
  845. goto Cleanup;
  846. }
  847. //
  848. // Set the string onto the clipboard.
  849. //
  850. {
  851. //
  852. // Allocate a global buffer for the string, since
  853. // clipboard needs this as HGLOBAL.
  854. //
  855. SIZE_T cchClipboardAndNull = SysStringLen( bstrClipboard ) + 1;
  856. hgbl = GlobalAlloc(
  857. GMEM_MOVEABLE | GMEM_DDESHARE
  858. , cchClipboardAndNull * sizeof( *bstrClipboard )
  859. );
  860. if ( hgbl == NULL )
  861. {
  862. hr = THR( E_OUTOFMEMORY );
  863. goto Cleanup;
  864. }
  865. pszGlobal = (LPWSTR) GlobalLock( hgbl );
  866. if ( pszGlobal == NULL )
  867. {
  868. sc = TW32( GetLastError() );
  869. hr = HRESULT_FROM_WIN32( sc );
  870. goto Cleanup;
  871. }
  872. hr = THR( StringCchCopyW( pszGlobal, cchClipboardAndNull, bstrClipboard ) );
  873. if ( FAILED( hr ) )
  874. {
  875. goto Cleanup;
  876. }
  877. //
  878. // Put it on the clipboard.
  879. //
  880. if ( SetClipboardData( CF_UNICODETEXT, hgbl ) )
  881. {
  882. // System owns it now.
  883. pszGlobal = NULL;
  884. hgbl = NULL;
  885. }
  886. } // Set the string onto the clipboard
  887. Cleanup:
  888. TraceSysFreeString( bstrClipboard );
  889. if ( pszGlobal != NULL )
  890. {
  891. GlobalUnlock( hgbl );
  892. }
  893. GlobalFree( hgbl );
  894. if ( fOpenedClipboard )
  895. {
  896. CloseClipboard();
  897. }
  898. RETURN( lr );
  899. } //*** CDetailsDlg::OnCommandBnClickedCopy()
  900. //////////////////////////////////////////////////////////////////////////////
  901. //++
  902. //
  903. // CDetailsDlg::HrAppendControlStringToClipboardString
  904. //
  905. // Description:
  906. // Append a string from a control on the dialog box to the clipboard string.
  907. //
  908. // Arguments:
  909. // pbstrClipboardInout - Clipboard string.
  910. // idsLabelIn - ID for the label string resource.
  911. // idcDataIn - ID for the control to read the text from.
  912. // fNewlineBeforeTextIn- TRUE if a newline should be added before the data.
  913. //
  914. // Return Values:
  915. // S_OK - Operation completed successfully.
  916. //
  917. //--
  918. //////////////////////////////////////////////////////////////////////////////
  919. HRESULT
  920. CDetailsDlg::HrAppendControlStringToClipboardString(
  921. BSTR * pbstrClipboard
  922. , UINT idsLabelIn
  923. , UINT idcDataIn
  924. , bool fNewlineBeforeTextIn
  925. )
  926. {
  927. TraceFunc( "" );
  928. HRESULT hr = S_OK;
  929. LPWSTR pszData = NULL;
  930. HWND hwndControl = GetDlgItem( m_hwnd, idcDataIn );
  931. int cch;
  932. //
  933. // Get the string from the control.
  934. //
  935. cch = GetWindowTextLength( hwndControl );
  936. pszData = new WCHAR[ cch + 1 ];
  937. if ( pszData == NULL )
  938. {
  939. hr = THR( E_OUTOFMEMORY );
  940. goto Cleanup;
  941. }
  942. GetWindowText( hwndControl, pszData, cch + 1 );
  943. //
  944. // Append the string to the clipboard string.
  945. //
  946. hr = THR( HrAppendStringToClipboardString( pbstrClipboard, idsLabelIn, pszData, fNewlineBeforeTextIn ) );
  947. if ( FAILED( hr ) )
  948. {
  949. goto Cleanup;
  950. }
  951. Cleanup:
  952. delete [] pszData;
  953. HRETURN( hr );
  954. } //*** HrAppendControlStringToClipboardString()
  955. //////////////////////////////////////////////////////////////////////////////
  956. //++
  957. //
  958. // HrAppendStringToClipboardString
  959. //
  960. // Description:
  961. // Append a label and data string to the clipboard string.
  962. //
  963. // Arguments:
  964. // pbstrClipboardInout - Clipboard string.
  965. // idsLabelIn - ID for the label string resource.
  966. // pszDataIn - Data string.
  967. // fNewlineBeforeTextIn- TRUE if a newline should be added before the data.
  968. //
  969. // Return Values:
  970. // S_OK - Operation completed successfully.
  971. //
  972. //--
  973. //////////////////////////////////////////////////////////////////////////////
  974. HRESULT
  975. HrAppendStringToClipboardString(
  976. BSTR * pbstrClipboard
  977. , UINT idsLabelIn
  978. , LPCWSTR pszDataIn
  979. , bool fNewlineBeforeTextIn
  980. )
  981. {
  982. TraceFunc( "" );
  983. HRESULT hr = S_OK;
  984. BSTR bstrLabel = NULL;
  985. BSTR bstr = NULL;
  986. LPCWSTR pszLabel;
  987. LPCWSTR pszFmt;
  988. static const WCHAR s_szBlank[] = L"";
  989. static const WCHAR s_szNoNewlineFmt[] = L"%1!ws!%2!ws!\n";
  990. static const WCHAR s_szNewlineFmt[] = L"%1!ws!\n%2!ws!\n";
  991. //
  992. // Load the label string.
  993. //
  994. if ( idsLabelIn == 0 )
  995. {
  996. pszLabel = s_szBlank;
  997. }
  998. else
  999. {
  1000. hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsLabelIn, &bstrLabel ) );
  1001. if ( FAILED( hr ) )
  1002. {
  1003. goto Cleanup;
  1004. }
  1005. pszLabel = bstrLabel;
  1006. }
  1007. //
  1008. // Get the right format string.
  1009. //
  1010. if ( fNewlineBeforeTextIn )
  1011. {
  1012. pszFmt = s_szNewlineFmt;
  1013. }
  1014. else
  1015. {
  1016. pszFmt = s_szNoNewlineFmt;
  1017. }
  1018. //
  1019. // Get the string from the dialog.
  1020. //
  1021. //
  1022. // Format the new label + string.
  1023. //
  1024. hr = THR( HrFormatStringIntoBSTR( pszFmt, &bstr, pszLabel, pszDataIn ) );
  1025. if ( FAILED( hr ) )
  1026. {
  1027. goto Cleanup;
  1028. }
  1029. //
  1030. // Concatenate the resulting string onto the end of the clipboard string.
  1031. //
  1032. hr = THR( HrConcatenateBSTRs( pbstrClipboard, bstr ) );
  1033. if ( FAILED( hr ) )
  1034. {
  1035. goto Cleanup;
  1036. }
  1037. Cleanup:
  1038. TraceSysFreeString( bstrLabel );
  1039. TraceSysFreeString( bstr );
  1040. HRETURN( hr );
  1041. } //*** HrAppendStringToClipboardString()
  1042. //////////////////////////////////////////////////////////////////////////////
  1043. //++
  1044. //
  1045. // CDetailsDlg::OnNotify
  1046. //
  1047. // Description:
  1048. // Handle the WM_NOTIFY message.
  1049. //
  1050. // Arguments:
  1051. // idCtrlIn - Control ID.
  1052. // pnmhdrIn - Notification structure.
  1053. //
  1054. // Return Values:
  1055. // TRUE - Message has been handled.
  1056. // FALSE - Message has not been handled yet.
  1057. //
  1058. //--
  1059. //////////////////////////////////////////////////////////////////////////////
  1060. LRESULT
  1061. CDetailsDlg::OnNotify(
  1062. WPARAM idCtrlIn
  1063. , LPNMHDR pnmhdrIn
  1064. )
  1065. {
  1066. TraceFunc( "" );
  1067. LRESULT lr = FALSE;
  1068. switch( pnmhdrIn->code )
  1069. {
  1070. case EN_LINK:
  1071. lr = OnNotifyEnLink( idCtrlIn, pnmhdrIn );
  1072. break;
  1073. } // switch: notify code
  1074. RETURN( lr );
  1075. } //*** CDetailsDlg::OnNotify()
  1076. //////////////////////////////////////////////////////////////////////////////
  1077. //++
  1078. //
  1079. // CDetailsDlg::OnNotifyEnLink
  1080. //
  1081. // Description:
  1082. // Handle the WM_NOTIFY message.
  1083. //
  1084. // Arguments:
  1085. // idCtrlIn - Control ID.
  1086. // pnmhdrIn - Notification structure.
  1087. //
  1088. // Return Values:
  1089. // TRUE - Message has been handled.
  1090. // FALSE - Message has not been handled yet.
  1091. //
  1092. //--
  1093. //////////////////////////////////////////////////////////////////////////////
  1094. LRESULT
  1095. CDetailsDlg::OnNotifyEnLink(
  1096. WPARAM idCtrlIn
  1097. , LPNMHDR pnmhdrIn
  1098. )
  1099. {
  1100. TraceFunc( "" );
  1101. LRESULT lr = FALSE;
  1102. ENLINK * penl = (ENLINK *) pnmhdrIn;
  1103. switch( idCtrlIn )
  1104. {
  1105. case IDC_DETAILS_RE_DESCRIPTION:
  1106. case IDC_DETAILS_RE_STATUS:
  1107. case IDC_DETAILS_RE_REFERENCE:
  1108. if ( penl->msg == WM_LBUTTONDOWN )
  1109. {
  1110. //
  1111. // Rich edit notification user has left clicked on link
  1112. //
  1113. m_chrgEnLinkClick = penl->chrg;
  1114. } // if: left button down
  1115. else if ( penl->msg == WM_LBUTTONUP )
  1116. {
  1117. if ( ( penl->chrg.cpMax == m_chrgEnLinkClick.cpMax )
  1118. && ( penl->chrg.cpMin == m_chrgEnLinkClick.cpMin )
  1119. )
  1120. {
  1121. ZeroMemory( &m_chrgEnLinkClick, sizeof m_chrgEnLinkClick );
  1122. HandleLinkClick( penl, idCtrlIn );
  1123. }
  1124. } // else if: left button up
  1125. break;
  1126. } // switch: notify code
  1127. RETURN( lr );
  1128. } //*** CDetailsDlg::OnNotifyEnLink()
  1129. //////////////////////////////////////////////////////////////////////////////
  1130. //++
  1131. //
  1132. // CDetailsDlg::HandleLinkClick
  1133. //
  1134. // Description:
  1135. // Handle notification that the user has clicked on text in a richedit
  1136. // control that is marked with the hyperlink attribute.
  1137. //
  1138. // Arguments:
  1139. // penlIn - Contains information about link clicked.
  1140. // idCtrlIn - Control in which user clicked.
  1141. //
  1142. // Return Values:
  1143. // None.
  1144. //
  1145. //--
  1146. //////////////////////////////////////////////////////////////////////////////
  1147. void
  1148. CDetailsDlg::HandleLinkClick(
  1149. ENLINK * penlIn
  1150. , WPARAM idCtrlIn
  1151. )
  1152. {
  1153. TraceFunc( "" );
  1154. Assert( penlIn->chrg.cpMax > penlIn->chrg.cpMin );
  1155. PWSTR pszLink = NULL;
  1156. ULONG cch;
  1157. TEXTRANGE tr;
  1158. DWORD sc;
  1159. //
  1160. // Get the text of the link.
  1161. //
  1162. cch = penlIn->chrg.cpMax - penlIn->chrg.cpMin + 1;
  1163. pszLink = new WCHAR[ cch ];
  1164. if ( pszLink == NULL )
  1165. {
  1166. goto Cleanup;
  1167. }
  1168. pszLink[ 0 ] = '\0';
  1169. ZeroMemory( &tr, sizeof( tr ) );
  1170. tr.chrg = penlIn->chrg;
  1171. tr.lpstrText = pszLink;
  1172. cch = (ULONG) SendDlgItemMessage(
  1173. m_hwnd
  1174. , (int) idCtrlIn
  1175. , EM_GETTEXTRANGE
  1176. , 0
  1177. , (LPARAM) &tr
  1178. );
  1179. Assert( cch > 0 );
  1180. //
  1181. // Pass the URL straight through to ShellExecute.
  1182. //
  1183. // Note that ShellExecute returns an HINSTANCE for historical reasons,
  1184. // but actually only returns integers. Any value greater than 32
  1185. // indicates success.
  1186. //
  1187. TraceFlow1( "Calling ShellExecute on %hs", pszLink );
  1188. sc = HandleToULong( ShellExecute( NULL, NULL, pszLink, NULL, NULL, SW_NORMAL ) );
  1189. if ( sc <= 32 )
  1190. {
  1191. TW32( sc );
  1192. THR( HrMessageBoxWithStatus(
  1193. m_hwnd
  1194. , IDS_ERR_INVOKING_LINK_TITLE
  1195. , IDS_ERR_INVOKING_LINK_TEXT
  1196. , sc
  1197. , 0 // idsSubStatusIn
  1198. , ( MB_OK
  1199. | MB_ICONEXCLAMATION )
  1200. , NULL // pidReturnOut
  1201. , pszLink
  1202. ) );
  1203. } // if: error from ShellExecute
  1204. Cleanup:
  1205. delete [] pszLink;
  1206. TraceFuncExit();
  1207. } //*** CDetailsDlg::HandleLinkClick()
  1208. //////////////////////////////////////////////////////////////////////////////
  1209. //++
  1210. //
  1211. // CDetailsDlg::UpdateButtons
  1212. //
  1213. // Description:
  1214. // Update the buttons based on whether there is a previous or next
  1215. // item or not.
  1216. //
  1217. // Arguments:
  1218. // None.
  1219. //
  1220. // Return Values:
  1221. // None.
  1222. //
  1223. //--
  1224. //////////////////////////////////////////////////////////////////////////////
  1225. void
  1226. CDetailsDlg::UpdateButtons( void )
  1227. {
  1228. TraceFunc( "" );
  1229. Assert( m_pttv != NULL );
  1230. HTREEITEM hti = NULL;
  1231. BOOL fEnablePrev;
  1232. BOOL fEnableNext;
  1233. STHR( m_pttv->HrFindPrevItem( &hti ) );
  1234. // ignore error
  1235. fEnablePrev = ( hti != NULL );
  1236. STHR( m_pttv->HrFindNextItem( &hti ) );
  1237. // ignore error
  1238. fEnableNext = ( hti != NULL );
  1239. EnableWindow( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ), fEnablePrev );
  1240. EnableWindow( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ), fEnableNext );
  1241. TraceFuncExit();
  1242. } //*** CDetailsDlg::UpdateButtons()
  1243. //////////////////////////////////////////////////////////////////////////////
  1244. //++
  1245. //
  1246. // CDetailsDlg::HrDisplayItem
  1247. //
  1248. // Description:
  1249. // Display an item in the details dialog.
  1250. //
  1251. // Arguments:
  1252. // htiIn - Handle to the item to display.
  1253. //
  1254. // Return Values:
  1255. // S_OK - Operation completed successfully.
  1256. // S_FALSE - Item not displayed.
  1257. //
  1258. // Remarks:
  1259. //
  1260. //--
  1261. //////////////////////////////////////////////////////////////////////////////
  1262. HRESULT
  1263. CDetailsDlg::HrDisplayItem(
  1264. HTREEITEM htiIn
  1265. )
  1266. {
  1267. TraceFunc( "" );
  1268. Assert( htiIn != NULL );
  1269. HRESULT hr = S_FALSE;
  1270. DWORD sc = ERROR_SUCCESS;
  1271. BOOL fRet;
  1272. BOOL fDisplayIcon = FALSE;
  1273. STreeItemLParamData * ptipd;
  1274. BSTR bstr = NULL;
  1275. BSTR bstrAdditionalInfo = NULL;
  1276. WCHAR wszText[ 64 ];
  1277. FILETIME filetime;
  1278. SYSTEMTIME systemtime;
  1279. int cch;
  1280. HICON hicon;
  1281. HRESULT hrNewStatus = S_OK;
  1282. //
  1283. // Get information about the selected item to see if it has details.
  1284. //
  1285. fRet = m_pttv->FGetItem( htiIn, &ptipd );
  1286. if ( ! fRet )
  1287. {
  1288. goto Cleanup;
  1289. }
  1290. //
  1291. // Set the date and time information from the structure into
  1292. // the dialog box.
  1293. //
  1294. if ( ( ptipd->ftTime.dwHighDateTime == 0 )
  1295. && ( ptipd->ftTime.dwLowDateTime == 0 )
  1296. )
  1297. {
  1298. SetDlgItemText( m_hwnd, IDC_DETAILS_E_DATE, L"" );
  1299. SetDlgItemText( m_hwnd, IDC_DETAILS_E_TIME, L"" );
  1300. } // if: no date time specified
  1301. else
  1302. {
  1303. //
  1304. // Convert the date time to local time, then to something we can
  1305. // use to display it.
  1306. //
  1307. if ( ! FileTimeToLocalFileTime( &ptipd->ftTime, &filetime ) )
  1308. {
  1309. sc = TW32( GetLastError() );
  1310. }
  1311. else if ( ! FileTimeToSystemTime( &filetime, &systemtime ) )
  1312. {
  1313. sc = TW32( GetLastError() );
  1314. }
  1315. if ( sc == ERROR_SUCCESS )
  1316. {
  1317. //
  1318. // Get the date string and display it.
  1319. //
  1320. cch = GetDateFormat(
  1321. LOCALE_USER_DEFAULT
  1322. , DATE_SHORTDATE
  1323. , &systemtime
  1324. , NULL // lpFormat
  1325. , wszText
  1326. , ARRAYSIZE( wszText )
  1327. );
  1328. if ( cch == 0 )
  1329. {
  1330. sc = TW32( GetLastError() );
  1331. }
  1332. SetDlgItemText( m_hwnd, IDC_DETAILS_E_DATE, wszText );
  1333. //
  1334. // Get the time string and display it.
  1335. //
  1336. cch = GetTimeFormat(
  1337. LOCALE_USER_DEFAULT
  1338. , 0
  1339. , &systemtime
  1340. , NULL // lpFormat
  1341. , wszText
  1342. , ARRAYSIZE( wszText )
  1343. );
  1344. if ( cch == 0 )
  1345. {
  1346. sc = TW32( GetLastError() );
  1347. }
  1348. SetDlgItemText( m_hwnd, IDC_DETAILS_E_TIME, wszText );
  1349. } // if: time converted successfully
  1350. else
  1351. {
  1352. SetDlgItemText( m_hwnd, IDC_DETAILS_E_DATE, L"" );
  1353. SetDlgItemText( m_hwnd, IDC_DETAILS_E_TIME, L"" );
  1354. }
  1355. } // else: date time specified
  1356. //
  1357. // Set the task IDs.
  1358. //
  1359. THR( HrFormatGuidIntoBSTR( &ptipd->clsidMajorTaskId, &bstr ) );
  1360. if ( SUCCEEDED( hr ) )
  1361. {
  1362. SetDlgItemText( m_hwnd, IDC_DETAILS_E_MAJOR_ID, bstr );
  1363. }
  1364. hr = THR( HrFormatGuidIntoBSTR( &ptipd->clsidMinorTaskId, &bstr ) );
  1365. if ( SUCCEEDED( hr ) )
  1366. {
  1367. SetDlgItemText( m_hwnd, IDC_DETAILS_E_MINOR_ID, bstr );
  1368. }
  1369. //
  1370. // Set the progress information.
  1371. //
  1372. hr = THR( HrFormatStringIntoBSTR( L"%1!d!, %2!d!, %3!d!", &bstr, ptipd->nMin, ptipd->nMax, ptipd->nCurrent ) );
  1373. if ( SUCCEEDED( hr ) )
  1374. {
  1375. SetDlgItemText( m_hwnd, IDC_DETAILS_E_PROGRESS, bstr );
  1376. }
  1377. else
  1378. {
  1379. SetDlgItemText( m_hwnd, IDC_DETAILS_E_PROGRESS, L"" );
  1380. }
  1381. //
  1382. // Set the text information.
  1383. //
  1384. // Node name.
  1385. if ( ptipd->bstrNodeName == NULL )
  1386. {
  1387. SetDlgItemText( m_hwnd, IDC_DETAILS_E_COMPUTER, L"" );
  1388. }
  1389. else
  1390. {
  1391. SetDlgItemText( m_hwnd, IDC_DETAILS_E_COMPUTER, ptipd->bstrNodeName );
  1392. }
  1393. // Description.
  1394. if ( ptipd->bstrDescription == NULL )
  1395. {
  1396. SetDlgItemText( m_hwnd, IDC_DETAILS_RE_DESCRIPTION, L"" );
  1397. }
  1398. else
  1399. {
  1400. SetDlgItemText( m_hwnd, IDC_DETAILS_RE_DESCRIPTION, ptipd->bstrDescription );
  1401. }
  1402. // Reference.
  1403. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_DEFAULT_DETAILS_REFERENCE, &bstrAdditionalInfo ) );
  1404. if ( SUCCEEDED( hr ) )
  1405. {
  1406. if ( ( ptipd->bstrReference == NULL )
  1407. || ( *ptipd->bstrReference == L'\0' )
  1408. )
  1409. {
  1410. TraceSysFreeString( bstr );
  1411. bstr = bstrAdditionalInfo;
  1412. bstrAdditionalInfo = NULL;
  1413. } // if: no reference specified
  1414. else
  1415. {
  1416. hr = THR( HrFormatStringIntoBSTR( L"%1!ws!\n\n%2!ws!", &bstr, ptipd->bstrReference, bstrAdditionalInfo ) );
  1417. } // else: reference specified
  1418. }
  1419. SetDlgItemText( m_hwnd, IDC_DETAILS_RE_REFERENCE, bstr );
  1420. //
  1421. // Set the status information.
  1422. //
  1423. if ( ptipd->hr == S_FALSE )
  1424. {
  1425. hr = THR( HrFormatStringIntoBSTR( L"S_FALSE", &bstr ) );
  1426. hrNewStatus = S_FALSE;
  1427. }
  1428. else
  1429. {
  1430. hr = THR( HrFormatErrorIntoBSTR( ptipd->hr, &bstr, &hrNewStatus ) );
  1431. } // else: hr not S_FALSE
  1432. //
  1433. // If we got an updated status code then we need to use a new format
  1434. // string that shows both the old and the new status codes.
  1435. //
  1436. if ( hrNewStatus != ptipd->hr )
  1437. {
  1438. THR( StringCchPrintfW( wszText, ARRAYSIZE( wszText ), L"%#08x (%#08x)", ptipd->hr, hrNewStatus ) );
  1439. } // if:
  1440. else
  1441. {
  1442. THR( StringCchPrintfW( wszText, ARRAYSIZE( wszText ), L"%#08x", ptipd->hr ) );
  1443. } // else:
  1444. SetDlgItemText( m_hwnd, IDC_DETAILS_E_STATUS, wszText );
  1445. if ( SUCCEEDED( hr ) )
  1446. {
  1447. Assert( bstr != NULL );
  1448. SetDlgItemText( m_hwnd, IDC_DETAILS_RE_STATUS, bstr );
  1449. if ( ptipd->hr == S_OK )
  1450. {
  1451. fDisplayIcon = FALSE;
  1452. }
  1453. else
  1454. {
  1455. fDisplayIcon = TRUE;
  1456. if ( FAILED( ptipd->hr ) )
  1457. {
  1458. hicon = m_hiconError;
  1459. }
  1460. else
  1461. {
  1462. hicon = m_hiconWarn;
  1463. }
  1464. SendDlgItemMessage( m_hwnd, IDC_DETAILS_I_STATUS, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hicon );
  1465. } // else: status not informational
  1466. }
  1467. ShowWindow( GetDlgItem( m_hwnd, IDC_DETAILS_I_STATUS ), fDisplayIcon ? SW_SHOW : SW_HIDE );
  1468. hr = S_OK;
  1469. Cleanup:
  1470. TraceSysFreeString( bstr );
  1471. TraceSysFreeString( bstrAdditionalInfo );
  1472. HRETURN( hr );
  1473. } //*** CDetailsDlg::HrDisplayItem()
  1474. //****************************************************************************
  1475. //
  1476. // Private Functions
  1477. //
  1478. //****************************************************************************
  1479. //////////////////////////////////////////////////////////////////////////////
  1480. //++
  1481. //
  1482. // ButtonFaceColorIsDark
  1483. //
  1484. // Description:
  1485. // Return TRUE if the button face color is dark (implying that
  1486. // the light colored button icons should be used).
  1487. //
  1488. // Arguments:
  1489. // None.
  1490. //
  1491. // Return Values:
  1492. // TRUE - Button face color is dark.
  1493. // FALSE - Button face color is light.
  1494. //
  1495. //--
  1496. //////////////////////////////////////////////////////////////////////////////
  1497. BOOL
  1498. ButtonFaceColorIsDark( void )
  1499. {
  1500. TraceFunc( "" );
  1501. COLORREF rgbBtnFace = GetSysColor( COLOR_BTNFACE );
  1502. ULONG nColors = GetRValue( rgbBtnFace ) +
  1503. GetGValue( rgbBtnFace ) +
  1504. GetBValue( rgbBtnFace );
  1505. RETURN( nColors < 300 ); // arbitrary threshold
  1506. } //*** ButtonFaceColorIsDark()
  1507. //////////////////////////////////////////////////////////////////////////////
  1508. //++
  1509. //
  1510. // SetButtonImage
  1511. //
  1512. // Description:
  1513. // Set an image on a button.
  1514. //
  1515. // Arguments:
  1516. // hwndBtnIn - Handle to the button window.
  1517. // idIconIn - ID for the icon resource.
  1518. //
  1519. // Return Values:
  1520. // None.
  1521. //
  1522. //--
  1523. //////////////////////////////////////////////////////////////////////////////
  1524. void
  1525. SetButtonImage(
  1526. HWND hwndBtnIn
  1527. , ULONG idIconIn
  1528. )
  1529. {
  1530. TraceFunc( "" );
  1531. HICON hIcon = (HICON) LoadImage( g_hInstance,
  1532. MAKEINTRESOURCE( idIconIn ),
  1533. IMAGE_ICON,
  1534. 16,
  1535. 16,
  1536. LR_DEFAULTCOLOR
  1537. );
  1538. if ( hIcon != NULL )
  1539. {
  1540. HICON hIconPrev = (HICON) SendMessage( hwndBtnIn,
  1541. BM_SETIMAGE,
  1542. (WPARAM) IMAGE_ICON,
  1543. (LPARAM) hIcon
  1544. );
  1545. if ( hIconPrev )
  1546. {
  1547. DestroyIcon( hIconPrev );
  1548. }
  1549. }
  1550. TraceFuncExit();
  1551. } //*** SetButtonImage()
  1552. //////////////////////////////////////////////////////////////////////////////
  1553. //++
  1554. //
  1555. // FreeButtonImage
  1556. //
  1557. // Description:
  1558. // Free an image used by button.
  1559. //
  1560. // Arguments:
  1561. // hwndBtnIn - Handle to the button window.
  1562. //
  1563. // Return Values:
  1564. // None.
  1565. //
  1566. //--
  1567. //////////////////////////////////////////////////////////////////////////////
  1568. void
  1569. FreeButtonImage(
  1570. HWND hwndBtnIn
  1571. )
  1572. {
  1573. HANDLE hIcon = (HANDLE) SendMessage( hwndBtnIn, BM_GETIMAGE, IMAGE_ICON, 0 );
  1574. if ( hIcon != NULL )
  1575. {
  1576. SendMessage( hwndBtnIn, BM_SETIMAGE, IMAGE_ICON, 0 );
  1577. DestroyIcon( (HICON) hIcon );
  1578. }
  1579. } //*** FreeButtonImage()