如何用CFileDialog产生新式的有我的电脑\我的文档等的对话框,像Winamp那样

escout 2003-07-07 12:20:02
我的代码如下,
CString str;
str.LoadString(IDS_SUPPORTED_FILES);
CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY
|OFN_ALLOWMULTISELECT|OFN_EXPLORER,
str,pWnd);
if(dlg.DoModal()==IDOK)
{
POSITION pos=dlg.GetStartPosition();
while(pos!=NULL)
{
CString str=dlg.GetNextPathName(pos);
OpenFile(str,FALSE);
}
}

但是产生的还是老样子的对话框.
如果不用CFileDialog,而用API我知道怎么作.问题是用了MFC,我也添加了OFN_EXPLORER(这个是mfc默认的),但是还是那个对话框,好难看.
...全文
88 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
wuwind 2003-07-07
  • 打赏
  • 举报
回复
http://www.vckbase.com/document/viewdoc.asp?id=578
escout 2003-07-07
  • 打赏
  • 举报
回复
但是我添加了下面这一句,可以出现新的界面了,但是会出现debug assertion.
CString str;
str.LoadString(IDS_SUPPORTED_FILES);
CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY
|OFN_ALLOWMULTISELECT|OFN_EXPLORER,
str,pWnd);
/////////////////////////////////////////////////
dlg.m_ofn.Flags=OFN_FILEMUSTEXIST|
OFN_EXPLORER|
OFN_ALLOWMULTISELECT |
//OFN_ENABLEHOOK|
OFN_HIDEREADONLY;

if(dlg.DoModal()==IDOK)
{
POSITION pos=dlg.GetStartPosition();
while(pos!=NULL)
{
CString str=dlg.GetNextPathName(pos);
OpenFile(str,FALSE);
}
}
我用debug发现是没有OFN_ENABLEHOOK标志,但是添加上了后,assert虽然没了,新的界面也换成就得了。
escout 2003-07-07
  • 打赏
  • 举报
回复
我上csdn上查了很久,虽然有很多CFileDialog的问题,但没有这个问题的答案,上codeguru上也没有找到.我个人也尝试了很久,都不行.
guoxiny 2003-07-07
  • 打赏
  • 举报
回复
That is OK.
escout 2003-07-07
  • 打赏
  • 举报
回复
http://msdn.microsoft.com/msdnmag/issues/0800/c/default.aspx
msdn上的解决方案,还是派生了一个CFileDialogEx类,不过上面有完整的代码.
下面我贴出来.
头文件FileDialogEx.h
////////////////////////////////////////////////////////////////
// MSDN -- August 2000
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably NT too.
//
#pragma once

// Windows 2000 version of OPENFILENAME.
// The new version has three extra members.
// This is copied from commdlg.h
//
struct OPENFILENAMEEX : public OPENFILENAME {
void * pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
};

/////////////////////////////////////////////////////////////////////////////
// CFileDialogEx: Encapsulate Windows-2000 style open dialog.
//
class CFileDialogEx : public CFileDialog {
DECLARE_DYNAMIC(CFileDialogEx)
public:
CFileDialogEx(BOOL bOpenFileDialog, // TRUE for open, FALSE for FileSaveAs
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL,
CWnd* pParentWnd = NULL);

// override
virtual int DoModal();

protected:
OPENFILENAMEEX m_ofnEx; // new Windows 2000 version of OPENFILENAME

virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);

// virtual fns that handle various notifications
virtual BOOL OnFileNameOK();
virtual void OnInitDone();
virtual void OnFileNameChange();
virtual void OnFolderChange();
virtual void OnTypeChange();

DECLARE_MESSAGE_MAP()
//{{AFX_MSG(CFileDialogEx)
//}}AFX_MSG
};
实现文件FileDialogEx.cpp:
////////////////////////////////////////////////////////////////
// MSDN -- August 2000
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Largely based on original implementation by Michael POSThttp://expert.csdn.net/Expert/reply.C++ 6.0, runs on Windows 98 and probably NT too.
//
// CFileDialogEx implements a CFileDialog that uses the new Windows
// 2000 style open/save dialog. Use companion class CDocManagerEx in an
// MFC framework app.
//
#include "stdafx.h"
#include <afxpriv.h>
#include "FileDialogEx.h"

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

static BOOL IsWin2000();

IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog)

CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt,
LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName,
dwFlags, lpszFilter, pParentWnd)
{
}


BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog)
//{{AFX_MSG_MAP(CFileDialogEx)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL IsWin2000()
{
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;

// Try calling GetVersionEx using the OSVERSIONINFOEX structure,
// which is supported on Windows 2000.
//
// If that fails, try using the OSVERSIONINFO structure.

ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.

osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return FALSE;
}

switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:

if ( osvi.dwMajorVersion >= 5 )
return TRUE;

break;
}
return FALSE;
}

//////////////////
// DoModal override copied mostly from MFC, with modification to use
// m_ofnEx instead of m_ofn.
//
int CFileDialogEx::DoModal()
{
ASSERT_VALID(this);
ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
ASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook

// zero out the file buffer for consistent parsing later
ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
DWORD nOffset = lstrlen(m_ofn.lpstrFile)+1;
ASSERT(nOffset <= m_ofn.nMaxFile);
memset(m_ofn.lpstrFile+nOffset, 0, (m_ofn.nMaxFile-nOffset)*sizeof(TCHAR));

// WINBUG: This is a special case for the file open/save dialog,
// which sometimes pumps while it is coming up but before it has
// disabled the main window.
HWND hWndFocus = ::GetFocus();
BOOL bEnableParent = FALSE;
m_ofn.hwndOwner = PreModal();
AfxUnhookWindowCreate();
if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner))
{
bEnableParent = TRUE;
::EnableWindow(m_ofn.hwndOwner, FALSE);
}

