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

📄 mfcmd5calculatordlg.cpp

📁 利用Windows API来计算MD5的MFC例程.计算MD5时主要用到了CryptAcquireContext、CryptCreateHash两个API
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
// FILE: MfcMD5CalculatorDlg.cpp
// DESC: Implementation of MD5 calculator main dialog box.
//
// By Giovanni Dicanio <giovanni.dicanio@gmail.com>
// 2008, September 26th
//*****************************************************************************


//=============================================================================
//                              INCLUDES
//=============================================================================

#include "stdafx.h"
#include "MfcMD5Calculator.h"
#include "MfcMD5CalculatorDlg.h"

#include "AboutDlg.h"               // About dialog box
#include "FileNameHelpers.h"        // Extract file title and file path
#include "MD5FileCalculator.h"      // Class to calculate MD5 from files



//=============================================================================
//                       LOCAL MODULE DEFINITIONS
//=============================================================================

#ifdef _DEBUG
#define new DEBUG_NEW
#endif



//-----------------------------------------------------------------------------
// Data for custom MD5 calculation messages
//-----------------------------------------------------------------------------
struct MD5CalculationStatus
{
    // Possible states of calculation
    enum States
    {
        CalculationCompleted,   // completed successfully
        CalculationError,       // error occurred
        CalculationAborted,     // user stopped it
        CalculationInProgress   // still processing
    };

    MD5CalculationStatus()
        : MD5Calculator( NULL ),
          State( CalculationInProgress )
    {
    }

    // The calculator object
    CMD5FileCalculator * MD5Calculator;

    // Current calculation state
    States State;
};


//-----------------------------------------------------------------------------
// Custom messages, sent by the worker thread to the main GUI thread.
// The main GUI thread will perform actions (like updating the progress
// bar, etc.) based on these messages.
//-----------------------------------------------------------------------------

// Base of these custom messages
#define UWM_MD5_CALCULATION_BASE        (WM_APP + 10)

// WPARAM and LPARAM unused, just check dialog class m_calcStatus field
// Always returns 0
#define UWM_MD5_CALCULATION_PROGRESS    (UWM_MD5_CALCULATION_BASE)

// WPARAM and LPARAM unused, just check dialog class m_calcStatus field
// Always returns 0
#define UWM_MD5_CALCULATION_TERMINATED  (UWM_MD5_CALCULATION_BASE + 1)



//=============================================================================
//                          METHOD IMPLEMENTATIONS
//=============================================================================


CMfcMD5CalculatorDlg::CMfcMD5CalculatorDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMfcMD5CalculatorDlg::IDD, pParent),
      m_calcStatus( NULL )
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}


CMfcMD5CalculatorDlg::~CMfcMD5CalculatorDlg()
{
    // This pointer should be NULL, but delete it in case of something
    // goes wrong and the stack unwinds...
    if ( m_calcStatus != NULL )
    {
        delete m_calcStatus;
        m_calcStatus = NULL;
    }
}


void CMfcMD5CalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_FILENAME, m_wndFilename);
    DDX_Control(pDX, IDC_INFO_FILE_NAME, m_wndInfoFileTitle);
    DDX_Control(pDX, IDC_INFO_FILE_PATH, m_wndInfoPath);
    DDX_Control(pDX, IDC_MD5, m_wndMD5Digest);
    DDX_Control(pDX, IDC_STOP_CALCULATION, m_btnStop);
    DDX_Control(pDX, IDC_MD5_PROGRESS, m_wndMD5Progress);
    DDX_Control(pDX, IDC_STATUS_MSG, m_wndMessage);
    DDX_Control(pDX, IDC_COPY_MD5_FILE_TITLE, m_btnCopyMD5AndFileTitle);
    DDX_Control(pDX, IDC_COPY_MD5_FULL_PATH, m_btnCopyMD5AndFilePath);
    DDX_Control(pDX, IDC_COPY_MD5, m_btnCopyMD5);
    DDX_Control(pDX, IDC_BROWSE_FILENAME, m_btnBrowse);
    DDX_Control(pDX, IDC_CLEAR, m_btnClear);
    DDX_Control(pDX, IDC_CALCULATE_MD5, m_btnCalculateMD5);
}


BEGIN_MESSAGE_MAP(CMfcMD5CalculatorDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
    ON_BN_CLICKED(IDC_BROWSE_FILENAME, &CMfcMD5CalculatorDlg::OnBnClickedBrowseFilename)
    ON_BN_CLICKED(IDC_CLEAR, &CMfcMD5CalculatorDlg::OnBnClickedClear)
    ON_BN_CLICKED(IDC_CALCULATE_MD5, &CMfcMD5CalculatorDlg::OnBnClickedCalculateMD5)
    ON_BN_CLICKED(IDC_COPY_MD5, &CMfcMD5CalculatorDlg::OnBnClickedCopyMD5)
    ON_BN_CLICKED(IDC_COPY_MD5_FILE_TITLE, &CMfcMD5CalculatorDlg::OnBnClickedCopyMD5FileTitle)
    ON_BN_CLICKED(IDC_COPY_MD5_FULL_PATH, &CMfcMD5CalculatorDlg::OnBnClickedCopyMD5FullPath)
    ON_BN_CLICKED(IDC_STOP_CALCULATION, &CMfcMD5CalculatorDlg::OnBnClickedStopCalculation)
    ON_MESSAGE( UWM_MD5_CALCULATION_PROGRESS, &CMfcMD5CalculatorDlg::OnMD5CalculationProgress)
    ON_MESSAGE( UWM_MD5_CALCULATION_TERMINATED, &CMfcMD5CalculatorDlg::OnMD5CalculationTerminated)
    ON_WM_DROPFILES()
END_MESSAGE_MAP()


BOOL CMfcMD5CalculatorDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	

    //
    // *** Custom Initialization ***
    //
    
    // Not calculating MD5
    SetGUIStateForMD5Calculation( FALSE );

    CString msg;
    msg.LoadString( IDS_INITIAL_PROMPT );
    m_wndMessage.SetWindowText( msg );

	return TRUE;  // return TRUE  unless you set the focus to a control
}


