📄 mfcmd5calculatordlg.cpp
字号:
}
// Hash another chunk of file (if any data is present)
if ( !md5Calc.HashMore() )
{
// No more data to hash - stop
// This can be caused by end-of-data (OK), or by some error.
if ( md5Calc.IsDigestReady() )
{
// Calculation successfully completed
m_calcStatus->State = MD5CalculationStatus::CalculationCompleted;
}
else
{
// Some error occurred
m_calcStatus->State = MD5CalculationStatus::CalculationError;
}
running = FALSE;
continue;
}
// Update progress bar, only if file size is big enough
// (else, if the file is small, there's no need to update progress bar)
static const __int64 megabyte = 1024 * 1024; // 1 MB
static const __int64 smallFileSizeThreshold = 200 * megabyte; // 200 MB
if ( md5Calc.GetFileSize() > smallFileSizeThreshold )
{
SendMessage( UWM_MD5_CALCULATION_PROGRESS );
}
}
}
// Notify GUI thread of termination of worker thread
SendMessage( UWM_MD5_CALCULATION_TERMINATED );
// Cleanup MD5 status object
delete m_calcStatus;
m_calcStatus = NULL; // avoid dangling references
}
LRESULT CMfcMD5CalculatorDlg::OnMD5CalculationProgress( WPARAM wParam, LPARAM lParam )
{
// Normal Update of progress bar
// MD5 calculator object must be available
ASSERT( m_calcStatus->MD5Calculator != NULL );
__int64 bytesProcessed = m_calcStatus->MD5Calculator->GetProcessedBytes();
__int64 totalBytes = m_calcStatus->MD5Calculator->GetFileSize();
double percent = 100.0 * static_cast<double>(bytesProcessed) / static_cast<double>(totalBytes);
int currPos = m_wndMD5Progress.GetPos();
int newPos = static_cast<int>( percent );
if ( newPos != currPos )
m_wndMD5Progress.SetPos( newPos );
return 0;
}
LRESULT CMfcMD5CalculatorDlg::OnMD5CalculationTerminated( WPARAM wParam, LPARAM lParam )
{
// Put the GUI in a state corresponding to: non calculating MD5
SetGUIStateForMD5Calculation( FALSE );
// MD5 Calculator must be valid
ASSERT( m_calcStatus->MD5Calculator != NULL );
// Message for status line
CString msg;
// Extract file title from full path
CString fileTitle = FileNameHelpers::GetFileTitle( m_inputFileName );
// Understand why we terminated
switch ( m_calcStatus->State )
{
case MD5CalculationStatus::CalculationCompleted:
// Computation terminated successfully
// Update status message: MD5 computation OK
msg.FormatMessage( IDS_MD5_DONE, fileTitle.GetString() );
m_wndMessage.SetWindowText( msg );
// Copy MD5 digest and fill file information in the GUI
m_wndMD5Digest.SetWindowText( m_calcStatus->MD5Calculator->GetMD5Digest() );
m_wndInfoFileTitle.SetWindowText( fileTitle );
m_wndInfoPath.SetWindowText( FileNameHelpers::GetFilePath( m_inputFileName ) );
break;
case MD5CalculationStatus::CalculationAborted:
// Computation aborted by the user
msg.FormatMessage( IDS_ERROR_USER_ABORT, fileTitle.GetString() );
m_wndMessage.SetWindowText( msg );
AfxMessageBox( msg, MB_ICONINFORMATION | MB_OK );
break;
case MD5CalculationStatus::CalculationError:
// Computation aborted due to some error
// Update status message: MD5 computation failed
msg.FormatMessage( IDS_ERROR_MD5_COMPUTATION, fileTitle.GetString() );
m_wndMessage.SetWindowText( msg );
AfxMessageBox( msg, MB_ICONERROR | MB_OK );
break;
default:
// Unknown invalid state ?!
ASSERT( FALSE );
break;
}
// Clear the progress bar on error
if ( m_calcStatus->State != MD5CalculationStatus::CalculationCompleted )
{
m_wndMD5Progress.SetPos( 0 );
}
else
{
// Progress bar should be full, but make it so anyway
m_wndMD5Progress.SetPos( 100 ); // full 100% range
}
return 0;
}
void CMfcMD5CalculatorDlg::SetGUIStateForMD5Calculation( BOOL calculatingMD5 )
{
if ( calculatingMD5 )
{
// Enable stop button
m_btnStop.EnableWindow();
// Disable MD5 copy buttons
EnableMD5Copy( FALSE );
// Disable selection of input file
EnableFileSelection( FALSE );
// Disable start MD5 calculation
m_btnCalculateMD5.EnableWindow( FALSE );
// We don't accept drag-and-drop files during processing
DragAcceptFiles( FALSE );
}
else
{
// Disable stop button (computation completed or aborted by the user)
m_btnStop.EnableWindow( FALSE );
// Enable MD5 copy buttons again
EnableMD5Copy();
// Enable selection of input file
EnableFileSelection();
// Enable start MD5 calculation again
m_btnCalculateMD5.EnableWindow();
// We accept drag-and-drop files
DragAcceptFiles( TRUE );
}
}
void CMfcMD5CalculatorDlg::OnBnClickedCopyMD5()
{
// Copy MD5 digest string to clipboard
CString strMD5;
m_wndMD5Digest.GetWindowText( strMD5 );
// We must have an MD5 digest ready
if ( strMD5.IsEmpty() )
{
AfxMessageBox( IDS_NO_MD5_DIGEST_AVAILABLE, MB_OK | MB_ICONERROR );
return;
}
VERIFY( CopyStringToClipboard( strMD5 ) );
}
void CMfcMD5CalculatorDlg::OnBnClickedCopyMD5FileTitle()
{
// Get MD5 digest string
CString strMD5;
m_wndMD5Digest.GetWindowText( strMD5 );
// We must have an MD5 digest ready
if ( strMD5.IsEmpty() )
{
AfxMessageBox( IDS_NO_MD5_DIGEST_AVAILABLE, MB_OK | MB_ICONERROR );
return;
}
// Get file title (no path)
CString strFileTitle;
m_wndInfoFileTitle.GetWindowText( strFileTitle );
// Copy MD5 + file title to clipboard
CString str;
str = strMD5;
str += TEXT(" ");
str += strFileTitle;
VERIFY( CopyStringToClipboard( str ) );
}
void CMfcMD5CalculatorDlg::OnBnClickedCopyMD5FullPath()
{
// Get MD5 digest string
CString strMD5;
m_wndMD5Digest.GetWindowText( strMD5 );
// We must have an MD5 digest ready
if ( strMD5.IsEmpty() )
{
AfxMessageBox( IDS_NO_MD5_DIGEST_AVAILABLE, MB_OK | MB_ICONERROR );
return;
}
// Copy MD5 + file full path to clipboard
CString str;
str = strMD5;
str += TEXT(" ");
str += m_inputFileName;
VERIFY( CopyStringToClipboard( str ) );
}
void CMfcMD5CalculatorDlg::OnBnClickedStopCalculation()
{
// Require a stop
// (the worker thread will stop its job when this flag is set)
m_stopMD5Calculation = TRUE;
}
BOOL CMfcMD5CalculatorDlg::CopyStringToClipboard( LPCTSTR text )
{
// Check input string
ASSERT( text != NULL );
if ( text == NULL )
return FALSE;
// Open the clipboard
if ( !OpenClipboard() )
return FALSE;
// Empty the clipboard
if ( !EmptyClipboard() )
{
CloseClipboard();
return FALSE;
}
// Number of bytes to copy (consider +1 for end-of-string, and
// properly scale byte size to sizeof(TCHAR))
SIZE_T textCopySize = (_tcslen( text ) + 1) * sizeof(TCHAR);
// Allocate a global memory object for the text
HGLOBAL hTextCopy = GlobalAlloc( GMEM_MOVEABLE, textCopySize );
if ( hTextCopy == NULL )
{
CloseClipboard();
return FALSE;
}
// Lock the handle, and copy source text to the buffer
TCHAR * textCopy = reinterpret_cast< TCHAR *>( GlobalLock( hTextCopy ) );
ASSERT( textCopy != NULL );
StringCbCopy( textCopy, textCopySize, text );
GlobalUnlock( hTextCopy );
textCopy = NULL; // avoid dangling references
// Place the handle on the clipboard
#if defined( _UNICODE )
UINT textFormat = CF_UNICODETEXT; // Unicode text
#else
UINT textFormat = CF_TEXT; // ANSI text
#endif // defined( _UNICODE )
if ( SetClipboardData( textFormat, hTextCopy ) == NULL )
{
// Failed
CloseClipboard();
return FALSE;
}
// Release the clipboard
CloseClipboard();
// All right
return TRUE;
}
void CMfcMD5CalculatorDlg::EnableMD5Copy( BOOL enable )
{
m_btnCopyMD5.EnableWindow( enable );
m_btnCopyMD5AndFileTitle.EnableWindow( enable );
m_btnCopyMD5AndFilePath.EnableWindow( enable );
}
void CMfcMD5CalculatorDlg::EnableFileSelection( BOOL enable )
{
m_wndFilename.EnableWindow( enable );
m_btnBrowse.EnableWindow( enable );
m_btnClear.EnableWindow( enable );
}
void CMfcMD5CalculatorDlg::OnDropFiles(HDROP hDropInfo)
{
// Get number of files dropped
UINT numFiles = DragQueryFile( hDropInfo, -1, NULL, 0 );
bool startMD5Computation = false;
// Only one file can be dropped
if ( numFiles == 1 )
{
// Get filename
TCHAR filename[ 4*1024 ]; // 4K TCHAR's buffer for filename... big enough :)
if ( DragQueryFile(
hDropInfo, // drag-and-drop info
0, // first file
filename, // destination buffer
_countof( filename ) ) > 0 ) // destination buffer size
{
// Store file name
m_wndFilename.SetWindowText( filename );
// Require the compute MD5
startMD5Computation = true;
}
else
{
// Drop error
AfxMessageBox( IDS_ERROR_DROP, MB_ICONERROR | MB_OK );
}
}
else
{
// Show error message
AfxMessageBox( IDS_CAN_DROP_ONLY_ONE_FILE, MB_OK | MB_ICONERROR );
}
// Release drop resources
DragFinish( hDropInfo );
// Start the MD5 computation if required
if ( startMD5Computation )
{
OnBnClickedCalculateMD5();
}
// This was added by the wizard, but I don't think it is useful...
// CDialog::OnDropFiles(hDropInfo);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -