📄 fileopendialog.cpp
字号:
/*
* Copyright (c) 2001,2002,2003 Mike Matsnev. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice immediately at the beginning of the file, without modification,
* this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Absolutely no warranty of function or purpose is made by the author
* Mike Matsnev.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: FileOpenDialog.cpp,v 1.24.2.14 2004/10/21 16:54:45 mike Exp $
*
*/
#include <afxcmn.h>
#include "resource.h"
#include "ptr.h"
#include "ZipFile.h"
#include "FileOpenDialog.h"
#include "TextViewNG.h"
#include "config.h"
#include "XListBox.h"
#if POCKETPC
#include <afxext.h>
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define T_UP 0
#define T_DIR 1
#define T_FILE 2
// string compare
#define CmpI(s1,s2) \
(::CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE, \
(s1),-1,(s2),-1)-2)
CString GetFileName(CString *filepath,CWnd *parent) {
CFileOpenDialog dlg(parent);
if (filepath && filepath->GetLength()>0) {
DWORD attr=GetFileAttributes(*filepath);
if (attr!=0xffffffff && ((attr&FILE_ATTRIBUTE_DIRECTORY) ||
(filepath->GetLength()>4 && filepath->Right(4).CompareNoCase(_T(".zip"))==0)))
dlg.m_path=*filepath;
}
int ret=dlg.DoModal();
if (filepath)
*filepath=dlg.m_path;
if (ret==IDOK)
return dlg.m_filename;
return CString();
}
/////////////////////////////////////////////////////////////////////////////
// CFileOpenDialog dialog
CFileOpenDialog::CFileOpenDialog(CWnd* pParent /*=NULL*/)
: CDialog(CFileOpenDialog::IDD, pParent), m_path(_T("\\"))
{
//{{AFX_DATA_INIT(CFileOpenDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CFileOpenDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFileOpenDialog)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CFileOpenDialog, CDialog)
//{{AFX_MSG_MAP(CFileOpenDialog)
ON_MESSAGE(XLM_CLICK,OnXClick)
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFileOpenDialog message handlers
BOOL CFileOpenDialog::OnInitDialog()
{
CDialog::OnInitDialog();
#if POCKETPC
((CCeCommandBar *)m_pWndEmptyCB)->LoadToolBar(cIDR_DIALOG);
#endif
HWND hList=::GetDlgItem(m_hWnd,IDC_FILELIST);
XLB_SetImageList(hList,CTVApp::ImageList()->GetSafeHandle(),true);
// fill in the dialog
DWORD attr=GetFileAttributes(m_path);
if (attr&FILE_ATTRIBUTE_DIRECTORY)
FindFiles();
else
OpenItem(m_path);
return TRUE;
}
static int get_file_icon(const TCHAR *name,bool inzip=false) {
int l=_tcslen(name);
if (l<=4)
return IM_FILE;
if (!CmpI(name+l-4,_T(".txt")) || !CmpI(name+l-4,_T(".xml")) ||
!CmpI(name+l-4,_T(".prc")) || !CmpI(name+l-4,_T(".pdb")) ||
!CmpI(name+l-4,_T(".fb2")) || !CmpI(name+l-4,_T(".dic")))
return IM_TEXT;
if (!inzip && !CmpI(name+l-4,_T(".zip")))
return IM_ZIP;
if (!CmpI(name+l-4,_T(".png")) || !CmpI(name+l-4,_T(".jpg")) ||
(l>5 && !CmpI(name+l-5,_T(".jpeg"))))
return IM_IMAGE;
return IM_FILE;
}
static void FormatSize(__int64 size,CString& str) {
if (size < 1000)
str.Format(_T("%d"),(int)size);
else if (size < 1024*10) // < 10k
str.Format(_T("%.2fk"),size/1024.0);
else if (size < 1024*100) // < 100k
str.Format(_T("%.1fk"),size/1024.0);
else if (size < 1024*1000) // < 1000k
str.Format(_T("%dk"),(int)(size>>10));
else if (size < 1024*1024*10) // < 10m
str.Format(_T("%.2fm"),size/1048576.0);
else if (size < 1024*1024*100) // < 100m
str.Format(_T("%.1fm"),size/1048576.0);
else if (size < 1024*1024*1000) // < 1000m
str.Format(_T("%dm"),(int)(size>>20));
else if (size < 1024*1024*1024*10i64) // < 10g
str.Format(_T(".2fg"),size/1073741824.0);
else if (size < 1024*1024*1024*100i64) // < 100g
str.Format(_T(".1fg"),size/1073741824.0);
else // >= 100g
str.Format(_T("%d"),(int)(size>>30));
}
void CFileOpenDialog::FindFiles(bool showall)
{
#ifdef _WIN32_WCE
// show current path
SetDlgItemText(IDC_FILEPATH,m_zip.get() ? m_filename : m_path);
#else
CString tmppath(m_zip.get() ? m_filename : m_path);
if (tmppath.GetLength()>0 && tmppath[0]==_T('\\'))
tmppath.Delete(0);
SetDlgItemText(IDC_FILEPATH,tmppath);
#endif
// fetch our control
HWND hList=::GetDlgItem(m_hWnd,IDC_FILELIST);
// delete all files
XLB_DeleteAllItems(hList);
XLB_Handle *handle=XLB_GetHandle(hList);
LARGE_INTEGER ui;
CString tmp;
if (m_zip.get()) { // we are inside zip file
bool dir;
CString cur;
m_zip->Reset();
for (int i=0;m_zip->GetNextFileInfo(cur,dir,ui.QuadPart);++i) {
if (!dir)
FormatSize(ui.QuadPart,tmp);
int icon=get_file_icon(cur,true);
if (dir || showall || icon!=IM_FILE)
XLB_AppendItem(handle,cur,dir ? NULL : (const TCHAR *)tmp,
dir ? IM_DIR : icon,
0,
dir ? T_DIR : T_FILE);
}
} else {
#ifndef _WIN32_WCE
// have to handle fucking disk drives
if (m_path.GetLength()==0 || (m_path.GetLength()==1 && m_path[0]==_T('\\')))
{
TCHAR buf[4];
buf[1]=_T(':'); buf[3]=_T('\0');
int i=0;
for (TCHAR drive='A';drive<='Z';++drive) {
buf[0]=drive;
buf[2]=_T('\\');
UINT dt=GetDriveType(buf);
if (dt!=DRIVE_UNKNOWN && dt!=DRIVE_NO_ROOT_DIR) {
buf[2]=_T('\0');
XLB_AppendItem(handle,buf,NULL,IM_DIR,0,T_DIR);
++i;
}
}
goto out; // no .. here
}
#endif
// build a search pattern
CString pat=m_path;
if (pat.GetLength()==0 || pat[pat.GetLength()-1]!=_T('\\'))
pat+=_T('\\');
pat+=_T('*');
#ifndef _WIN32_WCE
// remove leading \
if (pat.GetLength()>0 && pat[0]==_T('\\'))
pat.Delete(0);
#endif
// now try to find files
WIN32_FIND_DATA fd;
HANDLE fh;
bool run;
fh=FindFirstFile(pat,&fd);
run=fh!=INVALID_HANDLE_VALUE;
for (int i=0;run;) {
if (!(fd.cFileName[0]==_T('.') && (!fd.cFileName[1] ||
(fd.cFileName[1]==_T('.') && !fd.cFileName[2]))))
{
bool dir=(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0;
int icon;
if (!dir) {
icon=get_file_icon(fd.cFileName);
ui.LowPart=fd.nFileSizeLow;
ui.HighPart=fd.nFileSizeHigh;
FormatSize(ui.QuadPart,tmp);
}
if (dir || showall || icon!=IM_FILE)
XLB_AppendItem(handle,fd.cFileName,dir ? NULL : (const TCHAR *)tmp,
dir?IM_DIR:icon,0,dir ? T_DIR : T_FILE);
}
run=FindNextFile(fh,&fd)!=0;
}
if (fh!=INVALID_HANDLE_VALUE)
FindClose(fh);
}
if (m_path.GetLength()>1 || m_zip.get())
XLB_AppendItem(handle,_T(".."),NULL,IM_DIR,0,T_UP);
#ifndef _WIN32_WCE
out:
#endif
XLB_UpdateState(hList);
XLB_SortItems(hList);
::InvalidateRect(hList,NULL,FALSE);
}
LRESULT CFileOpenDialog::OnXClick(WPARAM wParam,LPARAM lParam)
{
HWND list=::GetDlgItem(m_hWnd,IDC_FILELIST);
ActivateItem(list,XLB_GetSelection(list));
return 0;
}
void CFileOpenDialog::ActivateItem(HWND list, int item) {
int type=XLB_GetData(list,item);
if (type==T_DIR || type==T_UP) { // change dir
CString path=XLB_GetItemText1(list,item);
if (path==_T("..")) { // one level up
int bsp=m_path.ReverseFind(_T('\\'));
if (bsp>0)
m_path=m_path.Left(bsp);
else
m_path=_T("\\");
} else {
if (m_path.GetLength()>0 && m_path[m_path.GetLength()-1]!=_T('\\'))
m_path+=_T('\\');
m_path+=path;
}
if (m_zip.get() && !m_zip->SetDir(path)) // get out of this zip
m_zip.reset();
FindFiles();
} else { // selected item
m_filename=m_path;
if (m_filename.GetLength()==0 || m_filename[m_filename.GetLength()-1]!=_T('\\'))
m_filename+=_T('\\');
m_filename+=XLB_GetItemText1(list,item);
#ifndef _WIN32_WCE
// strip leading \
if (m_filename.GetLength()>0 && m_filename[0]==_T('\\'))
m_filename.Delete(0);
#endif
if (!m_zip.get() && m_filename.GetLength()>4 &&
!m_filename.Right(4).CompareNoCase(_T(".zip")))
{
OpenItem(m_filename);
} else {
if (m_zip.get())
m_path=m_vpath;
EndDialog(IDOK);
}
}
}
void CFileOpenDialog::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
RECT r,rc;
GetClientRect(&r);
rc=r;
rc.bottom=rc.top+HIWORD(GetDialogBaseUnits())+5;
--rc.left; --rc.top; ++rc.right;
CWnd *ctl=GetDlgItem(IDC_FILEPATH);
if (ctl)
ctl->MoveWindow(&rc);
CWnd *list=GetDlgItem(IDC_FILELIST);
if (list) {
rc=r;
rc.top+=HIWORD(GetDialogBaseUnits())+5;
list->MoveWindow(&rc);
XLB_EnsureVisible(list->m_hWnd,XLB_GetSelection(list->m_hWnd));
}
}
void CFileOpenDialog::OnOK() {
HWND list=::GetDlgItem(m_hWnd,IDC_FILELIST);
int item=XLB_GetSelection(list);
if (item>=0)
ActivateItem(list,item);
}
void CFileOpenDialog::OpenItem(const CString &path) { // looks like a zip file
CFile *fp=new CFile;
CFileException ex;
if (!fp->Open(path,CFile::modeRead|CFile::shareDenyWrite,&ex)) {
MessageBox(_T("Can't open zip file"),_T("Error"),MB_OK|MB_ICONERROR);
delete fp;
} else {
m_zip=new ZipFile(path);
if (!m_zip->ReadZip()) {
MessageBox(_T("Invalid or unsupported ZIP file"),_T("Error"),MB_OK|MB_ICONERROR);
m_zip.reset(0);
} else {
CString tmp;
if (m_zip->IsSingleFile(&tmp)) {
m_filename=path+_T("\\")+tmp;
EndDialog(IDOK);
} else {
m_vpath=m_path;
m_path=m_filename=path;
FindFiles();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -