`
love19820823
  • 浏览: 934680 次
文章分类
社区版块
存档分类
最新评论

WTL文件选择对话框 - CFileDialogImpl

 
阅读更多

WTL文件选择对话框 - CFileDialogImpl

1)首先下面的代码是直接使用Win32 API来打开单个文件的代码:

void WinSDK_OpenFileDemo()
{
OPENFILENAME ofn = {0};
char szFile[MAX_PATH];
*szFile = 0;

// 开始设置OPENFILENAME结构成员
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDlg;
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = "ESRI Shape文件(*.SHP)/0*.shp/0AutoCAD交换文件(*.DXF;*.DXF.GZ)/0*.dxf;*.dxf.gz /0所有图像文件/0*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tif;*.tiff/0所有文件(*.*)/0*.*/0/0";

ofn.nFilterIndex = 1;
ofn.lpstrTitle = "打开地图文件";
ofn.lpstrInitialDir = 0;

ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;

// 指派给"打开"对话框, 并显示对话框
if (::GetOpenFileName(&ofn))
{

// 现在下面的成员中存放了我们要的文件名
// ofn.lpstrFile;
}
}

2)类似的用WTL来实现文件打开的功能就简单多了。下面的代码同时打开多个文件:


LRESULT CMainFrame::OnFileOpen(...)
{
CMyFileDialog openFileDlg( TRUE,
_T("shp"),
_T(""),
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT,
_T("Shape 文件(*.shp)|*.shp|CAD交换文件(*.dxf)|*.dxf|图像文件|*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tif;*.tiff|所有文件(*.*)|*.*|"),
this->m_hWnd,
_T("打开地图文件")
);

if ( IDOK == openFileDlg.DoModal() )
{
int nOpenFiles = openFileDlg.GetOpenFileCount();

if (nOpenFiles>0)
{
for (int i=0; i<nOpenFiles; i++)
{
//文件名:openFileDlg.GetOpenFileAt(i);
}
}
}

return 0;
}

3)完整的CMyFileDialog的代码如下(在WTL8.0, 8.1测试通过):


class CMyFileDialog :
public CFileDialogImpl<CMyFileDialog>
{
public:
// Construction
CMyFileDialog (BOOL bOpenFileDialog,
_U_STRINGorID szDefExt = 0U,
_U_STRINGorID szFileName = 0U,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_U_STRINGorID szFilter = 0U,
HWND hwndParent = NULL,
_U_STRINGorID szTitle= 0U ) :
CFileDialogImpl<CMyFileDialog>(bOpenFileDialog, NULL, NULL, dwFlags, NULL, hwndParent),
m_sDefExt(szDefExt.m_lpstr),
m_sFileName(szFileName.m_lpstr),
m_sFilter(szFilter.m_lpstr),
m_sTitle(szTitle.m_lpstr),
_FilesCount(-1)
{
m_ofn.lpstrDefExt = m_sDefExt;
m_ofn.lpstrFilter = PrepFilterString ( m_sFilter );
m_ofn.lpstrTitle = m_sTitle;

// setup initial file name
if ( !m_sFileName.IsEmpty() )
lstrcpyn ( m_szFileName, m_sFileName, _MAX_PATH );
}

// Maps
BEGIN_MSG_MAP(CMyFileDialog)
CHAIN_MSG_MAP(CFileDialogImpl<CMyFileDialog>)
END_MSG_MAP()

// Overrides
void OnInitDone ( LPOFNOTIFY lpon )
{
GetFileDialogWindow().CenterWindow(lpon->lpOFN->hwndOwner);
}

// Get Open Files Count
int GetOpenFileCount(void)
{
if (!m_bOpenFileDialog)
return 0;

if (_FilesCount==-1)
{
int i = 0;
int i0 = 0;
_FilesCount = 0;

while(i < _MAX_PATH-1){
if (m_szFileName[i]==0){
_FileStarts[_FilesCount++] = i0;
i0 = i+1;

if (m_szFileName[i+1]==0)
break;
}
i++;
}

if (_FilesCount>1){
_tcsncpy_s(_FileName, _MAX_PATH, m_szFileName, _FileStarts[1]);
_FileName[ _FileStarts[1] ] = 0;
_FileName[ _FileStarts[1]-1 ] = _T('//');
_FilesCount--;
}
}

return _FilesCount;
}

// Get Open FileName: index 0-based
LPCTSTR GetOpenFileAt(int index)
{
ATLASSERT(_FilesCount > 0);

if (_FilesCount==1){
ATLASSERT(index==0);
return m_szFileName;
}

_FileName[ _FileStarts[1] ] = 0;
_tcscat_s(_FileName, _MAX_PATH, m_szFileName + _FileStarts[index+1]);

return _FileName;
}

protected:
LPCTSTR PrepFilterString ( CString& sFilter )
{
LPTSTR psz = sFilter.GetBuffer(0);
LPCTSTR pszRet = psz;

while ( '/0' != *psz )
{
if ( '|' == *psz )
*psz++ = '/0';
else
psz = CharNext ( psz );
}

return pszRet;
}

int _FilesCount;
int _FileStarts[_MAX_PATH];
TCHAR _FileName[_MAX_PATH];

CString m_sDefExt, m_sFileName, m_sFilter, m_sTitle;
};

4)结论

编写windows客户端界面程序有不少于100种方法可用。经典的如MFC;时髦的如DHTML,Form,WPF;纯理论的如SDK;跨平台的如Java(这里面就有N多框架),QT等等。可是至今我觉得还是WTL/ATL最干净利落,也最强大。尤其WTL,虽然不是MS力推的主流,但这主要是因为MS为了.NET平台推广而有意压制的技术。WTL也是最适合我们玩的东西。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics