⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfcmd5calculatordlg.cpp

📁 利用Windows API来计算MD5的MFC例程.计算MD5时主要用到了CryptAcquireContext、CryptCreateHash两个API
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            }

            // 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 + -