📄 mfcmd5calculatordlg.cpp
字号:
//*****************************************************************************
// 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 + -