Source code of Windows XP (NT5)
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.

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