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

//////////////////////////////////////////////////////////////////////////////
//
// 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()