unzipdlg.cpp

来自「zip的全部算法源代码」· C++ 代码 · 共 477 行

CPP
477
字号
/*************************************************************************
                     ZipALot
**************************************************************************

Copyright (C) October, 2000 Jean-Pierre Bergamin, james@ractive.ch

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
***************************************************************************/

// UnzipDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ZipALot.h"
#include "Unzip.h"
#include "UnzipDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CUnzipDlg dialog

extern HANDLE hStop;
extern CStringList g_sListCurfiles;
extern CStringList g_sListCurZIPfiles;

CUnzipDlg * CUnzipDlg::m_pPseudoThis = 0;


CUnzipDlg::CUnzipDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CUnzipDlg::IDD, pParent), m_Mutex(FALSE, NULL)
{
	//{{AFX_DATA_INIT(CUnzipDlg)
	m_pbCloseWhenDone = NULL;
	//}}AFX_DATA_INIT

	m_pPseudoThis = this;
	m_htiCurFile = NULL;
}


void CUnzipDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CUnzipDlg)
	DDX_Control(pDX, IDC_DETAILGROUP, m_DetailGroup);
	DDX_Control(pDX, IDC_FILETREE, m_FileTree);
	DDX_Control(pDX, IDC_ANIMATION, m_Animation);
	DDX_Control(pDX, IDC_PROGRESS, m_Progress);
	DDX_Check(pDX, IDC_CLOSE, *m_pbCloseWhenDone);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CUnzipDlg, CDialog)
	//{{AFX_MSG_MAP(CUnzipDlg)
	ON_WM_CLOSE()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_SHOWDETAILS, OnShowDetails)
	ON_BN_CLICKED(IDC_CANCEL, OnClose)
	//}}AFX_MSG_MAP

	ON_MESSAGE(WM_EXTRACT_RANGE, OnRange)
	ON_MESSAGE(WM_EXTRACT_ERROR, OnError)
	ON_MESSAGE(WM_EXTRACT_STEPIT, OnStepIt)
	ON_MESSAGE(WM_EXTRACT_CURFILE, OnCurFile)
	ON_MESSAGE(WM_EXTRACT_CURZIPFILE, OnCurZIPFile)
	ON_MESSAGE(WM_EXTRACT_SETSOURCE, OnSetSource)
	ON_MESSAGE(WM_EXTRACT_SETTARGET, OnSetTarget)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CUnzipDlg message handlers

BOOL CUnzipDlg::Pump()
{
	MSG msg;

	// Retrieve and dispatch any waiting messages.

	while (::PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {
		if (!AfxGetApp ()->PumpMessage ()) {
			::PostQuitMessage (0);
			return FALSE;
		}
	}

	return TRUE;

}


void CUnzipDlg::UpdateDlg(LPCTSTR sFileName)
{
	CString sText;
	CString sName(sFileName);
	// The DLL returns Unix-like file-separators. Replace them
	sName.Replace('/', '\\');
	int nFirst = sName.ReverseFind('\\') + 1;
	sName = sName.Mid(nFirst);
	m_pPseudoThis->AddExtractedFile(sName);
}

void CUnzipDlg::SetRange(UINT nRange)
{
	m_pPseudoThis->ShowWindow(SW_SHOW);

	// Set the range of the Progress bar
	m_pPseudoThis->m_Progress.SetRange32(0, nRange);
	m_pPseudoThis->m_noOfFiles = nRange;
	// Set the step width to 1
	m_pPseudoThis->m_Progress.SetStep(1);
	m_pPseudoThis->m_Progress.SetPos(0);
	m_pPseudoThis->m_nErrors = 0;
	m_pPseudoThis->m_nFileNo = 1;

	//m_pPseudoThis->ShowDetails(FALSE);
}

void CUnzipDlg::StepIt()
{
	m_pPseudoThis->m_Progress.StepIt();
}

void CUnzipDlg::ShowCurZIPFile(LPCTSTR sFileName)
{
	// Show information with the new ZIP file.
	CString sFiles;
	sFiles.Format("Extracting file %d from %d", m_pPseudoThis->m_nFileNo++, m_pPseudoThis->m_noOfFiles);
	m_pPseudoThis->SetDlgItemText(IDC_FILEOF, sFiles);
	m_pPseudoThis->SetDlgItemText(IDC_STATICFILENAME, sFileName);
	m_pPseudoThis->AddCurFile(sFileName);
}


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

	// Load the indizes of these two file types so that
	// they don't have to be determined every time.
	CString sExt = "C:\\*.zip";
	m_nZIPIconIndex = GetIconIndex(sExt);
	sExt = "C:\\*.txt";
	m_nTXTIconIndex = GetIconIndex(sExt);

	HIMAGELIST hSmallSystemImageList;
	SHFILEINFO shinfo;

	// Get the handle of the (normal) system imagelist.
	hSmallSystemImageList = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\\"), 0, &shinfo, sizeof(shinfo), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
	m_ImageList.Attach(hSmallSystemImageList);
	::SendMessage(m_FileTree.m_hWnd, TVM_SETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)hSmallSystemImageList);
	m_ImageList.Detach();
	m_nErrors = 0;
	m_nFileNo = 1;

	m_bInfoShown = TRUE;

	ShowDetails(FALSE);

	m_Animation.Open(IDR_EXTRACT);
	SetDlgItemText(IDC_SOURCE, m_sSourceDir);
	SetDlgItemText(IDC_TARGET, m_sTargetDir);

	m_noOfFiles = 0;

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CUnzipDlg::OnClose() 
{
	if (!m_bCanClose) {
		SetEvent(hStop);
		return;
	}
	
	UpdateData();

	CDialog::OnClose();
}

void CUnzipDlg::EndStatus()
{
	m_Animation.Stop();
	m_Animation.Seek(0);
	CString sMsg;
	if (m_nErrors > 0) {
		sMsg.Format("All files processed. %d Errors!", m_nErrors);
	}
	else {
		sMsg = "All files extracted";
	}
	SetDlgItemText(IDC_FILEOF, sMsg);
	m_Progress.SetPos(0);
	m_FileTree.Invalidate();
	SetWindowText("Finished");
	GetDlgItem(IDC_CANCEL)->ModifyStyle(WS_VISIBLE, 0);
	RECT updateRect;
	GetDlgItem(IDC_CANCEL)->GetWindowRect(&updateRect);
	ScreenToClient(&updateRect);
	InvalidateRect(&updateRect, TRUE);
	UpdateWindow();
	MessageBeep(MB_OK);
}

void CUnzipDlg::CancelStatus()
{
	m_Animation.Stop();
	m_Animation.Seek(0);
	SetDlgItemText(IDC_FILEOF, "Extraction cancelled by user!");
	SetWindowText("CANCELLED");
	MessageBeep(MB_ICONEXCLAMATION);
}


void CUnzipDlg::AddCurFile(LPCTSTR sName)
{
	m_htiCurFile = m_FileTree.InsertItem(sName, m_nZIPIconIndex, m_nZIPIconIndex);
	m_FileTree.EnsureVisible(m_htiCurFile);
}

void CUnzipDlg::AddExtractedFile(LPCTSTR sName)
{
	if (m_htiCurFile) {
		CString sExt = sName;
		sExt = "C:\\*" + sExt.Mid(sExt.ReverseFind('.'));
		int nImage = GetIconIndex(sExt);
		HTREEITEM hInserted = m_FileTree.InsertItem(sName, nImage, nImage, m_htiCurFile);
		HTREEITEM hParent = NULL;
		if (hParent = m_FileTree.GetParentItem(hInserted)) {
			if (m_FileTree.GetItemState(hParent, TVIF_STATE) & TVIS_EXPANDED) {
				m_FileTree.EnsureVisible(hInserted);
			}
		}
	}
}

int CUnzipDlg::GetIconIndex(const CString &sPath)
{
	SHFILEINFO shinfo;

	// We get the index of the file from the ImageList.

	// WARNING: These calls are hideously expensive in terms of time!!!
	SHGetFileInfo(sPath, FILE_ATTRIBUTE_NORMAL, &shinfo, sizeof(shinfo), SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
	return shinfo.iIcon;
}

void CUnzipDlg::OnDestroy() 
{
	CDialog::OnDestroy();

	//m_ImageList.Detach();
}

void CUnzipDlg::ErrorInCurFile(errorCode error, LPCTSTR sFile /* = NULL */)
{
	CString sErrorMsg;
	CString sFileName;
	if (sFile) {
		sFileName = sFile;
	}
	switch(error) {
		case EX_OK:
			return;
		case EX_ARCHIVE:
			sErrorMsg = "Error in Archive file " + sFileName;
			break;
		case EX_MEM:
			sErrorMsg = "Not enough free memory available";
			break;
		case EX_NO_ARCHIVES:
			sErrorMsg = "No archives found";
			break;
		case EX_NO_FILES:
			sErrorMsg = "No files in archive found " + sFileName;
			break;
		case EX_DISK:
			sErrorMsg = "The disk is probably full";
			break;
		case EX_EOF:
			sErrorMsg = "Unexpected end of file found. Archive is probably corrupt";
			break;
		case EX_UNSUP:
			sErrorMsg = "Unsupported archive type";
			break;
		case EX_BADPWD:
			sErrorMsg = "Bad password for file " + sFileName;
			break;
		case EX_CRC:
			sErrorMsg = "CRC error in " + sFileName + ". Data is probably corrupt";
			break;
		case EX_OPEN:
			sErrorMsg = sFileName + " could not be opened";
			break;
		case EX_CLOSE:
			sErrorMsg = sFileName + " could not be closed";
			break;
		case EX_READ:
			sErrorMsg = "No data could be read from " + sFileName;
			break;
		case EX_WRITE:
			sErrorMsg = "No data could be written to " + sFileName;
			break;
		case EX_CREATE:
			sErrorMsg = sFileName + " could not be created";
			break;
		default:
			sErrorMsg = "Unknown Error while processing files";
	}
	m_pPseudoThis->m_nErrors++;
	// Bold this entry
	m_pPseudoThis->m_FileTree.SetItemState(m_pPseudoThis->m_htiCurFile, TVIS_BOLD, TVIS_BOLD);
	// Delete the added files from this item
	m_pPseudoThis->DeleteChildren(m_pPseudoThis->m_htiCurFile);
	// Change the item image to the txt image
	m_pPseudoThis->m_FileTree.SetItemImage(m_pPseudoThis->m_htiCurFile, m_pPseudoThis->m_nTXTIconIndex, m_pPseudoThis->m_nTXTIconIndex);
	// Insert the error message
	m_pPseudoThis->m_FileTree.InsertItem(sErrorMsg, m_pPseudoThis->m_nTXTIconIndex, m_pPseudoThis->m_nTXTIconIndex, m_pPseudoThis->m_htiCurFile);
	m_pPseudoThis->m_FileTree.Expand(m_pPseudoThis->m_htiCurFile, TVE_EXPAND);
}

void CUnzipDlg::DeleteChildren(HTREEITEM hParent)
{
	if (!hParent) {
		return;
	}

	HTREEITEM hChild = m_FileTree.GetChildItem(hParent), hTemp;
	while (hChild != NULL) {
		hTemp = m_FileTree.GetNextSiblingItem(hChild);
		m_FileTree.DeleteItem(hChild);
		hChild = hTemp;
	}
}



void CUnzipDlg::OnShowDetails() 
{
	ShowDetails(!m_bInfoShown);
}

void CUnzipDlg::ShowDetails(BOOL bShow)
{
	if (m_bInfoShown && bShow) {
		return;
	}
	if (!m_bInfoShown && !bShow) {
		return;
	}



	RECT dlgrect, inforect;
	GetWindowRect(&dlgrect);
	m_DetailGroup.GetWindowRect(&inforect);


	if (bShow) {
		// Expand the dialog
		dlgrect.bottom += (inforect.bottom - inforect.top);
		SetDlgItemText(IDC_SHOWDETAILS, "<<< Details");
		m_bInfoShown = TRUE;
	}
	else {
		// Make the dialog smaller.
		dlgrect.bottom -= (inforect.bottom - inforect.top);
		SetDlgItemText(IDC_SHOWDETAILS, "Details >>>");
		m_bInfoShown = FALSE;
	}

	MoveWindow(&dlgrect);

	// Force the window to be redrawn
	InvalidateRect(NULL);
	UpdateWindow();
}

BOOL CUnzipDlg::CloseIfDone()
{
	UpdateData();
	if (m_bCanClose && m_nErrors == 0 && *m_pbCloseWhenDone) {
		EndDialog(0);
		return TRUE;
	}

	return FALSE;
}

void CUnzipDlg::OnRange(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);

	lock.Lock();
	SetRange(lParam);
	lock.Unlock();
}

void CUnzipDlg::OnCurFile(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);
	lock.Lock();
	UpdateDlg(g_sListCurfiles.RemoveHead());
	lock.Unlock();
}

void CUnzipDlg::OnCurZIPFile(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);
	lock.Lock();
	ShowCurZIPFile(g_sListCurZIPfiles.RemoveHead());
	lock.Unlock();
}

void CUnzipDlg::OnStepIt(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);
	StepIt();
	lock.Unlock();
}	

void CUnzipDlg::OnError(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);
	lock.Lock();
	ErrorInCurFile((errorCode)lParam, (LPTSTR)pParam);
	lock.Unlock();
}


void CUnzipDlg::OnSetSource(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);
	lock.Lock();
	GetDlgItem(IDC_SOURCE)->SetWindowText((LPTSTR)lParam);
	lock.Unlock();
}

void CUnzipDlg::OnSetTarget(UINT pParam, long lParam)
{
	CSingleLock lock(&m_Mutex);
	lock.Lock();
	GetDlgItem(IDC_TARGET)->SetWindowText((LPTSTR)lParam);
	lock.Unlock();
}


void CUnzipDlg::Kill()
{
	CSingleLock lock(&m_Mutex);
	lock.Lock();
	UpdateData();
	EndDialog(0);
	DestroyWindow();
	lock.Unlock();
}

⌨️ 快捷键说明

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