_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState->m_pAlternateWndInit == NULL);

if (m_ofn.Flags & OFN_EXPLORER)
pThreadState->m_pAlternateWndInit = this;
else
AfxHookWindowCreate(this);

memset(&m_ofnEx, 0, sizeof(m_ofnEx));
memcpy(&m_ofnEx, &m_ofn, sizeof(m_ofn));
if (IsWin2000())
m_ofnEx.lStructSize = sizeof(m_ofnEx);

int nResult;
if (m_bOpenFileDialog)
nResult = ::GetOpenFileName((OPENFILENAME*)&m_ofnEx);
else
nResult = ::GetSaveFileName((OPENFILENAME*)&m_ofnEx);

memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));
m_ofn.lStructSize = sizeof(m_ofn);

if (nResult)
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
pThreadState->m_pAlternateWndInit = NULL;

// WINBUG: Second part of special case for file open/save dialog.
if (bEnableParent)
::EnableWindow(m_ofnEx.hwndOwner, TRUE);
if (::IsWindow(hWndFocus))
::SetFocus(hWndFocus);

PostModal();
return nResult ? nResult : IDCANCEL;
}

//////////////////
// When the open dialog sends a notification, copy m_ofnEx to m_ofn in
// case handler function is expecting updated information in the
// OPENFILENAME struct.
//
BOOL CFileDialogEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));
m_ofn.lStructSize = sizeof(m_ofn);

return CFileDialog::OnNotify( wParam, lParam, pResult);
}

////////////////////////////////////////////////////////////////
// The following functions are provided for testing purposes, to
// demonstrate that they in fact called; ie, that MFC's internal dialog
// proc is hooked up properly. Delete them if you like.
//
BOOL CFileDialogEx::OnFileNameOK()
{
TRACE(_T("CFileDialogEx::OnFileNameOK\n"));
return CFileDialog::OnFileNameOK();
}

void CFileDialogEx::OnInitDone()
{
TRACE(_T("CFileDialogEx::OnInitDone\n"));
CFileDialog::OnInitDone();
}

void CFileDialogEx::OnFileNameChange()
{
TRACE(_T("CFileDialogEx::OnFileNameChange\n"));
CFileDialog::OnFileNameChange();
}

void CFileDialogEx::OnFolderChange()
{
TRACE(_T("CFileDialogEx::OnFolderChange\n"));
CFileDialog::OnFolderChange();
}

void CFileDialogEx::OnTypeChange()
{
TRACE(_T("OnTypeChange(), index = %d\n"), m_ofn.nFilterIndex);
CFileDialog::OnTypeChange();
}
escout 2003-07-07
  • 打赏
  • 举报
回复
刚才查了msdn,看到这样说
When you run your app, you must have the old size when running on Windows 95, Windows 98, or Windows NT® 4.0. On Windows 2000, you can have either the old or new size. If lStructSize is the new size, Windows 2000 runs the new dialog. If it's the old size, Windows examines other information in OPENFILENAME: if the dialog has a hook function (OFN_ENABLEHOOK) or template (OFN_ENABLETEMPLATE), it runs the old dialog; otherwise it runs the new one.
escout 2003-07-07
  • 打赏
  • 举报
回复
98中是可以显示新的式样的对话框的.关键在于标志OFN_ENABLEHOOK,正如 wuwind(风) 上面提到的那篇文章.

CFileDialog f(TRUE);
f.m_ofn.lStructSize = sizeof(f.m_ofn);
f.DoModal();
没有用,还是老对话框.问题是我只要设置了OFN_ENABLEHOOK标志,就可以出来新的对话框,只不过在debug下会出assert,released却没有问题,debug下忽略也可以。所以,我认为应该可以用CFileDialog的。

zwvista 2003-07-07
  • 打赏
  • 举报
回复
typedef struct tagOFN {
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter;
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
LPARAM lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
#if (_WIN32_WINNT >= 0x0500)
void * pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME;
仔细看看新的SDK中OPENFILENAME结构的定义,你就会明白要在mfc程序
产生新式的有我的电脑\我的文档等的对话框,必须满足几个条件:
1) win2K操作系统及以上
2) 定义_WIN32_WINNT 0x0500或以上
在mfc程序的stdafx.h中定义(在所有include之前)
#define _WIN32_WINNT 0x0500
3)必须应用新的sdk,这个可以在微软sdk网站上下载并安装
4)CFileDialog中的m_ofn必须应用新的OPENFILENAME结构
且m_ofn.lStructSize 是 sizeof(OPENFILENAME) 而不是 OPENFILENAME_SIZE_VERSION_400
后者不包括三个附加字段
在vc6上第4点除了写派生类外无法做到,因为无法替换m_ofn的类型
可以在做到第2第3点后尝试写如下程序
CFileDialog f(TRUE);
f.m_ofn.lStructSize = sizeof(f.m_ofn);
f.DoModal();
就可以看到新式对话框,但f析构时会出错
在vc7上只要做到第2点即可,或者干脆去掉_WIN32_WINNT的定义,此时他的缺省值
就是0x0500
换言之,你如果不想用派生类,恐怕就得升到vs.net了
escout 2003-07-07
  • 打赏
  • 举报
回复
我仔细看了,楼上所说文章指出
在一个MFC应用中得到新风格的对话框的唯一的办法是完全绕开CFileDialog,直接调用GetOpenFileName,并且不使用hook过程。我也知道这样可以,但是,我前面已经说了,我只要添加上OFN_ENABLEHOOK标志,就可以出来新的对话框,只不过在debug下会出assert,released却没有问题,debug下忽略也可以。所以,我认为应该可以用CFileDialog的。

我的问题是怎样用CFileDialog实现

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