// 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++;
}
}
// Restore initial target
pfinTarget = &pcdlg->m_fiaTargetInfos[iTarget];
if (pfinTarget->GetLength64() >= pfinSource->GetLength64())
iSource++; // In case of equal sizes, iSource must be incremented first
// (see inner loop for reasons)
else
iTarget++;
pcdlg->m_ulProgress++;
}
// Set new progress values
pcdlg->m_ulProgress = 0;
pcdlg->m_ulProgressMax = pcdlg->m_msaMatchedInfos.GetSize();
pcdlg->m_bCompareInProgress = FALSE;
pcdlg->m_bFillInProgress = TRUE;
// Fill listview
pcdlg->m_lblStatus.SetWindowText(_T("Filling listview..."));
pcdlg->m_lstMatchedFiles.LockWindowUpdate();
// Set common LVITEM values for all elements
lviMatched.mask = LVIF_PARAM | LVIF_TEXT;
lviMatched.iSubItem = 0;
lviMatched.pszText = LPSTR_TEXTCALLBACK;
for (int i=0;(i<pcdlg->m_msaMatchedInfos.GetSize()) && (!pcdlg->m_bAbort);i++) {
lviMatched.iItem = i;
lviMatched.lParam = (LPARAM) &pcdlg->m_msaMatchedInfos[i];
pcdlg->m_lstMatchedFiles.InsertItem(&lviMatched);
pcdlg->m_ulProgress++;
}
pcdlg->m_lstMatchedFiles.UnlockWindowUpdate();
pcdlg->m_bFillInProgress = FALSE;
// Report compare thread end
pcdlg->PostMessage(WM_COMPARE_FINISHED,dwMatchNumber, dwMatchSize);
return 0;
}
void CFCompareDlg::SetBusyState(int m_bsState) {
this->m_bsState = m_bsState;
GetDlgItem(LST_SOURCEFILES)->EnableWindow(m_bsState != BS_SEARCHING);
GetDlgItem(LST_TARGETFILES)->EnableWindow(m_bsState != BS_SEARCHING);
GetDlgItem(CHK_RECURSEDIR)->EnableWindow(m_bsState != BS_SEARCHING);
GetDlgItem(BTN_COMPARE)->EnableWindow(m_bsState == BS_IDLE);
GetDlgItem(BTN_CLEARSOURCEFILES)->EnableWindow(m_bsState == BS_IDLE);
GetDlgItem(BTN_CLEARTARGETFILES)->EnableWindow(m_bsState == BS_IDLE);
GetDlgItem(BTN_ADDSOURCEFILES)->EnableWindow(m_bsState == BS_IDLE);
GetDlgItem(BTN_ADDTARGETFILES)->EnableWindow(m_bsState == BS_IDLE);
GetDlgItem(BTN_EXPORT)->EnableWindow(m_bsState == BS_IDLE);
GetDlgItem(RAD_MATCHCRITERIA)->EnableWindow(m_bsState != BS_COMPARING);
GetDlgItem(RAD_MATCHCHECKSUM)->EnableWindow(m_bsState != BS_COMPARING);
GetDlgItem(RAD_MATCHCRC)->EnableWindow(m_bsState != BS_COMPARING);
GetDlgItem(RAD_MATCHCONTENTS)->EnableWindow(m_bsState != BS_COMPARING);
GetDlgItem(EDT_UPTO)->EnableWindow((m_bsState != BS_COMPARING) &&
(IsDlgButtonChecked(RAD_MATCHCRITERIA) != BST_CHECKED));
GetDlgItem(CHK_COMPAREDUPLICATES)->EnableWindow(m_bsState != BS_COMPARING);
if (m_bsState != BS_IDLE) {
GetDlgItem(BTN_EXIT)->SetWindowText(_T("Cancel"));
} else {
GetDlgItem(BTN_EXIT)->SetWindowText(_T("Exit"));
m_lblStatus.SetWindowText(_T("Ready"));
m_prgProgress.SetPos(0);
}
}
void CFCompareDlg::UpdateCounters() {
CString str;
str.Format(_T("Matched files (%d)"), m_lstMatchedFiles.GetItemCount());
GetDlgItem(LBL_MATCHEDFILES)->SetWindowText(str);
str.Format(_T("Source files (%d)"), m_lstSourceFiles.GetItemCount());
GetDlgItem(LBL_SOURCEFILES)->SetWindowText(str);
str.Format(_T("Target files (%d)"), m_lstTargetFiles.GetItemCount());
GetDlgItem(LBL_TARGETFILES)->SetWindowText(str);
}
void CFCompareDlg::OnCompare() {
// Retrieve comparison settings
UpdateData(TRUE);
m_lblStatus.SetWindowText(_T("Comparing files..."));
// Empty compare list
m_lstMatchedFiles.DeleteAllItems();
m_msaMatchedInfos.RemoveAll();
m_bAbort = FALSE;
SetBusyState(BS_COMPARING);
// Launch thread
AfxBeginThread((AFX_THREADPROC) CompareThread,(LPVOID) this);
// Launch progress-report timer
if (SetTimer(1,250, NULL) == 0){
// Timer not available
AfxMessageBox(_T("Timer is not available, real time progress will not be reported."),
MB_ICONINFORMATION | MB_OK);
}
}
void CFCompareDlg::OnGetdispinfoSearchFiles(NMHDR* pNMHDR, LRESULT* pResult) {
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
CString str;
CFileInfo* pinf;
pinf = (CFileInfo*) pDispInfo->item.lParam;
switch (pDispInfo->item.iSubItem) {
case 0:
pDispInfo->item.mask = LVIF_TEXT;
StrCpyN(pDispInfo->item.pszText, pinf->GetFilePath(), pDispInfo->item.cchTextMax);
break;
case 1:
if (pinf->GetLength64() < 1024)
str.Format("%d B", pinf->GetLength());
else {
// The following weird LONGLONG casts are because VC 6.0 doesn't implement int64
// to double conversion =8-ooo
if (pinf->GetLength64() < (1024*1024))
str.Format("%3.2f KB",(LONGLONG) pinf->GetLength64() / 1024.0);
else {
if (pinf->GetLength64() < (1024*1024*1024))
str.Format("%3.2f MB", (LONGLONG) pinf->GetLength64() / (1024*1024.0));
else
str.Format("%1.2f GB", (LONGLONG) pinf->GetLength64() / (1024.0*1024*1024));
}
}
pDispInfo->item.mask = LVIF_TEXT;
StrCpyN(pDispInfo->item.pszText, str, pDispInfo->item.cchTextMax);
break;
}
*pResult = 0;
}
void CFCompareDlg::OnTimer(UINT nIDEvent) {
CString str;
if (m_bAddInProgress) {
str.Format(_T("Found %d files"),m_fiaSourceInfos.GetSize() + m_fiaTargetInfos.GetSize());
m_lblStatus.SetWindowText(str);
str.Format(_T("Source files (%d)"), m_fiaSourceInfos.GetSize());
m_lblSourceFiles.SetWindowText(str);
str.Format(_T("Target files (%d)"), m_fiaTargetInfos.GetSize());
m_lblTargetFiles.SetWindowText(str);
}
if (m_bFillInProgress) {
m_prgProgress.SetRange(0, (short) m_ulProgressMax);
m_prgProgress.SetPos(m_ulProgress);
}
if (m_bCompareInProgress) {
str.Format(_T("Matched %d files"), m_msaMatchedInfos.GetSize());
m_lblStatus.SetWindowText(str);
str.Format(_T("Matched files (%d)"), m_msaMatchedInfos.GetSize());
m_lblMatchedFiles.SetWindowText(str);
m_prgProgress.SetRange(0, (short) m_ulProgressMax);
m_prgProgress.SetPos(m_ulProgress);
}
CDialog::OnTimer(nIDEvent);
}
afx_msg LONG CFCompareDlg::OnSearchFinished(WPARAM /* wparam*/ , LPARAM /* lparam */) {
if (m_bAbort) {
// Delete items from aborted listview
m_plstFiles->DeleteAllItems();
// Delete items from aborted CFileInfoArray
m_pfiaInfos->RemoveAll();
}
KillTimer(1);
SetBusyState(BS_IDLE);
m_lblStatus.SetWindowText(_T("Ready"));
UpdateCounters();
if (m_bExit) PostQuitMessage(0);
return TRUE;
}
afx_msg LONG CFCompareDlg::OnCompareFinished(WPARAM wparam, LPARAM lparam) {
CString str;
if (m_bAbort)
m_lstMatchedFiles.DeleteAllItems();
KillTimer(1);
SetBusyState(BS_IDLE);
if (!m_bAbort) {
str.Format(_T("Comparison results:\r\n* %d files matched\r\n* %d bytes matched"),
wparam, lparam);
MessageBox(str,_T("Comparison ended"),MB_OK);
}
m_prgProgress.SetPos(0);
str.Format(_T("Matched files (%d)"),m_lstMatchedFiles.GetItemCount());
m_lblMatchedFiles.SetWindowText(str);
UpdateCounters();
if (m_bExit) PostQuitMessage(0);
return TRUE;
}
void CFCompareDlg::OnExit() {
if (m_bsState == BS_IDLE) PostQuitMessage(0);
m_bAbort = TRUE;
}
void CFCompareDlg::OnSelchangeAction(NMHDR* /* pNMHDR*/, LRESULT* pResult) {
if (m_tabAction.GetCurSel() == PPG_COMPARE) {
GetDlgItem(LBL_TARGETFILES)->ShowWindow(SW_HIDE);
GetDlgItem(LBL_SOURCEFILES)->ShowWindow(SW_HIDE);
GetDlgItem(LST_TARGETFILES)->ShowWindow(SW_HIDE);
GetDlgItem(LST_SOURCEFILES)->ShowWindow(SW_HIDE);
GetDlgItem(BTN_COMPARE)->ShowWindow(SW_HIDE);
GetDlgItem(LBL_MATCHEDFILES)->ShowWindow(SW_SHOW);
GetDlgItem(LST_MATCHEDFILES)->ShowWindow(SW_SHOW);
GetDlgItem(CHK_COMPAREDUPLICATES)->ShowWindow(SW_HIDE);
} else {
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(BTN_COMPARE)->ShowWindow(SW_SHOW);
GetDlgItem(LBL_MATCHEDFILES)->ShowWindow(SW_HIDE);
GetDlgItem(LST_MATCHEDFILES)->ShowWindow(SW_HIDE);
GetDlgItem(CHK_COMPAREDUPLICATES)->ShowWindow(SW_SHOW);
}
*pResult = 0;
}
void CFCompareDlg::OnGetdispinfoMatchedFiles(NMHDR* pNMHDR, LRESULT* pResult) {
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
MATCHSTRUCT* pms;
CFileInfo* pinf;
CString str;
switch (pDispInfo->item.iSubItem) {
case 0:
pDispInfo->item.mask = LVIF_TEXT;
pms = (MATCHSTRUCT*) pDispInfo->item.lParam;
StrCpyN(pDispInfo->item.pszText, pms->pfinSource->GetFilePath(),
pDispInfo->item.cchTextMax);
break;
case 1:
pDispInfo->item.mask = LVIF_TEXT;
pms = (MATCHSTRUCT*) pDispInfo->item.lParam;
StrCpyN(pDispInfo->item.pszText, pms->pfinTarget->GetFilePath(),
pDispInfo->item.cchTextMax);
break;
case 2:
pms = (MATCHSTRUCT*) pDispInfo->item.lParam;
pinf = pms->pfinSource;
if (pinf->GetLength64() < 1024)
str.Format("%d B",pinf->GetLength());
else {
// The following weird LONGLONG casts are because VC 6.0 doesn't implement int64
// to double conversion =8-ooo
if (pinf->GetLength64() < (1024*1024))
str.Format("%3.2f KB",(LONGLONG) pinf->GetLength64() / 1024.0);
else {
if (pinf->GetLength64() < (1024*1024*1024))
str.Format("%3.2f MB", (LONGLONG) pinf->GetLength64() / (1024*1024.0));
else
str.Format("%1.2f GB", (LONGLONG) pinf->GetLength64() / (1024.0*1024*1024));
}
}
pDispInfo->item.mask = LVIF_TEXT;
StrCpyN(pDispInfo->item.pszText, str, pDispInfo->item.cchTextMax);
break;
}
*pResult = 0;
}
void CFCompareDlg::OnAddSourceFiles() {
// Retrieve search settings from dialog controls
UpdateData(TRUE);
// Append backslash if necessary
if ((m_strDirectory.GetLength()>0) &&
(m_strDirectory[m_strDirectory.GetLength()-1] != TCHAR('\\'))) m_strDirectory += TCHAR('\\');
UpdateData(FALSE);
// Set common variables with thread
m_plstFiles = &m_lstSourceFiles;
m_pfiaInfos = &m_fiaSourceInfos;
// Compare text-callback list will no longer be up to date, empty it
m_lstMatchedFiles.DeleteAllItems();
m_msaMatchedInfos.RemoveAll();
m_lblStatus.SetWindowText(_T("Inserting files..."));
m_bAbort = FALSE;
SetBusyState(BS_SEARCHING);
// Launch thread
AfxBeginThread((AFX_THREADPROC) SearchThread,(LPVOID) this);
// Launch progress-report timer
if (SetTimer(1,250, NULL) == 0){
// Timer not available
AfxMessageBox(_T("Timer is not available, real time progress will not be reported."),
MB_ICONINFORMATION | MB_OK);
}
}
void CFCompareDlg::OnAddTargetFiles() {
// Retrieve search settings from dialog controls
UpdateData(TRUE);
// Append backslash if necessary
if ((m_strDirectory.GetLength()>0) &&
(m_strDirectory[m_strDirectory.GetLength()-1] != TCHAR('\\'))) m_strDirectory += TCHAR('\\');
UpdateData(FALSE);
// Set common variables with thread
m_plstFiles = &m_lstTargetFiles;
m_pfiaInfos = &m_fiaTargetInfos;
// Compare text-callback list will no longer be up to date, empty it
m_lstMatchedFiles.DeleteAllItems();
m_msaMatchedInfos.RemoveAll();
m_lblStatus.SetWindowText(_T("Inserting files..."));
m_bAbort = FALSE;
SetBusyState(BS_SEARCHING);
// Launch thread
AfxBeginThread((AFX_THREADPROC) SearchThread,(LPVOID) this);
// Launch progress-report timer
if (SetTimer(1,250, NULL) == 0){
// Timer not available
AfxMessageBox(_T("Timer is not available, real time progress will not be reported."),
MB_ICONINFORMATION | MB_OK);
}
}
void CFCompareDlg::OnClearSourceFiles() {
// Clear matched
m_lstMatchedFiles.DeleteAllItems();
m_msaMatchedInfos.RemoveAll();
// Clear listview
m_lstSourceFiles.DeleteAllItems();
// Clear fileinfos array
m_fiaSourceInfos.RemoveAll();
// UpdateCounters
UpdateCounters();
}
void CFCompareDlg::OnClearTargetFiles() {
// Clear matched
m_lstMatchedFiles.DeleteAllItems();
m_msaMatchedInfos.RemoveAll();
// Clear listview
m_lstTargetFiles.DeleteAllItems();
// Clear fileinfos array
m_fiaTargetInfos.RemoveAll();
// Update counters
UpdateCounters();
}
void CFCompareDlg::OnClose() {
if (m_bsState != BS_IDLE) {
// Thread running, signal abort and exit flag
m_bExit = TRUE;
m_bAbort = TRUE;
} else
CDialog::OnClose();
}
void CFCompareDlg::OnExport() {
CStdioFile sf;
CFileDialog fd(FALSE);
int i;
CString str;
if (fd.DoModal() == IDOK) {
try {
sf.Open(fd.m_ofn.lpstrFile, CStdioFile::modeWrite | CFile::modeCreate | CStdioFile::typeText);
sf.WriteString(_T("SOURCE FILES:\n"));
for (i=0;i<m_fiaSourceInfos.GetSize();i++)
sf.WriteString("\""+m_fiaSourceInfos[i].GetFilePath() + "\"\n");
sf.WriteString(_T("TARGET FILES:\n"));
for (i=0;i<m_fiaTargetInfos.GetSize();i++)
sf.WriteString("\"" + m_fiaTargetInfos[i].GetFilePath() + "\"\n");
sf.WriteString(_T("MATCHED FILES:\n"));
for (i=0;i<m_msaMatchedInfos.GetSize();i++)
sf.WriteString("\"" + m_msaMatchedInfos[i].pfinSource->GetFilePath() + "\"" +
" \\ " + "\"" + m_msaMatchedInfos[i].pfinTarget->GetFilePath() + "\"\n");
sf.Close();
} catch (CException e) {
e.Delete();
}
}
}