FileOpenDialog.cpp
上传用户:hmc_gdtv
上传日期:2013-08-04
资源大小:798k
文件大小:11k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001,2002,2003 Mike Matsnev.  All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice immediately at the beginning of the file, without modification,
  10.  *    this list of conditions, and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. Absolutely no warranty of function or purpose is made by the author
  15.  *    Mike Matsnev.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * 
  28.  * $Id: FileOpenDialog.cpp,v 1.24.2.14 2004/10/21 16:54:45 mike Exp $
  29.  * 
  30.  */
  31. #include <afxcmn.h>
  32. #include "resource.h"
  33. #include "ptr.h"
  34. #include "ZipFile.h"
  35. #include "FileOpenDialog.h"
  36. #include "TextViewNG.h"
  37. #include "config.h"
  38. #include "XListBox.h"
  39. #if POCKETPC
  40. #include <afxext.h>
  41. #endif
  42. #ifdef _DEBUG
  43. #define new DEBUG_NEW
  44. #undef THIS_FILE
  45. static char THIS_FILE[] = __FILE__;
  46. #endif
  47. #define T_UP 0
  48. #define T_DIR 1
  49. #define T_FILE 2
  50. // string compare
  51. #define CmpI(s1,s2) 
  52.     (::CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE, 
  53.     (s1),-1,(s2),-1)-2)
  54. CString GetFileName(CString *filepath,CWnd *parent) {
  55.   CFileOpenDialog   dlg(parent);
  56.   if (filepath && filepath->GetLength()>0) {
  57.     DWORD attr=GetFileAttributes(*filepath);
  58.     if (attr!=0xffffffff && ((attr&FILE_ATTRIBUTE_DIRECTORY) ||
  59. (filepath->GetLength()>4 && filepath->Right(4).CompareNoCase(_T(".zip"))==0)))
  60.       dlg.m_path=*filepath;
  61.   }
  62.   int ret=dlg.DoModal();
  63.   if (filepath)
  64.     *filepath=dlg.m_path;
  65.   if (ret==IDOK)
  66.     return dlg.m_filename;
  67.   return CString();
  68. }
  69. /////////////////////////////////////////////////////////////////////////////
  70. // CFileOpenDialog dialog
  71. CFileOpenDialog::CFileOpenDialog(CWnd* pParent /*=NULL*/)
  72. : CDialog(CFileOpenDialog::IDD, pParent), m_path(_T("\"))
  73. {
  74.   //{{AFX_DATA_INIT(CFileOpenDialog)
  75. // NOTE: the ClassWizard will add member initialization here
  76.   //}}AFX_DATA_INIT
  77. }
  78. void CFileOpenDialog::DoDataExchange(CDataExchange* pDX)
  79. {
  80.   CDialog::DoDataExchange(pDX);
  81.   //{{AFX_DATA_MAP(CFileOpenDialog)
  82. // NOTE: the ClassWizard will add DDX and DDV calls here
  83.   //}}AFX_DATA_MAP
  84. }
  85. BEGIN_MESSAGE_MAP(CFileOpenDialog, CDialog)
  86. //{{AFX_MSG_MAP(CFileOpenDialog)
  87. ON_MESSAGE(XLM_CLICK,OnXClick)
  88. ON_WM_SIZE()
  89. //}}AFX_MSG_MAP
  90. END_MESSAGE_MAP()
  91. /////////////////////////////////////////////////////////////////////////////
  92. // CFileOpenDialog message handlers
  93. BOOL CFileOpenDialog::OnInitDialog()
  94. {
  95.   CDialog::OnInitDialog();
  96. #if POCKETPC
  97.   ((CCeCommandBar *)m_pWndEmptyCB)->LoadToolBar(cIDR_DIALOG);
  98. #endif
  99.   HWND     hList=::GetDlgItem(m_hWnd,IDC_FILELIST);
  100.   XLB_SetImageList(hList,CTVApp::ImageList()->GetSafeHandle(),true);
  101.   // fill in the dialog
  102.   DWORD attr=GetFileAttributes(m_path);
  103.   if (attr&FILE_ATTRIBUTE_DIRECTORY)
  104.     FindFiles();
  105.   else
  106.     OpenItem(m_path);
  107.   return TRUE;
  108. }
  109. static int  get_file_icon(const TCHAR *name,bool inzip=false) {
  110.   int l=_tcslen(name);
  111.   if (l<=4)
  112.     return IM_FILE;
  113.   if (!CmpI(name+l-4,_T(".txt")) || !CmpI(name+l-4,_T(".xml")) ||
  114.       !CmpI(name+l-4,_T(".prc")) || !CmpI(name+l-4,_T(".pdb")) ||
  115.       !CmpI(name+l-4,_T(".fb2")) || !CmpI(name+l-4,_T(".dic")))
  116.     return IM_TEXT;
  117.   if (!inzip && !CmpI(name+l-4,_T(".zip")))
  118.     return IM_ZIP;
  119.   if (!CmpI(name+l-4,_T(".png")) || !CmpI(name+l-4,_T(".jpg")) ||
  120.       (l>5 && !CmpI(name+l-5,_T(".jpeg"))))
  121.     return IM_IMAGE;
  122.   return IM_FILE;
  123. }
  124. static void FormatSize(__int64 size,CString& str) {
  125.   if (size < 1000)
  126.     str.Format(_T("%d"),(int)size);
  127.   else if (size < 1024*10) // < 10k
  128.     str.Format(_T("%.2fk"),size/1024.0);
  129.   else if (size < 1024*100) // < 100k
  130.     str.Format(_T("%.1fk"),size/1024.0);
  131.   else if (size < 1024*1000) // < 1000k
  132.     str.Format(_T("%dk"),(int)(size>>10));
  133.   else if (size < 1024*1024*10) // < 10m
  134.     str.Format(_T("%.2fm"),size/1048576.0);
  135.   else if (size < 1024*1024*100) // < 100m
  136.     str.Format(_T("%.1fm"),size/1048576.0);
  137.   else if (size < 1024*1024*1000) // < 1000m
  138.     str.Format(_T("%dm"),(int)(size>>20));
  139.   else if (size < 1024*1024*1024*10i64) // < 10g
  140.     str.Format(_T(".2fg"),size/1073741824.0);
  141.   else if (size < 1024*1024*1024*100i64) // < 100g
  142.     str.Format(_T(".1fg"),size/1073741824.0);
  143.   else // >= 100g
  144.     str.Format(_T("%d"),(int)(size>>30));
  145. }
  146. void CFileOpenDialog::FindFiles(bool showall)
  147. {
  148. #ifdef _WIN32_WCE
  149.   // show current path
  150.   SetDlgItemText(IDC_FILEPATH,m_zip.get() ? m_filename : m_path);
  151. #else
  152.   CString   tmppath(m_zip.get() ? m_filename : m_path);
  153.   if (tmppath.GetLength()>0 && tmppath[0]==_T('\'))
  154.     tmppath.Delete(0);
  155.   SetDlgItemText(IDC_FILEPATH,tmppath);
  156. #endif
  157.   // fetch our control
  158.   HWND       hList=::GetDlgItem(m_hWnd,IDC_FILELIST);
  159.   // delete all files
  160.   XLB_DeleteAllItems(hList);
  161.   XLB_Handle  *handle=XLB_GetHandle(hList);
  162.   LARGE_INTEGER   ui;
  163.   CString   tmp;
  164.   if (m_zip.get()) { // we are inside zip file
  165.     bool    dir;
  166.     CString cur;
  167.     m_zip->Reset();
  168.     for (int i=0;m_zip->GetNextFileInfo(cur,dir,ui.QuadPart);++i) {
  169.       if (!dir)
  170. FormatSize(ui.QuadPart,tmp);
  171.       int icon=get_file_icon(cur,true);
  172.       if (dir || showall || icon!=IM_FILE)
  173. XLB_AppendItem(handle,cur,dir ? NULL : (const TCHAR *)tmp,
  174.   dir ? IM_DIR : icon,
  175.   0,
  176.   dir ? T_DIR : T_FILE);
  177.     }
  178.   } else {
  179. #ifndef _WIN32_WCE
  180.     // have to handle fucking disk drives
  181.     if (m_path.GetLength()==0 || (m_path.GetLength()==1 && m_path[0]==_T('\')))
  182.     {
  183.       TCHAR   buf[4];
  184.       buf[1]=_T(':'); buf[3]=_T('');
  185.       int   i=0;
  186.       for (TCHAR drive='A';drive<='Z';++drive) {
  187. buf[0]=drive;
  188. buf[2]=_T('\');
  189. UINT  dt=GetDriveType(buf);
  190. if (dt!=DRIVE_UNKNOWN && dt!=DRIVE_NO_ROOT_DIR) {
  191.   buf[2]=_T('');
  192.   XLB_AppendItem(handle,buf,NULL,IM_DIR,0,T_DIR);
  193.   ++i;
  194. }
  195.       }
  196.       goto out; // no .. here
  197.     }
  198. #endif
  199.     // build a search pattern
  200.     CString pat=m_path;
  201.     if (pat.GetLength()==0 || pat[pat.GetLength()-1]!=_T('\'))
  202.       pat+=_T('\');
  203.     pat+=_T('*');
  204. #ifndef _WIN32_WCE
  205.     // remove leading  
  206.     if (pat.GetLength()>0 && pat[0]==_T('\'))
  207.       pat.Delete(0);
  208. #endif
  209.     // now try to find files
  210.     WIN32_FIND_DATA fd;
  211.     HANDLE     fh;
  212.     bool     run;
  213.     fh=FindFirstFile(pat,&fd);
  214.     run=fh!=INVALID_HANDLE_VALUE;
  215.     for (int i=0;run;) {
  216.       if (!(fd.cFileName[0]==_T('.') && (!fd.cFileName[1] ||
  217.     (fd.cFileName[1]==_T('.') && !fd.cFileName[2]))))
  218.       {
  219. bool dir=(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0;
  220. int icon;
  221. if (!dir) {
  222.   icon=get_file_icon(fd.cFileName);
  223.   ui.LowPart=fd.nFileSizeLow;
  224.   ui.HighPart=fd.nFileSizeHigh;
  225.   FormatSize(ui.QuadPart,tmp);
  226. }
  227. if (dir || showall || icon!=IM_FILE)
  228.   XLB_AppendItem(handle,fd.cFileName,dir ? NULL : (const TCHAR *)tmp,
  229.     dir?IM_DIR:icon,0,dir ? T_DIR : T_FILE);
  230.       }
  231.       run=FindNextFile(fh,&fd)!=0;
  232.     }
  233.     if (fh!=INVALID_HANDLE_VALUE)
  234.       FindClose(fh);
  235.   }
  236.   if (m_path.GetLength()>1 || m_zip.get())
  237.     XLB_AppendItem(handle,_T(".."),NULL,IM_DIR,0,T_UP);
  238. #ifndef _WIN32_WCE
  239. out:
  240. #endif
  241.   XLB_UpdateState(hList);
  242.   XLB_SortItems(hList);
  243.   ::InvalidateRect(hList,NULL,FALSE);
  244. }
  245. LRESULT CFileOpenDialog::OnXClick(WPARAM wParam,LPARAM lParam)
  246. {
  247.   HWND list=::GetDlgItem(m_hWnd,IDC_FILELIST);
  248.   ActivateItem(list,XLB_GetSelection(list));
  249.   return 0;
  250. }
  251. void CFileOpenDialog::ActivateItem(HWND list, int item) {
  252.   int type=XLB_GetData(list,item);
  253.   if (type==T_DIR || type==T_UP) { // change dir
  254.     CString   path=XLB_GetItemText1(list,item);
  255.     if (path==_T("..")) { // one level up
  256.       int     bsp=m_path.ReverseFind(_T('\'));
  257.       if (bsp>0)
  258. m_path=m_path.Left(bsp);
  259.       else
  260. m_path=_T("\");
  261.     } else {
  262.       if (m_path.GetLength()>0 && m_path[m_path.GetLength()-1]!=_T('\'))
  263. m_path+=_T('\');
  264.       m_path+=path;
  265.     }
  266.     if (m_zip.get() && !m_zip->SetDir(path)) // get out of this zip
  267.       m_zip.reset();
  268.     FindFiles();
  269.   } else { // selected item
  270.     m_filename=m_path;
  271.     if (m_filename.GetLength()==0 || m_filename[m_filename.GetLength()-1]!=_T('\'))
  272.       m_filename+=_T('\');
  273.     m_filename+=XLB_GetItemText1(list,item);
  274. #ifndef _WIN32_WCE
  275.     // strip leading  
  276.     if (m_filename.GetLength()>0 && m_filename[0]==_T('\'))
  277.       m_filename.Delete(0);
  278. #endif
  279.     if (!m_zip.get() && m_filename.GetLength()>4 &&
  280. !m_filename.Right(4).CompareNoCase(_T(".zip")))
  281.     {
  282.       OpenItem(m_filename);
  283.     } else {
  284.       if (m_zip.get())
  285. m_path=m_vpath;
  286.       EndDialog(IDOK);
  287.     }
  288.   }
  289. }
  290. void CFileOpenDialog::OnSize(UINT nType, int cx, int cy) 
  291. {
  292.   CDialog::OnSize(nType, cx, cy);
  293.   RECT   r,rc;
  294.   GetClientRect(&r);
  295.   rc=r;
  296.   rc.bottom=rc.top+HIWORD(GetDialogBaseUnits())+5;
  297.   --rc.left; --rc.top; ++rc.right;
  298.   CWnd *ctl=GetDlgItem(IDC_FILEPATH);
  299.   if (ctl)
  300.     ctl->MoveWindow(&rc);
  301.   CWnd *list=GetDlgItem(IDC_FILELIST);
  302.   if (list) {
  303.     rc=r;
  304.     rc.top+=HIWORD(GetDialogBaseUnits())+5;
  305.     list->MoveWindow(&rc);
  306.     XLB_EnsureVisible(list->m_hWnd,XLB_GetSelection(list->m_hWnd));
  307.   }
  308. }
  309. void CFileOpenDialog::OnOK() {
  310.   HWND   list=::GetDlgItem(m_hWnd,IDC_FILELIST);
  311.   int   item=XLB_GetSelection(list);
  312.   if (item>=0)
  313.     ActivateItem(list,item);
  314. }
  315. void CFileOpenDialog::OpenItem(const CString &path) { // looks like a zip file
  316.   CFile       *fp=new CFile;
  317.   CFileException  ex;
  318.   if (!fp->Open(path,CFile::modeRead|CFile::shareDenyWrite,&ex)) {
  319.     MessageBox(_T("Can't open zip file"),_T("Error"),MB_OK|MB_ICONERROR);
  320.     delete fp;
  321.   } else {
  322.     m_zip=new ZipFile(path);
  323.     if (!m_zip->ReadZip()) {
  324.       MessageBox(_T("Invalid or unsupported ZIP file"),_T("Error"),MB_OK|MB_ICONERROR);
  325.       m_zip.reset(0);
  326.     } else {
  327.       CString tmp;
  328.       if (m_zip->IsSingleFile(&tmp)) {
  329. m_filename=path+_T("\")+tmp;
  330. EndDialog(IDOK);
  331.       } else {
  332. m_vpath=m_path;
  333. m_path=m_filename=path;
  334. FindFiles();
  335.       }
  336.     }
  337.   }
  338. }