自定义文件读写(打开、保存)对话框样式

    技术2022-05-19  21

    在我告诉大家怎么样修改MFC浏览程序中文件读写对话框的缺省设置之前呢,我们应该先知道MFC是怎么样显示 文件打开和文件保存对话框的。如果你选择了文件菜单中的打开,那么就会有一个消息发送给CWinApp::OnFileOpen,通过一个成员变量 m_pDocManager(一个指向CDocManager 对象的指针)来调用CDocManager::OnFileOpen,那么函数就会调用CDocManager的虚函数 DoPromptFileName,成功后再调用CWinApp::OpenDocumentFile函数,这个文件对话框就是在 DoPromptFileName的虚函数中显示的。当我们打开的是保存对话框时,文件保存(或另存为)命令消息就会发给CDocument:: OnFileSave (or CDocument::OnFileSaveAs),在这2种情况下,CDocument::DoSave函数都会被调用。最后,如果文件名是空的,那么 CDocument::DoSave就会调用CWinApp::DoPromptFileName,使得成员变量m_pDocManager有效,并且调 用CDocManager::DoPromptFileName来显示保存对话框。

      那么现在大家都明白了,CDocManager::DoPromptFileName函数(注意它是一个虚函数)就是负责显示标准的文件打开和保存对话框的(可是有一个BOOL变量来决定显示哪一个对话框的)。

      现在看起来,这好象对改变默认的对话框设置没什么用。你可能也没有考虑过在类CDocManager中的DoPromptFileName函 数,或者不知道怎么改,来使用你自己的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函数是从DoPromptFileName中被调用的,原 代码可以从你的工程中获得。如果你想显示打开和保存对话框,你可以使用bOpenFileDialog参数,TRUE表示对话框是打开对话框,反之,亦 然。

     

    当然我们也可以使用我们自己定义的CDocManagerEx类来代替原来的CDocManager类, CWinApp是通过成员变量m_pDocManager来使用文档管理器,所以我们必须正确的初始化这个变量。有必要特别关注一下在CWinApp:: AddDocTemplate中CWinApp创建对象的原代码,这其中有一个很普通的函数调用,我们把它给忽略了,那就是CWinApp:: InitInstance函数。当m_pDocManager参数是NULL的时候,CWinApp::AddDocTemplate函数只是创建 CDocManager对象,那么一旦m_pDocManager指针被正确的初始化,CWinApp::AddDocTemplate函数也就能够被正 确的调用了。因此,这最后一步就是在调用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; } 


    最新回复(0)