void CMfcMD5CalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}


// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMfcMD5CalculatorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}


// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMfcMD5CalculatorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CMfcMD5CalculatorDlg::OnBnClickedBrowseFilename()
{
    // Filter for open files
    CString strFilter;
    VERIFY( strFilter.LoadString( IDS_OPEN_FILE_FILTER ) );

    // Open file dialog to select file
    CFileDialog dlgOpenFile( 
        TRUE,   // open
        NULL,   // no default extension
        NULL,   // no default filename
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        strFilter, // just show all files
        this    // open file dialog owner
    );

    INT_PTR nResult = dlgOpenFile.DoModal();
    if ( nResult == IDOK )
    {
        // User selected a file: update the GUI with that information
        m_wndFilename.SetWindowText( dlgOpenFile.GetPathName() );
    }
}


void CMfcMD5CalculatorDlg::OnBnClickedClear()
{
    // Clear filename edit box
    m_wndFilename.SetWindowText( TEXT("") );

    // Clear other MD5 related fields
    m_inputFileName.Empty();
    m_wndMD5Progress.SetPos(0);
    m_wndInfoFileTitle.SetWindowText( TEXT("") );
    m_wndInfoPath.SetWindowText( TEXT("") );
    m_wndMD5Digest.SetWindowText( TEXT("") );

    // Reset status bar message
    CString msg;
    msg.LoadString( IDS_INITIAL_PROMPT );
    m_wndMessage.SetWindowText( msg );
}


void CMfcMD5CalculatorDlg::OnBnClickedCalculateMD5()
{
    // Store file name (full path) in local data member
    m_wndFilename.GetWindowText( m_inputFileName );

    // Check that file name is valid (i.e. no empty string)
    m_inputFileName.TrimLeft();
    m_inputFileName.TrimRight();
    if ( m_inputFileName.IsEmpty() )
    {
        AfxMessageBox( IDS_ERROR_EMPTY_FILENAME, MB_OK | MB_ICONERROR );
        return;
    }

    // Status messages
    CString msg;

    // Write message to status bar: MD5 computation begins
    msg.FormatMessage( IDS_CALCULATING_MD5, 
        FileNameHelpers::GetFileTitle( m_inputFileName ).GetString() );
    m_wndMessage.SetWindowText( msg );


    // Initialize the progress bar
    m_wndMD5Progress.SetRange( 0, 100 );    // range is 0-100 (%)
    m_wndMD5Progress.SetStep( 1 );
    m_wndMD5Progress.SetPos( 0 );

    // Set GUI in state corresponding to: calculating MD5
    SetGUIStateForMD5Calculation( TRUE );

    // When the user wants to stop the worker thread, 
    // this flag will be set to TRUE
    m_stopMD5Calculation = FALSE;

    // Run the worker thread
    AfxBeginThread( MD5WorkerThreadFunction, this );
}


UINT CMfcMD5CalculatorDlg::MD5WorkerThreadFunction( LPVOID param )
{
    // Get the "this" parameter
    CMfcMD5CalculatorDlg * pThis = reinterpret_cast<CMfcMD5CalculatorDlg *>( param );
    ASSERT( pThis != NULL );

    // Route to non-static method
    pThis->MD5WorkerThreadFunctionMain();

    return TRUE;
}


//
// *** MAIN WORKER THREAD JOB IS DONE HERE ***
//
void CMfcMD5CalculatorDlg::MD5WorkerThreadFunctionMain()
{
    // Prepare for MD5 digest
    CMD5FileCalculator md5Calc( m_inputFileName );

    // Prepare calculation status
    ASSERT( m_calcStatus == NULL );
    m_calcStatus = new MD5CalculationStatus();
    m_calcStatus->MD5Calculator = &md5Calc;

    // Check that constructor was OK
    if ( ! md5Calc.IsInitOK() )
    {
        // Initialization failed

        // Set status flag indicating error
        m_calcStatus->State = MD5CalculationStatus::CalculationError;
    }
    else
    {
        // Initialization was successful

        // Do the main computation loop in this worker thread
        m_calcStatus->State = MD5CalculationStatus::CalculationInProgress;
        BOOL running = TRUE;
        while ( running )
        {
            // If user requests a stop, do it
            if ( m_stopMD5Calculation )
            {
                m_calcStatus->State = MD5CalculationStatus::CalculationAborted;
                running = FALSE;
                continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -