在我告訴大家怎么樣修改MFC瀏覽程序中文件讀寫對話框的缺省設置之前呢,我們應該先知道MFC是怎么樣顯示文件打開和文件保存對話框的。如果你選擇了文件菜單中的打開,那么就會有一個消息發(fā)送給CWinApp::OnFileOpen,通過一個成員變量m_pDocManager(一個指向CDocManager 對象的指針)來調用CDocManager::OnFileOpen,那么函數(shù)就會調用CDocManager的虛函數(shù)DoPromptFileName,成功后再調用CWinApp::OpenDocumentFile函數(shù),這個文件對話框就是在DoPromptFileName的虛函數(shù)中顯示的。當我們打開的是保存對話框時,文件保存(或另存為)命令消息就會發(fā)給CDocument::OnFileSave (or CDocument::OnFileSaveAs),在這2種情況下,CDocument::DoSave函數(shù)都會被調用。最后,如果文件名是空的,那么CDocument::DoSave就會調用CWinApp::DoPromptFileName,使得成員變量m_pDocManager有效,并且調用CDocManager::DoPromptFileName來顯示保存對話框。
那么現(xiàn)在大家都明白了,CDocManager::DoPromptFileName函數(shù)(注意它是一個虛函數(shù))就是負責顯示標準的文件打開和保存對話框的(可是有一個BOOL變量來決定顯示哪一個對話框的)。
現(xiàn)在看起來,這好象對改變默認的對話框設置沒什么用。你可能也沒有考慮過在類CDocManager中的DoPromptFileName函數(shù),或者不知道怎么改,來使用你自己的CDocManager類。那么你不用急,下面的代碼就是告訴你怎么自定義CDocManager。
// CDocManager class declaration
//
class CDocManagerEx : public CDocManager
{
DECLARE_DYNAMIC(CDocManagerEx)
// Construction
public:
CDocManagerEx();
// Attributes
public:
// Operations
public:
// Overrides
// helper for standard commdlg dialogs
virtual BOOL DoPromptFileName(CString& fileName, UINT nIDSTitle,
DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate);
// Implementation
public:
virtual ~CDocManagerEx();
};
// DocManager.cpp : implementation file
//
#include "stdafx.h"
#include "PreviewFileDlg.h"
#include "DocManager.h" // the header with the class declaration
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static void AppendFilterSuffix(CString& filter, OPENFILENAME& ofn,
CDocTemplate* pTemplate, CString* pstrDefaultExt)
{
ASSERT_VALID(pTemplate);
ASSERT_KINDOF(CDocTemplate, pTemplate);
CString strFilterExt, strFilterName;
if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) &&
!strFilterExt.IsEmpty() &&
pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
!strFilterName.IsEmpty())
{
// a file based document template - add to filter list
#ifndef _MAC
ASSERT(strFilterExt[0] == '.');
#endif
if (pstrDefaultExt != NULL)
{
// set the default extension
#ifndef _MAC
*pstrDefaultExt = ((LPCTSTR)strFilterExt) 1; // skip the '.'
#else
*pstrDefaultExt = strFilterExt;
#endif
ofn.lpstrDefExt = (LPTSTR)(LPCTSTR)(*pstrDefaultExt);
ofn.nFilterIndex = ofn.nMaxCustFilter 1; // 1 based number
}
// add to filter
filter = strFilterName;
ASSERT(!filter.IsEmpty()); // must have a file type name
filter = (TCHAR)'\0'; // next string please
#ifndef _MAC
filter = (TCHAR)'*';
#endif
filter = strFilterExt;
filter = (TCHAR)'\0'; // next string please
ofn.nMaxCustFilter ;
}
}
/////////////////////////////////////////////////////////////////////////////
// CDocManagerEx
IMPLEMENT_DYNAMIC(CDocManagerEx, CDocManager)
CDocManagerEx::CDocManagerEx()
{
}
CDocManagerEx::~CDocManagerEx()
{
}
BOOL CDocManagerEx::DoPromptFileName(CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate)
{
CPreviewFileDlg dlgFile(bOpenFileDialog); // this is the only modified line!
CString title;
VERIFY(title.LoadString(nIDSTitle));
dlgFile.m_ofn.Flags |= lFlags;
CString strFilter;
CString strDefault;
if (pTemplate != NULL)
{
ASSERT_VALID(pTemplate);
AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, &strDefault);
}
else
{
// do for all doc template
POSITION pos = m_templateList.GetHeadPosition();
BOOL bFirst = TRUE;
while (pos != NULL)
{
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate,
bFirst ? &strDefault : NULL);
bFirst = FALSE;
}
}
// append the "*.*" all files filter
CString allFilter;
VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
strFilter = allFilter;
strFilter = (TCHAR)'\0'; // next string please
#ifndef _MAC
strFilter = _T("*.*");
#else
strFilter = _T("****");
#endif
strFilter = (TCHAR)'\0'; // last string
dlgFile.m_ofn.nMaxCustFilter ;
dlgFile.m_ofn.lpstrFilter = strFilter;
#ifndef _MAC
dlgFile.m_ofn.lpstrTitle = title;
#else
dlgFile.m_ofn.lpstrPrompt = title;
#endif
dlgFile.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH);
BOOL bResult = dlgFile.DoModal() == IDOK ? TRUE : FALSE;
fileName.ReleaseBuffer();
return bResult;
}
以上代碼是從MFC原代碼中完整的拷貝過來的,當中只有一行需要改:對話框的聲明(當然,由于這是CFileDialog的子類,你可以有更多的修改權),而且對于標準對話框來說,還應該有預覽功能。AppendFilterSuffix函數(shù)是從DoPromptFileName中被調用的,原代碼可以從你的工程中獲得。如果你想顯示打開和保存對話框,你可以使用bOpenFileDialog參數(shù),TRUE表示對話框是打開對話框,反之,亦然。
當然我們也可以使用我們自己定義的CDocManagerEx類來代替原來的CDocManager類,CWinApp是通過成員變量m_pDocManager來使用文檔管理器,所以我們必須正確的初始化這個變量。有必要特別關注一下在CWinApp::AddDocTemplate中CWinApp創(chuàng)建對象的原代碼,這其中有一個很普通的函數(shù)調用,我們把它給忽略了,那就是CWinApp::InitInstance函數(shù)。當m_pDocManager參數(shù)是NULL的時候,CWinApp::AddDocTemplate函數(shù)只是創(chuàng)建CDocManager對象,那么一旦m_pDocManager指針被正確的初始化,CWinApp::AddDocTemplate函數(shù)也就能夠被正確的調用了。因此,這最后一步就是在調用CWinApp::AddDocTemplate之前就初始化成員變量m_pDocManager,以達到我們想要的樣子。(當然你也不一定得調用CWinApp::AddDocTemplate,而是直接調用m_pDocManager->AddDocTemplate也行)
以下就是代碼:
BOOL COurApp::InitInstance()
{
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// Change the registry key under which our settings are stored.
// You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_DIBTYPE,
RUNTIME_CLASS(COurDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(COurView));
ASSERT(m_pDocManager == NULL);
m_pDocManager = new CDocManagerEx;
m_pDocManager->AddDocTemplate(pDocTemplate); // or just AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The main window has been initialized, so show and update it.
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
from: http://www.quickviews.net/data/2006/0421/article_16587_1.htm