////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2001 Microsoft Corporation // // Module Name: // DetailsDlg.cpp // // Maintained By: // David Potter (DavidP) 27-MAR-2001 // ////////////////////////////////////////////////////////////////////////////// #include "Pch.h" #include "TaskTreeView.h" #include "DetailsDlg.h" #include "WizardUtils.h" DEFINE_THISCLASS("DetailsDlg"); ////////////////////////////////////////////////////////////////////////////// // Static Function Prototypes ////////////////////////////////////////////////////////////////////////////// static BOOL ButtonFaceColorIsDark( void ); static void SetButtonImage( HWND hwndBtnIn , ULONG idIconIn ); static void FreeButtonImage( HWND hwndBtnIn ); static HRESULT HrAppendStringToClipboardString( BSTR * pbstrClipboard , UINT idsLabelIn , LPCWSTR pszDataIn , bool fNewlineBeforeTextIn ); ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::S_HrDisplayModalDialog // // Description: // Display the dialog box. // // Arguments: // hwndParentIn - Parent window for the dialog box. // pttvIn - Task tree view control. // htiSelectedIn - Handle to the selected item. // // Return Values: // S_OK - Operation completed successfully. // // Remarks: // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT CDetailsDlg::S_HrDisplayModalDialog( HWND hwndParentIn , CTaskTreeView * pttvIn , HTREEITEM htiSelectedIn ) { TraceFunc( "" ); Assert( pttvIn != NULL ); Assert( htiSelectedIn != NULL ); HRESULT hr = S_OK; CDetailsDlg dlg( pttvIn, htiSelectedIn ); DialogBoxParam( g_hInstance , MAKEINTRESOURCE( IDD_DETAILS ) , hwndParentIn , CDetailsDlg::S_DlgProc , (LPARAM) &dlg ); HRETURN( hr ); } //*** CDetailsDlg::S_HrDisplayModalDialog() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::CDetailsDlg // // Description: // Constructor. // // Arguments: // pttvIn - Tree view to traverse. // htiSelectedIn - Handle to the selected item in the tree control. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// CDetailsDlg::CDetailsDlg( CTaskTreeView * pttvIn , HTREEITEM htiSelectedIn ) { TraceFunc( "" ); Assert( pttvIn != NULL ); Assert( htiSelectedIn != NULL ); // m_hwnd m_hiconWarn = NULL; m_hiconError = NULL; m_pttv = pttvIn; m_htiSelected = htiSelectedIn; m_fControlDown = FALSE; m_fAltDown = FALSE; TraceFuncExit(); } //*** CDetailsDlg::CDetailsDlg() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::~CDetailsDlg // // Description: // Destructor. // // Arguments: // None. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// CDetailsDlg::~CDetailsDlg( void ) { TraceFunc( "" ); if ( m_hiconWarn != NULL ) { DeleteObject( m_hiconWarn ); } if ( m_hiconError != NULL ) { DeleteObject( m_hiconError ); } TraceFuncExit(); } //*** CDetailsDlg::~CDetailsDlg() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::S_DlgProc // // Description: // Dialog proc for the Details dialog box. // // Arguments: // hwndDlgIn - Dialog box window handle. // nMsgIn - Message ID. // wParam - Message-specific parameter. // lParam - Message-specific parameter. // // Return Values: // TRUE - Message was processed by this procedure. // FALSE - Message was NOT processed by this procedure. // // Remarks: // It is expected that this dialog box is invoked by a call to // DialogBoxParam() with the lParam argument set to the address of the // instance of this class. // //-- ////////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK CDetailsDlg::S_DlgProc( HWND hwndDlgIn , UINT nMsgIn , WPARAM wParam , LPARAM lParam ) { // Don't do TraceFunc because every mouse movement // will cause this function to be called. WndMsg( hwndDlgIn, nMsgIn, wParam, lParam ); LRESULT lr = FALSE; HACCEL haccel = NULL; CDetailsDlg * pdlg; // // Get a pointer to the class. // if ( nMsgIn == WM_INITDIALOG ) { SetWindowLongPtr( hwndDlgIn, GWLP_USERDATA, lParam ); pdlg = reinterpret_cast< CDetailsDlg * >( lParam ); pdlg->m_hwnd = hwndDlgIn; } else { pdlg = reinterpret_cast< CDetailsDlg * >( GetWindowLongPtr( hwndDlgIn, GWLP_USERDATA ) ); } if ( pdlg != NULL ) { Assert( hwndDlgIn == pdlg->m_hwnd ); switch( nMsgIn ) { case WM_INITDIALOG: lr = pdlg->OnInitDialog(); break; case WM_DESTROY: pdlg->OnDestroy(); break; case WM_SYSCOLORCHANGE: pdlg->OnSysColorChange(); break; case WM_NOTIFY: lr = pdlg->OnNotify( wParam, reinterpret_cast< LPNMHDR >( lParam ) ); break; case WM_COMMAND: lr = pdlg->OnCommand( HIWORD( wParam ), LOWORD( wParam ), reinterpret_cast< HWND >( lParam ) ); break; case WM_KEYDOWN: lr = pdlg->OnKeyDown( lParam ); break; case WM_KEYUP: lr = pdlg->OnKeyUp( lParam ); break; default: lr = FALSE; } // switch: nMsgIn } // if: page is specified return lr; } //*** CDetailsDlg::S_DlgProc() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnInitDialog // // Description: // Handler for the WM_INITDIALOG message. // // Arguments: // None. // // Return Values: // TRUE Focus has been set. // FALSE Focus has not been set. //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnInitDialog( void ) { TraceFunc( "" ); LRESULT lr = TRUE; // did set focus HWND hwnd; // // Tell the rich edit controls we want to receive notifications of clicks // on text that has the link (hyperlink, aka URL) format. Also, set the // background color of the rich edit to match the background color of // the dialog. // hwnd = GetDlgItem( m_hwnd, IDC_DETAILS_RE_DESCRIPTION ); SendMessage( hwnd, EM_SETEVENTMASK, 0, ENM_LINK ); SendMessage( hwnd, EM_SETBKGNDCOLOR, 0, GetSysColor( COLOR_BTNFACE ) ); SendMessage( hwnd, EM_AUTOURLDETECT, TRUE, 0 ); hwnd = GetDlgItem( m_hwnd, IDC_DETAILS_RE_STATUS ); SendMessage( hwnd, EM_SETEVENTMASK, 0, ENM_LINK ); SendMessage( hwnd, EM_SETBKGNDCOLOR, 0, GetSysColor( COLOR_BTNFACE ) ); SendMessage( hwnd, EM_AUTOURLDETECT, TRUE, 0 ); hwnd = GetDlgItem( m_hwnd, IDC_DETAILS_RE_REFERENCE ); SendMessage( hwnd, EM_SETEVENTMASK, 0, ENM_LINK ); SendMessage( hwnd, EM_SETBKGNDCOLOR, 0, GetSysColor( COLOR_BTNFACE ) ); SendMessage( hwnd, EM_AUTOURLDETECT, TRUE, 0 ); // // Set the icons for the icon pushbuttons // OnSysColorChange(); SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_COPY ), IDI_COPY ); // // Load the status icons. // m_hiconWarn = (HICON) LoadImage( g_hInstance , MAKEINTRESOURCE( IDI_WARN ) , IMAGE_ICON , 16 , 16 , LR_SHARED ); Assert( m_hiconWarn != NULL ); m_hiconError = (HICON) LoadImage( g_hInstance , MAKEINTRESOURCE( IDI_FAIL ) , IMAGE_ICON , 16 , 16 , LR_SHARED ); Assert( m_hiconError != NULL ); // // Display the selected item. // THR( HrDisplayItem( m_htiSelected ) ); // // Update the buttons based on what is selected. // UpdateButtons(); // // Set focus to the OK button. // SetFocus( GetDlgItem( m_hwnd, IDOK ) ); RETURN( lr ); } //*** CDetailsDlg::OnInitDialog() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnDestroy // // Description: // Handler for the WM_DESTROY message. // // Arguments: // None. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// void CDetailsDlg::OnDestroy( void ) { TraceFunc( "" ); // // Destroy the images loaded for the icon pushbuttons // FreeButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ) ); FreeButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ) ); FreeButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_COPY ) ); } //*** CDetailsDlg::OnDestroy() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnSysColorChange // // Description: // Handler for the WM_SYSCOLORCHANGE message. // // Arguments: // None. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// void CDetailsDlg::OnSysColorChange( void ) { TraceFunc( "" ); if ( ButtonFaceColorIsDark() ) { SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ), IDI_PREVIOUS_HC ); SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ), IDI_NEXT_HC ); } else { SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ), IDI_PREVIOUS ); SetButtonImage( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ), IDI_NEXT ); } SendDlgItemMessage( m_hwnd , IDC_DETAILS_RE_DESCRIPTION , EM_SETBKGNDCOLOR , 0 , GetSysColor( COLOR_BTNFACE ) ); TraceFuncExit(); } //*** CDetailsDlg::OnSysColorChange() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnKeyDown // // Description: // Handler for the WM_KEYDOWN message. // // Arguments: // lParamIn - Parameter containing information about the key. // // Return Values: // TRUE - Message was processed. // FALSE - Message was not processed. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnKeyDown( LPARAM lParamIn ) { TraceFunc( "" ); LRESULT lr = FALSE; union { LPARAM lParam; struct { BYTE cRepeat; BYTE nScanCode; unsigned fExtendedKey : 1; unsigned reserved : 4; unsigned fIsAltKeyDown : 1; // always 0 for WM_KEYDOWN unsigned fKeyDownBefore : 1; unsigned fKeyReleased : 1; // always 0 for WM_KEYDOWN }; } uFlags; uFlags.lParam = lParamIn; switch ( uFlags.nScanCode ) { case VK_CONTROL: m_fControlDown = TRUE; lr = TRUE; break; case VK_MENU: // ALT m_fAltDown = TRUE; lr = TRUE; break; case 'c': case 'C': if ( m_fControlDown ) { OnCommandBnClickedCopy(); lr = TRUE; } break; } // switch: scan code RETURN( lr ); } //*** CDetailsDlg::OnKeyDown() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnKeyUp // // Description: // Handler for the WM_KEYUP message. // // Arguments: // lParamIn - Parameter containing information about the key. // // Return Values: // TRUE - Message was processed. // FALSE - Message was not processed. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnKeyUp( LPARAM lParamIn ) { TraceFunc( "" ); LRESULT lr = FALSE; union { LPARAM lParam; struct { BYTE cRepeat; BYTE nScanCode; unsigned fExtendedKey : 1; unsigned reserved : 4; unsigned fIsAltKeyDown : 1; // always 0 for WM_KEYDOWN unsigned fKeyDownBefore : 1; unsigned fKeyReleased : 1; // always 0 for WM_KEYDOWN }; } uFlags; uFlags.lParam = lParamIn; switch ( uFlags.nScanCode ) { case VK_CONTROL: m_fControlDown = FALSE; lr = TRUE; break; case VK_MENU: // ALT m_fAltDown = FALSE; lr = TRUE; break; } // switch: scan code RETURN( lr ); } //*** CDetailsDlg::OnKeyUp() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnCommand // // Description: // Handler for the WM_COMMAND message. // // Arguments: // idNotificationIn - Notification code. // idControlIn - Control ID. // hwndSenderIn - Handle for the window that sent the message. // // Return Values: // TRUE - Message has been handled. // FALSE - Message has not been handled yet. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnCommand( UINT idNotificationIn , UINT idControlIn , HWND hwndSenderIn ) { TraceFunc( "" ); LRESULT lr = FALSE; switch ( idControlIn ) { case IDC_DETAILS_PB_PREV: if ( idNotificationIn == BN_CLICKED ) { lr = OnCommandBnClickedPrev(); } break; case IDC_DETAILS_PB_NEXT: if ( idNotificationIn == BN_CLICKED ) { lr = OnCommandBnClickedNext(); } break; case IDC_DETAILS_PB_COPY: if ( idNotificationIn == BN_CLICKED ) { lr = OnCommandBnClickedCopy(); } break; case IDCANCEL: EndDialog( m_hwnd, IDCANCEL ); break; } // switch: idControlIn RETURN( lr ); } //*** CDetailsDlg::OnCommand() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnCommandBnClickedPrev // // Description: // Handler for the BN_CLICKED notification on the Prev button. // // Arguments: // None. // // Return Values: // TRUE - Message has been handled. // FALSE - Message has not been handled yet. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnCommandBnClickedPrev( void ) { TraceFunc( "" ); LRESULT lr = FALSE; HRESULT hr; HTREEITEM htiPrev; // // Find the previous item. // hr = STHR( m_pttv->HrFindPrevItem( &htiPrev ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Select that item. // hr = THR( m_pttv->HrSelectItem( htiPrev ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Display the newly selected item. // if ( htiPrev != NULL ) { hr = THR( HrDisplayItem( htiPrev ) ); } // // Update the buttons based on our new position. // UpdateButtons(); lr = TRUE; Cleanup: RETURN( lr ); } //*** CDetailsDlg::OnCommandBnClickedPrev() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnCommandBnClickedNext // // Description: // Handler for the BN_CLICKED notification on the Next button. // // Arguments: // None. // // Return Values: // TRUE - Message has been handled. // FALSE - Message has not been handled yet. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnCommandBnClickedNext( void ) { TraceFunc( "" ); LRESULT lr = FALSE; HRESULT hr; HTREEITEM htiNext; // // Find the next item. // hr = STHR( m_pttv->HrFindNextItem( &htiNext ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Select that item. // hr = THR( m_pttv->HrSelectItem( htiNext ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Display the newly selected item. // if ( htiNext != NULL ) { hr = THR( HrDisplayItem( htiNext ) ); } // // Update the buttons based on our new position. // UpdateButtons(); lr = TRUE; Cleanup: RETURN( lr ); } //*** CDetailsDlg::OnCommandBnClickedNext() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnCommandBnClickedCopy // // Description: // Handler for the BN_CLICKED notification on the Copy button. // // Arguments: // None. // // Return Values: // TRUE - Message has been handled. // FALSE - Message has not been handled yet. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnCommandBnClickedCopy( void ) { TraceFunc( "" ); LRESULT lr = FALSE; HRESULT hr; DWORD sc; BSTR bstrClipboard = NULL; HGLOBAL hgbl = NULL; LPWSTR pszGlobal = NULL; BOOL fOpenedClipboard; // // Open the clipboard. // fOpenedClipboard = OpenClipboard( m_hwnd ); if ( ! fOpenedClipboard ) { sc = TW32( GetLastError() ); hr = HRESULT_FROM_WIN32( sc ); TraceFlow2( "Can't open clipboard (error = %#08x), currently owned by %#x", sc, GetClipboardOwner() ); goto Cleanup; } if ( ! EmptyClipboard() ) { sc = TW32( GetLastError() ); hr = HRESULT_FROM_WIN32( sc ); goto Cleanup; } // // Construct the text to put on the clipboard. // hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_DATE , IDC_DETAILS_E_DATE , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_TIME , IDC_DETAILS_E_TIME , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_COMPUTER , IDC_DETAILS_E_COMPUTER , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_MAJOR , IDC_DETAILS_E_MAJOR_ID , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_MINOR , IDC_DETAILS_E_MINOR_ID , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_DESC , IDC_DETAILS_RE_DESCRIPTION , true // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_STATUS , IDC_DETAILS_E_STATUS , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , 0 , IDC_DETAILS_RE_STATUS , false // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrAppendControlStringToClipboardString( &bstrClipboard , IDS_DETAILS_CLP_INFO , IDC_DETAILS_RE_REFERENCE , true // fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Set the string onto the clipboard. // { // // Allocate a global buffer for the string, since // clipboard needs this as HGLOBAL. // hgbl = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE , ( wcslen( bstrClipboard ) + 1) * sizeof( *bstrClipboard ) ); if ( hgbl == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } pszGlobal = (LPWSTR) GlobalLock( hgbl ); if ( pszGlobal == NULL ) { sc = TW32( GetLastError() ); hr = HRESULT_FROM_WIN32( sc ); goto Cleanup; } wcscpy( pszGlobal, bstrClipboard ); // // Put it on the clipboard. // if ( SetClipboardData( CF_UNICODETEXT, hgbl ) ) { // System owns it now. pszGlobal = NULL; hgbl = NULL; } } // Set the string onto the clipboard Cleanup: TraceSysFreeString( bstrClipboard ); if ( pszGlobal != NULL ) { GlobalUnlock( hgbl ); } GlobalFree( hgbl ); if ( fOpenedClipboard ) { CloseClipboard(); } RETURN( lr ); } //*** CDetailsDlg::OnCommandBnClickedCopy() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::HrAppendControlStringToClipboardString // // Description: // Append a string from a control on the dialog box to the clipboard string. // // Arguments: // pbstrClipboardInout - Clipboard string. // idsLabelIn - ID for the label string resource. // idcDataIn - ID for the control to read the text from. // fNewlineBeforeTextIn- TRUE if a newline should be added before the data. // // Return Values: // S_OK - Operation completed successfully. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT CDetailsDlg::HrAppendControlStringToClipboardString( BSTR * pbstrClipboard , UINT idsLabelIn , UINT idcDataIn , bool fNewlineBeforeTextIn ) { TraceFunc( "" ); HRESULT hr = S_OK; LPWSTR pszData = NULL; HWND hwndControl = GetDlgItem( m_hwnd, idcDataIn ); int cch; // // Get the string from the control. // cch = GetWindowTextLength( hwndControl ); pszData = new WCHAR[ cch + 1 ]; if ( pszData == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } GetWindowText( hwndControl, pszData, cch + 1 ); // // Append the string to the clipboard string. // hr = THR( HrAppendStringToClipboardString( pbstrClipboard, idsLabelIn, pszData, fNewlineBeforeTextIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } Cleanup: delete [] pszData; HRETURN( hr ); } //*** HrAppendControlStringToClipboardString() ////////////////////////////////////////////////////////////////////////////// //++ // // HrAppendStringToClipboardString // // Description: // Append a label and data string to the clipboard string. // // Arguments: // pbstrClipboardInout - Clipboard string. // idsLabelIn - ID for the label string resource. // pszDataIn - Data string. // fNewlineBeforeTextIn- TRUE if a newline should be added before the data. // // Return Values: // S_OK - Operation completed successfully. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrAppendStringToClipboardString( BSTR * pbstrClipboard , UINT idsLabelIn , LPCWSTR pszDataIn , bool fNewlineBeforeTextIn ) { TraceFunc( "" ); HRESULT hr = S_OK; BSTR bstrLabel = NULL; BSTR bstr = NULL; LPCWSTR pszLabel; LPCWSTR pszFmt; static const WCHAR s_szBlank[] = L""; static const WCHAR s_szNoNewlineFmt[] = L"%1!ws!%2!ws!\n"; static const WCHAR s_szNewlineFmt[] = L"%1!ws!\n%2!ws!\n"; // // Load the label string. // if ( idsLabelIn == 0 ) { pszLabel = s_szBlank; } else { hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsLabelIn, &bstrLabel ) ); if ( FAILED( hr ) ) { goto Cleanup; } pszLabel = bstrLabel; } // // Get the right format string. // if ( fNewlineBeforeTextIn ) { pszFmt = s_szNewlineFmt; } else { pszFmt = s_szNoNewlineFmt; } // // Get the string from the dialog. // // // Format the new label + string. // hr = THR( HrFormatStringIntoBSTR( pszFmt, &bstr, pszLabel, pszDataIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Concatenate the resulting string onto the end of the clipboard string. // hr = THR( HrConcatenateBSTRs( pbstrClipboard, bstr ) ); if ( FAILED( hr ) ) { goto Cleanup; } Cleanup: TraceSysFreeString( bstrLabel ); TraceSysFreeString( bstr ); HRETURN( hr ); } //*** HrAppendStringToClipboardString() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnNotify // // Description: // Handle the WM_NOTIFY message. // // Arguments: // idCtrlIn - Control ID. // pnmhdrIn - Notification structure. // // Return Values: // TRUE - Message has been handled. // FALSE - Message has not been handled yet. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnNotify( WPARAM idCtrlIn , LPNMHDR pnmhdrIn ) { TraceFunc( "" ); LRESULT lr = FALSE; switch( pnmhdrIn->code ) { case EN_LINK: lr = OnNotifyEnLink( idCtrlIn, pnmhdrIn ); break; } // switch: notify code RETURN( lr ); } //*** CDetailsDlg::OnNotify() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::OnNotifyEnLink // // Description: // Handle the WM_NOTIFY message. // // Arguments: // idCtrlIn - Control ID. // pnmhdrIn - Notification structure. // // Return Values: // TRUE - Message has been handled. // FALSE - Message has not been handled yet. // //-- ////////////////////////////////////////////////////////////////////////////// LRESULT CDetailsDlg::OnNotifyEnLink( WPARAM idCtrlIn , LPNMHDR pnmhdrIn ) { TraceFunc( "" ); LRESULT lr = FALSE; ENLINK * penl = (ENLINK *) pnmhdrIn; switch( idCtrlIn ) { case IDC_DETAILS_RE_DESCRIPTION: case IDC_DETAILS_RE_STATUS: case IDC_DETAILS_RE_REFERENCE: if ( penl->msg == WM_LBUTTONDOWN ) { // // Rich edit notification user has left clicked on link // m_chrgEnLinkClick = penl->chrg; } // if: left button down else if ( penl->msg == WM_LBUTTONUP ) { if ( ( penl->chrg.cpMax == m_chrgEnLinkClick.cpMax ) && ( penl->chrg.cpMin == m_chrgEnLinkClick.cpMin ) ) { ZeroMemory( &m_chrgEnLinkClick, sizeof m_chrgEnLinkClick ); HandleLinkClick( penl, idCtrlIn ); } } // else if: left button up break; } // switch: notify code RETURN( lr ); } //*** CDetailsDlg::OnNotifyEnLink() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::HandleLinkClick // // Description: // Handle notification that the user has clicked on text in a richedit // control that is marked with the hyperlink attribute. // // Arguments: // penlIn - Contains information about link clicked. // idCtrlIn - Control in which user clicked. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// void CDetailsDlg::HandleLinkClick( ENLINK * penlIn , WPARAM idCtrlIn ) { TraceFunc( "" ); Assert( penlIn->chrg.cpMax > penlIn->chrg.cpMin ); PWSTR pszLink = NULL; ULONG cch; TEXTRANGE tr; DWORD sc; // // Get the text of the link. // cch = penlIn->chrg.cpMax - penlIn->chrg.cpMin + 1; pszLink = new WCHAR[ cch ]; if ( pszLink == NULL ) { goto Cleanup; } pszLink[ 0 ] = '\0'; ZeroMemory( &tr, sizeof( tr ) ); tr.chrg = penlIn->chrg; tr.lpstrText = pszLink; cch = (ULONG) SendDlgItemMessage( m_hwnd , (int) idCtrlIn , EM_GETTEXTRANGE , 0 , (LPARAM) &tr ); Assert( cch > 0 ); // // Pass the URL straight through to ShellExecute. // // Note that ShellExecute returns an HINSTANCE for historical reasons, // but actually only returns integers. Any value greater than 32 // indicates success. // TraceFlow1( "Calling ShellExecute on %hs", pszLink ); sc = HandleToULong( ShellExecute( NULL, NULL, pszLink, NULL, NULL, SW_NORMAL ) ); if ( sc <= 32 ) { TW32( sc ); THR( HrMessageBoxWithStatus( m_hwnd , IDS_ERR_INVOKING_LINK_TITLE , IDS_ERR_INVOKING_LINK_TEXT , sc , 0 // idsSubStatusIn , ( MB_OK | MB_ICONEXCLAMATION ) , NULL // pidReturnOut , pszLink ) ); } // if: error from ShellExecute Cleanup: delete [] pszLink; } //*** CDetailsDlg::HandleLinkClick() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::UpdateButtons // // Description: // Update the buttons based on whether there is a previous or next // item or not. // // Arguments: // None. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// void CDetailsDlg::UpdateButtons( void ) { TraceFunc( "" ); Assert( m_pttv != NULL ); HTREEITEM hti = NULL; HRESULT hr; BOOL fEnablePrev; BOOL fEnableNext; STHR( m_pttv->HrFindPrevItem( &hti ) ); // ignore error fEnablePrev = ( hti != NULL ); STHR( m_pttv->HrFindNextItem( &hti ) ); // ignore error fEnableNext = ( hti != NULL ); EnableWindow( GetDlgItem( m_hwnd, IDC_DETAILS_PB_PREV ), fEnablePrev ); EnableWindow( GetDlgItem( m_hwnd, IDC_DETAILS_PB_NEXT ), fEnableNext ); } //*** CDetailsDlg::UpdateButtons() ////////////////////////////////////////////////////////////////////////////// //++ // // CDetailsDlg::HrDisplayItem // // Description: // Display an item in the details dialog. // // Arguments: // htiIn - Handle to the item to display. // // Return Values: // S_OK - Operation completed successfully. // S_FALSE - Item not displayed. // // Remarks: // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT CDetailsDlg::HrDisplayItem( HTREEITEM htiIn ) { TraceFunc( "" ); Assert( htiIn != NULL ); HRESULT hr = S_FALSE; DWORD sc = ERROR_SUCCESS; BOOL fRet; BOOL fDisplayIcon; STreeItemLParamData * ptipd; BSTR bstr = NULL; BSTR bstrAdditionalInfo = NULL; WCHAR wszText[ 64 ]; FILETIME filetime; SYSTEMTIME systemtime; int cch; HICON hicon; // // Get information about the selected item to see if it has details. // fRet = m_pttv->FGetItem( htiIn, &ptipd ); if ( ! fRet ) { goto Cleanup; } // // Set the date and time information from the structure into // the dialog box. // if ( ( ptipd->ftTime.dwHighDateTime == 0 ) && ( ptipd->ftTime.dwLowDateTime == 0 ) ) { SetDlgItemText( m_hwnd, IDC_DETAILS_E_DATE, L"" ); SetDlgItemText( m_hwnd, IDC_DETAILS_E_TIME, L"" ); } // if: no date time specified else { // // Convert the date time to local time, then to something we can // use to display it. // if ( ! FileTimeToLocalFileTime( &ptipd->ftTime, &filetime ) ) { sc = TW32( GetLastError() ); } else if ( ! FileTimeToSystemTime( &filetime, &systemtime ) ) { sc = TW32( GetLastError() ); } if ( sc == ERROR_SUCCESS ) { // // Get the date string and display it. // cch = GetDateFormat( LOCALE_USER_DEFAULT , DATE_SHORTDATE , &systemtime , NULL // lpFormat , wszText , ARRAYSIZE( wszText ) ); if ( cch == 0 ) { sc = TW32( GetLastError() ); } SetDlgItemText( m_hwnd, IDC_DETAILS_E_DATE, wszText ); // // Get the time string and display it. // cch = GetTimeFormat( LOCALE_USER_DEFAULT , 0 , &systemtime , NULL // lpFormat , wszText , ARRAYSIZE( wszText ) ); if ( cch == 0 ) { sc = TW32( GetLastError() ); } SetDlgItemText( m_hwnd, IDC_DETAILS_E_TIME, wszText ); } // if: time converted successfully else { SetDlgItemText( m_hwnd, IDC_DETAILS_E_DATE, L"" ); SetDlgItemText( m_hwnd, IDC_DETAILS_E_TIME, L"" ); } } // else: date time specified // // Set the task IDs. // THR( HrFormatGuidIntoBSTR( &ptipd->clsidMajorTaskId, &bstr ) ); if ( SUCCEEDED( hr ) ) { SetDlgItemText( m_hwnd, IDC_DETAILS_E_MAJOR_ID, bstr ); } hr = THR( HrFormatGuidIntoBSTR( &ptipd->clsidMinorTaskId, &bstr ) ); if ( SUCCEEDED( hr ) ) { SetDlgItemText( m_hwnd, IDC_DETAILS_E_MINOR_ID, bstr ); } // // Set the text information. // // Node name. if ( ptipd->bstrNodeName == NULL ) { SetDlgItemText( m_hwnd, IDC_DETAILS_E_COMPUTER, L"" ); } else { SetDlgItemText( m_hwnd, IDC_DETAILS_E_COMPUTER, ptipd->bstrNodeName ); } // Description. if ( ptipd->bstrDescription == NULL ) { SetDlgItemText( m_hwnd, IDC_DETAILS_RE_DESCRIPTION, L"" ); } else { SetDlgItemText( m_hwnd, IDC_DETAILS_RE_DESCRIPTION, ptipd->bstrDescription ); } // Reference. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_DEFAULT_DETAILS_REFERENCE, &bstrAdditionalInfo ) ); if ( SUCCEEDED( hr ) ) { if ( ( ptipd->bstrReference == NULL ) || ( *ptipd->bstrReference == L'\0' ) ) { bstr = bstrAdditionalInfo; bstrAdditionalInfo = NULL; } // if: no reference specified else { hr = THR( HrFormatStringIntoBSTR( L"%s\n\n%s", &bstr, ptipd->bstrReference, bstrAdditionalInfo ) ); } // else: reference specified } SetDlgItemText( m_hwnd, IDC_DETAILS_RE_REFERENCE, bstr ); // // Set the status information. // _snwprintf( wszText, ARRAYSIZE( wszText ), L"0x%08x", ptipd->hr ); SetDlgItemText( m_hwnd, IDC_DETAILS_E_STATUS, wszText ); hr = ptipd->hr; if ( hr == S_FALSE ) { hr = THR( HrFormatStringIntoBSTR( L"S_FALSE", &bstr ) ); } else { // If not S_OK, this is a warning, so set the high bit before // translating to text, since the text string will not be found // without doing this. if ( hr != S_OK ) { hr |= 0x80000000; } hr = THR( HrFormatErrorIntoBSTR( hr, &bstr ) ); } // else: hr not S_FALSE if ( SUCCEEDED( hr ) ) { SetDlgItemText( m_hwnd, IDC_DETAILS_RE_STATUS, bstr ); if ( ptipd->hr == S_OK ) { fDisplayIcon = FALSE; } else { fDisplayIcon = TRUE; if ( FAILED( ptipd->hr ) ) { hicon = m_hiconError; } else { hicon = m_hiconWarn; } SendDlgItemMessage( m_hwnd, IDC_DETAILS_I_STATUS, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hicon ); } // else: status not informational } ShowWindow( GetDlgItem( m_hwnd, IDC_DETAILS_I_STATUS ), fDisplayIcon ? SW_SHOW : SW_HIDE ); hr = S_OK; Cleanup: TraceSysFreeString( bstr ); TraceSysFreeString( bstrAdditionalInfo ); HRETURN( hr ); } //*** CDetailsDlg::HrDisplayItem() //**************************************************************************** // // Private Functions // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// //++ // // ButtonFaceColorIsDark // // Description: // Return TRUE if the button face color is dark (implying that // the light colored button icons should be used). // // Arguments: // None. // // Return Values: // TRUE - Button face color is dark. // FALSE - Button face color is light. // //-- ////////////////////////////////////////////////////////////////////////////// BOOL ButtonFaceColorIsDark( void ) { TraceFunc( "" ); COLORREF rgbBtnFace = GetSysColor( COLOR_BTNFACE ); ULONG ulColors = GetRValue( rgbBtnFace ) + GetGValue( rgbBtnFace ) + GetBValue( rgbBtnFace ); RETURN( ulColors < 300 ); // arbitrary threshold } //*** ButtonFaceColorIsDark() ////////////////////////////////////////////////////////////////////////////// //++ // // SetButtonImage // // Description: // Set an image on a button. // // Arguments: // hwndBtnIn - Handle to the button window. // idIconIn - ID for the icon resource. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// void SetButtonImage( HWND hwndBtnIn , ULONG idIconIn ) { TraceFunc( "" ); HICON hIcon = (HICON) LoadImage( g_hInstance, MAKEINTRESOURCE( idIconIn ), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR ); if ( hIcon != NULL ) { HICON hIconPrev = (HICON) SendMessage( hwndBtnIn, BM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM) hIcon ); if ( hIconPrev ) { DestroyIcon( hIconPrev ); } } TraceFuncExit(); } //*** SetButtonImage() ////////////////////////////////////////////////////////////////////////////// //++ // // FreeButtonImage // // Description: // Free an image used by button. // // Arguments: // hwndBtnIn - Handle to the button window. // // Return Values: // None. // //-- ////////////////////////////////////////////////////////////////////////////// void FreeButtonImage( HWND hwndBtnIn ) { HANDLE hIcon = (HANDLE) SendMessage( hwndBtnIn, BM_GETIMAGE, IMAGE_ICON, 0 ); if ( hIcon != NULL ) { SendMessage( hwndBtnIn, BM_SETIMAGE, IMAGE_ICON, 0 ); DestroyIcon( (HICON) hIcon ); } } //*** FreeButtonImage()