📄 fcomparedlg.cpp
字号:
// FCompareDlg.cpp : implementation file
// (c) Codeguru & friends
// Coded by Antonio Tejada Lacaci. 1999
// atejada@espanet.com
//
#include "stdafx.h"
#include "FCompare.h"
#include "FCompareDlg.h"
#include "DirDialog.h"
#include <Shlwapi.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
#include "HyperLink.h"
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
CHyperLink m_urlHomepage;
CHyperLink m_urlCodeguru;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
DDX_Control(pDX, URL_HOMEPAGE, m_urlHomepage);
DDX_Control(pDX, URL_CODEGURU, m_urlCodeguru);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFCompareDlg dialog
CFCompareDlg::CFCompareDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFCompareDlg::IDD, pParent) {
//{{AFX_DATA_INIT(CFCompareDlg)
m_bRecurse = FALSE;
m_nMatchCriteria = 0;
m_dwUpto = 0;
m_strAllowedMasks = _T("*.*");
m_strDirectory = _T("");
m_bCompareDuplicates = FALSE;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
// Flags
m_bExit = FALSE;
m_bAbort = FALSE;
m_bAddInProgress = FALSE;
m_bFillInProgress = FALSE;
m_bCompareInProgress = FALSE;
m_bsState = BS_IDLE;
// Logical data
m_msaMatchedInfos.SetSize(0,20);
}
void CFCompareDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFCompareDlg)
DDX_Control(pDX, LBL_STATUS, m_lblStatus);
DDX_Control(pDX, LBL_TARGETFILES, m_lblTargetFiles);
DDX_Control(pDX, LBL_SOURCEFILES, m_lblSourceFiles);
DDX_Control(pDX, LBL_MATCHEDFILES, m_lblMatchedFiles);
DDX_Control(pDX, LST_MATCHEDFILES, m_lstMatchedFiles);
DDX_Control(pDX, TAB_ACTION, m_tabAction);
DDX_Control(pDX, LST_TARGETFILES, m_lstTargetFiles);
DDX_Control(pDX, LST_SOURCEFILES, m_lstSourceFiles);
DDX_Control(pDX, PRG_PROGRESS, m_prgProgress);
DDX_Check(pDX, CHK_RECURSEDIR, m_bRecurse);
DDX_Radio(pDX, RAD_MATCHCRITERIA, m_nMatchCriteria);
DDX_Text(pDX, EDT_UPTO, m_dwUpto);
DDX_Text(pDX, EDT_ALLOWEDMASKS, m_strAllowedMasks);
DDX_Text(pDX, EDT_DIRECTORY, m_strDirectory);
DDX_Check(pDX, CHK_COMPAREDUPLICATES, m_bCompareDuplicates);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CFCompareDlg, CDialog)
//{{AFX_MSG_MAP(CFCompareDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(RAD_MATCHCONTENTS, OnMatchContents)
ON_BN_CLICKED(RAD_MATCHCRITERIA, OnMatchCriteria)
ON_BN_CLICKED(BTN_COMPARE, OnCompare)
ON_WM_TIMER()
ON_NOTIFY(LVN_GETDISPINFO, LST_SOURCEFILES, OnGetdispinfoSearchFiles)
ON_BN_CLICKED(BTN_EXIT, OnExit)
ON_NOTIFY(TCN_SELCHANGE, TAB_ACTION, OnSelchangeAction)
ON_NOTIFY(LVN_GETDISPINFO, LST_MATCHEDFILES, OnGetdispinfoMatchedFiles)
ON_BN_CLICKED(BTN_EXPLOREDIR, OnExploreDirectory)
ON_BN_CLICKED(BTN_ADDSOURCEFILES, OnAddSourceFiles)
ON_BN_CLICKED(BTN_ADDTARGETFILES, OnAddTargetFiles)
ON_BN_CLICKED(BTN_CLEARSOURCEFILES, OnClearSourceFiles)
ON_BN_CLICKED(BTN_CLEARTARGETFILES, OnClearTargetFiles)
ON_WM_CLOSE()
ON_NOTIFY(LVN_GETDISPINFO, LST_TARGETFILES, OnGetdispinfoSearchFiles)
ON_BN_CLICKED(RAD_MATCHCHECKSUM, OnMatchContents)
ON_BN_CLICKED(RAD_MATCHCRC, OnMatchContents)
ON_BN_CLICKED(BTN_EXPORT, OnExport)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SEARCH_FINISHED, OnSearchFinished)
ON_MESSAGE(WM_COMPARE_FINISHED, OnCompareFinished)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFCompareDlg message handlers
BOOL CFCompareDlg::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) {
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty()) {
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
// Invalidate maximize & resize
pSysMenu->EnableMenuItem(SC_SIZE,MF_GRAYED);
pSysMenu->EnableMenuItem(SC_MAXIMIZE,MF_GRAYED);
pSysMenu->EnableMenuItem(SC_RESTORE,MF_GRAYED);
}
// 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
m_lstSourceFiles.InsertColumn(0,_T("Filename"),LVCFMT_LEFT,300);
m_lstSourceFiles.InsertColumn(1,_T("Size"),LVCFMT_RIGHT,65);
m_lstTargetFiles.InsertColumn(0,_T("Filename"),LVCFMT_LEFT,300);
m_lstTargetFiles.InsertColumn(1,_T("Size"),LVCFMT_RIGHT,65);
m_lstMatchedFiles.InsertColumn(0,_T("Source Filename"),LVCFMT_LEFT,268);
m_lstMatchedFiles.InsertColumn(1,_T("Target Filename"),LVCFMT_LEFT,268);
m_lstMatchedFiles.InsertColumn(2,_T("Size"),LVCFMT_RIGHT,65);
UpdateCounters();
m_tabAction.InsertItem(PPG_SEARCH,_T(" Search "));
m_tabAction.InsertItem(PPG_COMPARE,_T(" Compare "));
GetDlgItem(LBL_TARGETFILES)->ShowWindow(SW_SHOW);
GetDlgItem(LBL_SOURCEFILES)->ShowWindow(SW_SHOW);
GetDlgItem(LST_TARGETFILES)->ShowWindow(SW_SHOW);
GetDlgItem(LST_SOURCEFILES)->ShowWindow(SW_SHOW);
GetDlgItem(CHK_RECURSEDIR)->ShowWindow(SW_SHOW);
GetDlgItem(BTN_COMPARE)->ShowWindow(SW_SHOW);
GetDlgItem(LBL_MATCHEDFILES)->ShowWindow(SW_HIDE);
GetDlgItem(LST_MATCHEDFILES)->ShowWindow(SW_HIDE);
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CFCompareDlg::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 CFCompareDlg::OnPaint() {
if (IsIconic()) {
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (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 to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFCompareDlg::OnQueryDragIcon() {
return (HCURSOR) m_hIcon;
}
void CFCompareDlg::OnExploreDirectory() {
CDirDialog dlgDir;
dlgDir.m_strTitle = _T("Select directory for file search");
UpdateData(TRUE);
dlgDir.m_strSelDir = m_strDirectory;
dlgDir.m_strWindowTitle = _T("Select directory");
if (dlgDir.DoBrowse(this) == IDOK) {
m_strDirectory = dlgDir.m_strPath;
// Append backslash if necessary
if ((m_strDirectory.GetLength()>0) &&
(m_strDirectory[m_strDirectory.GetLength()-1] != TCHAR('\\')))
m_strDirectory += TCHAR('\\');
UpdateData(FALSE);
}
}
void CFCompareDlg::OnMatchContents() {
GetDlgItem(EDT_UPTO)->EnableWindow(TRUE);
}
void CFCompareDlg::OnMatchCriteria() {
GetDlgItem(EDT_UPTO)->EnableWindow(FALSE);
}
UINT SearchThread(CFCompareDlg *pcdlg) {
// Retrieve directories
LVITEM lvi;
CString strMask;
int nPos=0;
int nNextPos=0;
memset(&lvi,0,sizeof(lvi));
pcdlg->m_bAddInProgress = TRUE;
// Delete files' listview (if files were added, listviews are no longer up to date due
// to possible reordering of items in FileInfoArray).
pcdlg->m_plstFiles->DeleteAllItems();
// Retrieve files: Sorted by size and ascending, do not include dirs.
while (nPos < pcdlg->m_strAllowedMasks.GetLength()) {
nNextPos = pcdlg->m_strAllowedMasks.Find(";",nPos);
if (nNextPos == -1) nNextPos = pcdlg->m_strAllowedMasks.GetLength();
strMask = pcdlg->m_strAllowedMasks.Mid(nPos, nNextPos-nPos);
strMask.TrimLeft();
strMask.TrimRight();
TRACE("strMask is %s\n",strMask);
if (strMask != "")
pcdlg->m_pfiaInfos->AddDir(pcdlg->m_strDirectory, strMask, pcdlg->m_bRecurse,
CFileInfoArray::AP_SORTBYSIZE | CFileInfoArray::AP_SORTASCENDING, FALSE,
&pcdlg->m_bAbort);
nPos = nNextPos+1;
}
pcdlg->m_lblStatus.SetWindowText(_T("Filling listview..."));
pcdlg->m_ulProgress = 0;
pcdlg->m_ulProgressMax = pcdlg->m_pfiaInfos->GetSize();
pcdlg->m_bAddInProgress = FALSE;
pcdlg->m_bFillInProgress = TRUE;
// Set common LVITEM attributes
lvi.pszText = LPSTR_TEXTCALLBACK;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iSubItem = 0;
// Insert files
pcdlg->m_plstFiles->LockWindowUpdate();
for (int i=0;((i<pcdlg->m_pfiaInfos->GetSize()) && (!pcdlg->m_bAbort));i++) {
lvi.iItem = i;
lvi.lParam = (LPARAM) &(*pcdlg->m_pfiaInfos)[i];
pcdlg->m_plstFiles->InsertItem(&lvi);
pcdlg->m_ulProgress++;
}
pcdlg->m_plstFiles->UnlockWindowUpdate();
pcdlg->m_bFillInProgress = FALSE;
pcdlg->PostMessage(WM_SEARCH_FINISHED);
return 0;
}
BOOL CompareContents(CFileInfo* pfinSrc, CFileInfo* pfinDest, const DWORD dwUpTo,
volatile BOOL* pbAbort) {
// Note this method is not "win64 friendly"
FILE* fSrc;
FILE* fDest;
DWORD dwCount = 0;
BYTE cSrc, cDest;
if ((dwUpTo == 0) || (dwUpTo > pfinSrc->GetLength()))
dwCount = pfinSrc->GetLength();
else
dwCount = dwUpTo;
fSrc = fopen(pfinSrc->GetFilePath(),"rb");
fDest = fopen(pfinDest->GetFilePath(),"rb");
if (fSrc && fDest) {
while (!feof(fSrc) && !feof(fDest) && !(*pbAbort) && (dwCount>0) &&
fread(&cSrc,1,1,fSrc) && fread(&cDest,1,1,fDest) && (cSrc == cDest)) {
dwCount--;
}
}
if (fSrc) fclose(fSrc);
if (fDest) fclose(fDest);
return (dwCount == 0);
}
UINT CompareThread(CFCompareDlg *pcdlg) {
CFileInfo* pfinSource;
CFileInfo* pfinTarget;
MATCHSTRUCT ms;
DWORD dwMatchSize=0;
DWORD dwMatchNumber=0;
LVITEM lviMatched;
// Compare
int iSource=0;
int iTarget=0;
pcdlg->m_bCompareInProgress = TRUE;
pcdlg->m_ulProgress = 0;
pcdlg->m_ulProgressMax = pcdlg->m_fiaSourceInfos.GetSize() +
pcdlg->m_fiaTargetInfos.GetSize();
while ((!pcdlg->m_bAbort) &&
(iSource<pcdlg->m_fiaSourceInfos.GetSize()) &&
(iTarget<pcdlg->m_fiaTargetInfos.GetSize())) {
pfinSource = &pcdlg->m_fiaSourceInfos[iSource];
pfinTarget = &pcdlg->m_fiaTargetInfos[iTarget];
// Compare pfinSource with all the files of target with the same size of pfinSource
for (int i=iTarget;(i<pcdlg->m_fiaTargetInfos.GetSize()) &&
(pcdlg->m_fiaTargetInfos[i].GetLength64() == pfinSource->GetLength64());i++) {
pfinTarget = &pcdlg->m_fiaTargetInfos[i];
if (// Not the same file or Ignore duplicates unchecked
(pcdlg->m_bCompareDuplicates ||
(pfinSource->GetFilePath().CompareNoCase(pfinTarget->GetFilePath()) != 0)) &&
// Checksum criteria
((pcdlg->m_nMatchCriteria != 1) ||
(pfinSource->GetChecksum(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort) ==
pfinTarget->GetChecksum(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort))) &&
// CRC criteria
((pcdlg->m_nMatchCriteria != 2) ||
(pfinSource->GetCRC(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort) ==
pfinTarget->GetCRC(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort))) &&
// Contents criteria
((pcdlg->m_nMatchCriteria != 3) ||
(CompareContents(pfinSource, pfinTarget, pcdlg->m_dwUpto, &pcdlg->m_bAbort)))
) {
// Match!
ms.pfinTarget = pfinTarget;
ms.pfinSource = pfinSource;
pcdlg->m_msaMatchedInfos.InsertAt(pcdlg->m_msaMatchedInfos.GetSize(), ms);
dwMatchSize += pfinTarget->GetLength();
dwMatchNumber++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -