whatifdlg.cpp
来自「zip的全部算法源代码」· C++ 代码 · 共 461 行
CPP
461 行
/*************************************************************************
ZipALot
**************************************************************************
Copyright (C) December, 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.
***************************************************************************/
// WhatIfDlg.cpp : implementation file
//
#include "stdafx.h"
#include "ZipALot.h"
#include "WhatIfDlg.h"
#include "Unzip.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_READ (WM_USER + 23)
extern HANDLE hStop;
CWhatIfDlg * CWhatIfDlg::m_pPseudoThis = NULL;
/////////////////////////////////////////////////////////////////////////////
// CWhatIfDlg dialog
CWhatIfDlg::CWhatIfDlg(tagUnzipInfo * pInfo, CWnd* pParent /*=NULL*/)
: CDialog(CWhatIfDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CWhatIfDlg)
m_sInfo = _T("");
m_sStatus = _T("");
//}}AFX_DATA_INIT
m_pUnzipInfo = pInfo;
m_pPseudoThis = this;
m_bCanClose = TRUE;
m_bSortAscending = TRUE;
m_dwPackedSize = 0;
m_dwUnpackedSize = 0;
m_nEncrypted = 0;
m_nFiles = 0;
m_nSortedCol = 0;
}
void CWhatIfDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CWhatIfDlg)
DDX_Control(pDX, IDC_FILELIST, m_FileList);
DDX_Text(pDX, IDC_INFO, m_sInfo);
DDX_Text(pDX, IDC_STATUS, m_sStatus);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CWhatIfDlg, CDialog)
//{{AFX_MSG_MAP(CWhatIfDlg)
ON_WM_DESTROY()
ON_WM_CLOSE()
ON_NOTIFY(HDN_ITEMCLICK, 0, OnHeaderClick)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_READ, OnRead)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWhatIfDlg message handlers
BOOL CWhatIfDlg::OnInitDialog()
{
CDialog::OnInitDialog();
int nItem = 0;
int nSubItem = 0;
// Add the list control headers
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.iSubItem = nSubItem++;
lvc.cx = 200;
lvc.pszText = _T("Name");
m_FileList.InsertColumn(0, &lvc);
lvc.fmt = LVCFMT_RIGHT;
lvc.iSubItem = nSubItem++;
lvc.cx = 70;
lvc.pszText = _T("Unpacked");
m_FileList.InsertColumn(1, &lvc);
lvc.fmt = LVCFMT_RIGHT;
lvc.iSubItem = nSubItem++;
lvc.cx = 70;
lvc.pszText = _T("Packed");
m_FileList.InsertColumn(2, &lvc);
lvc.fmt = LVCFMT_RIGHT;
lvc.iSubItem = nSubItem++;
lvc.cx = 40;
lvc.pszText = _T("Ratio");
m_FileList.InsertColumn(3, &lvc);
lvc.fmt = LVCFMT_RIGHT;
lvc.iSubItem = nSubItem++;
lvc.cx = 100;
lvc.pszText = _T("Date/Time");
m_FileList.InsertColumn(4, &lvc);
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_FileList.m_hWnd, LVM_SETIMAGELIST, (WPARAM)LVSIL_SMALL, (LPARAM)hSmallSystemImageList);
m_ImageList.Detach();
m_sInfo = "Output of unzip operation to ";
m_sInfo += m_pUnzipInfo->sTarget;
UpdateData(FALSE);
AfxBeginThread(FillFileList, NULL);
m_nFiles = 0;
m_dwPackedSize = 0;
m_dwUnpackedSize = 0;
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CWhatIfDlg::OnDestroy()
{
CDialog::OnDestroy();
//m_ImageList.Detach();
}
void CWhatIfDlg::OnClose()
{
if (!m_bCanClose) {
return;
}
//m_ImageList.Detach();
CDialog::OnClose();
}
void CWhatIfDlg::InsertFile(CString sName, DWORD dwSize, DWORD dwPackedSize, int nRatio, char cEncrypted, CString sDateTime)
{
// Check for directories in the filename
// Remove them if we dont have bRecreateDir
int nFind = -1;
if ((nFind = sName.ReverseFind('\\')) != -1 && !m_pPseudoThis->m_pUnzipInfo->bRecreateDir) {
// Extract only the filename
sName = sName.Mid(nFind + 1);
}
LVFINDINFO fi;
fi.flags = LVFI_STRING;
fi.psz = sName;
int nReplace = FALSE;
nReplace = m_pPseudoThis->m_FileList.FindItem(&fi);
if (nReplace != -1 ) {
if (!m_pPseudoThis->m_pUnzipInfo->bOverwrite) {
// The file is already present and shall not be overwritten
// We leave.
return;
}
}
int nItem = 0;
int nSubItem = 0;
LV_ITEM item;
item.mask = LVIF_TEXT | LVIF_IMAGE;
item.iItem = nItem++;
item.iSubItem = nSubItem++;
CString sExt = "C:\\*";
sExt += sName.Mid(sName.ReverseFind('.'));
item.iImage = m_pPseudoThis->GetIconIndex(sExt);
if (cEncrypted == 'E') {
//sName += "+";
m_pPseudoThis->m_nEncrypted++;
}
item.pszText = (LPTSTR)(LPCTSTR)sName;
if (m_pPseudoThis->m_pUnzipInfo->bOverwrite) {
// Replace the existing item
item.iItem = nReplace;
m_pPseudoThis->m_FileList.SetItem(&item);
}
else {
item.iItem = m_pPseudoThis->m_FileList.InsertItem(&item);
}
item.mask = LVIF_TEXT;
// Add size
CString sEntryText;
sEntryText.Format("%ld", dwSize);
item.pszText = (LPTSTR)(LPCTSTR)sEntryText;
item.iSubItem = 1;
m_pPseudoThis->m_FileList.SetItem(&item);
// Add Unpacked Size
sEntryText.Format("%ld", dwPackedSize);
item.iSubItem = 2;
item.pszText = (LPTSTR)(LPCTSTR)sEntryText;
m_pPseudoThis->m_FileList.SetItem(&item);
// Add Ratio
sEntryText.Format("%d%%", nRatio);
item.iSubItem = 3;
item.pszText = (LPTSTR)(LPCTSTR)sEntryText;
m_pPseudoThis->m_FileList.SetItem(&item);
// Add Date
item.iSubItem = 4;
item.pszText = (LPTSTR)(LPCTSTR)sDateTime;
m_pPseudoThis->m_FileList.SetItem(&item);
m_pPseudoThis->m_nFiles++;
m_pPseudoThis->m_dwPackedSize += dwPackedSize;
m_pPseudoThis->m_dwUnpackedSize += dwSize;
}
int CWhatIfDlg::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;
}
UINT CWhatIfDlg::FillFileList(LPVOID lParam)
{
CWaitCursor wait;
// Do the unzipping...
CUnzip unzipper(NULL);
unzipper.Init();
hStop = CreateEvent(NULL, FALSE, FALSE, NULL);
unzipper.InsertFile = &InsertFile;
m_pPseudoThis->m_pUnzipInfo->bExtract = FALSE;
unzipper.unzipInfo = *m_pPseudoThis->m_pUnzipInfo;
m_pPseudoThis->m_bCanClose = FALSE;
int nRet = unzipper.ExtractAll(m_pPseudoThis->m_pUnzipInfo->sSource, m_pPseudoThis->m_pUnzipInfo->sTarget);
m_pPseudoThis->m_bCanClose = TRUE;
// This gives an access violation in MFC42.DLL in the releaseversion :-(
// Why?
//m_pPseudoThis->SendMessage(WM_READ);
m_pPseudoThis->OnRead();
return nRet;
}
BOOL CWhatIfDlg::SortItems(int nCol, BOOL bAscending, int low, int high)
{
if (nCol >= m_FileList.GetHeaderCtrl()->GetItemCount()) {
return FALSE;
}
if( high == -1 )
high = m_FileList.GetItemCount() - 1;
int lo = low;
int hi = high;
CString midItem;
if( hi <= lo )
return FALSE;
midItem = m_FileList.GetItemText( (lo+hi)/2, nCol );
// loop through the list until indices cross
while( lo <= hi ) {
// rowText will hold all column text for one row
CStringArray rowText;
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending ) {
//while( ( lo < high ) && (atoi(GetItemText(lo, nCol)) < midItem ) )
while( ( lo < high ) && ( CmpItems( m_FileList.GetItemText(lo, nCol) , midItem, nCol) < 0 ) )
++lo;
}
else {
//while( ( lo < high ) && (atoi(GetItemText(lo, nCol)) > midItem ) )
while( ( lo < high ) && ( CmpItems( m_FileList.GetItemText(lo, nCol) , midItem, nCol) > 0 ) )
++lo;
}
// find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending ) {
//while( ( hi > low ) && (atoi(GetItemText(hi, nCol)) > midItem ) )
while( ( hi > low ) && ( CmpItems(m_FileList.GetItemText(hi, nCol) , midItem, nCol ) > 0 ) )
--hi;
}
else {
//while( ( hi > low ) && (atoi(GetItemText(hi, nCol)) < midItem ) )
while( ( hi > low ) && ( CmpItems(m_FileList.GetItemText(hi, nCol) , midItem, nCol ) < 0 ) )
--hi;
}
// if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi ) {
// swap only if the items are not equal
//if(atoi(GetItemText(lo, nCol)) != atoi(GetItemText(hi, nCol)) ) /*!!!*
if( CmpItems (m_FileList.GetItemText(lo, nCol) , m_FileList.GetItemText(hi, nCol), nCol ) != 0) {
// swap the rows
LV_ITEM lvitemlo, lvitemhi;
int nColCount = m_FileList.GetHeaderCtrl()->GetItemCount();
rowText.SetSize( nColCount );
int i;
for( i=0; i < nColCount; i++)
rowText[i] = m_FileList.GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
lvitemhi = lvitemlo;
lvitemhi.iItem = hi;
m_FileList.GetItem( &lvitemlo );
m_FileList.GetItem( &lvitemhi );
for( i=0; i< nColCount; i++)
m_FileList.SetItemText(lo, i, m_FileList.GetItemText(hi, i) );
lvitemhi.iItem = lo;
m_FileList.SetItem( &lvitemhi );
for( i=0; i< nColCount; i++)
m_FileList.SetItemText(hi, i, rowText[i]);
lvitemlo.iItem = hi;
m_FileList.SetItem( &lvitemlo );
}
++lo;
--hi;
}
}
// If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortItems( nCol, bAscending , low, hi);
// If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortItems( nCol, bAscending , lo, high );
return TRUE;
}
int CWhatIfDlg::CmpItems(CString cstL, CString cstR, int nCol)
{
if (nCol == 0 || nCol == 3) {
return cstL.CompareNoCase(cstR);
}
else if (nCol == 1 || nCol == 2) {
if (cstR == cstL)
return 0;
else if (atol((LPCTSTR)cstL) < atol((LPCTSTR)cstR))
return -1;
else
return 1;
}
else if (nCol == 4) {
COleDateTime odtL;
COleDateTime odtR;
odtL.ParseDateTime(cstL);
odtR.ParseDateTime(cstR);
COleDateTimeSpan spanElapsed = odtL - odtR;
if (spanElapsed.GetStatus() == COleDateTimeSpan::invalid) {
return 0;
}
return (int)spanElapsed.GetTotalSeconds();
}
return 0;
}
void CWhatIfDlg::OnHeaderClick(NMHDR* pNMHDR, LRESULT* pResult)
{
HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
// TODO: Add your control notification handler code here
m_nSortedCol = phdn->iItem;
m_bSortAscending = !m_bSortAscending;
SortItems(m_nSortedCol, m_bSortAscending, 0, -1);
*pResult = 0;
}
void CWhatIfDlg::OnRead()
{
m_sStatus.Format("%d files - unpacked: %s - packed: %s Bytes", m_nFiles, FormatNumber(m_dwUnpackedSize), FormatNumber(m_dwPackedSize));
CString sEnc;
if (m_nEncrypted > 0) {
sEnc.Format(" - %d encrypted [+]", m_nEncrypted);
m_sStatus += sEnc;
}
ULARGE_INTEGER ulFreeToCaller;
ULARGE_INTEGER ulFreeDisk;
ULARGE_INTEGER ulFreeTotal;
BOOL bRet = GetDiskFreeSpaceEx(m_pUnzipInfo->sTarget, &ulFreeToCaller, &ulFreeDisk, &ulFreeTotal);
// bRet may be FALSE, if the target directory does not exist yet.
if (bRet && ulFreeToCaller.LowPart < m_dwUnpackedSize) {
MessageBox("ATTENTION! This operation would exceed your free disk space!", "DISK FULL", MB_ICONEXCLAMATION);
}
if (bRet) {
sEnc.Format(" - Free disk space: %s", FormatNumber(ulFreeToCaller.LowPart));
m_sStatus += sEnc;
}
UpdateData(FALSE);
}
CString CWhatIfDlg::FormatNumber(DWORD dwNumber)
{
CString sNumber;
sNumber.Format("%ld", dwNumber);
int nLen = sNumber.GetLength() - 3;
for (int i = nLen; i > 0; i -= 3) {
sNumber.Insert(i, '\'');
}
return sNumber;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?