1. 程式人生 > >MfC開啟過程詳解及應用

MfC開啟過程詳解及應用

本文主要介紹:在MFC中,選單開啟命令的響應過程。

一、MFC開啟命令的響應過程:

File->Open 對應的ID為ID_FILE_OPEN,其響應過程如下:

注:如果自己已將ID_FLIE_OPEN在MFC中過載了,則會直接響應過載函式,不會按以下過程響應。

1.點選File->Open,首先響應的函式為: CWinApp::OnFileOpen(),其函式原型為:

void CWinApp::OnFileOpen()
{
	ASSERT(m_pDocManager != NULL);
        m_pDocManager->OnFileOpen();
}

2.由上面的程式可知,接著呼叫的是: CDocManager::onFileOpen()

,該函式功能是:顯示開啟檔案的對話方塊,並獲取檔案的路徑,其函式原型為:

void CDocManager::OnFileOpen()
{
       // prompt the user (with all document templates)
	CString newName;  //彈出開啟檔案的對話方塊,獲取檔案路徑
    if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
		return; // open cancelled
    AfxGetApp()->OpenDocumentFile(newName);
      // if returns NULL, the user has already been alerted
}

3.接著呼叫函式: CWinApp::OpenDocumentFile(LPCTSTR lpszFileName),其函式原型為:
CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)
{
    ASSERT(m_pDocManager != NULL);
    return m_pDocManager->OpenDocumentFile(lpszFileName);
}

4.再呼叫函式: CDocManager::OpenDocumentFile(LPCTSTR lpszFileName),該函式遍歷文件模板,對每個文件進行匹配,若該檔案已經在某個文件中開啟,則會啟用該文件檢視,否則用匹配的文件模板,呼叫下一個開啟函式,其原型為:

CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)
{
       // find the highest confidence
    POSITION pos = m_templateList.GetHeadPosition();
    CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;
    CDocTemplate* pBestTemplate = NULL;
    CDocument* pOpenDocument = NULL;
       lstrcpyn(szTemp, lpszFileName, _MAX_PATH);
       LPTSTR lpszLast = _tcsrchr(szTemp, '"');

       if (lpszLast != NULL)
              *lpszLast = 0;
			  
       AfxFullPath(szPath, szTemp);
       TCHAR szLinkName[_MAX_PATH];
	   
       if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))
              lstrcpy(szPath, szLinkName);

       while (pos != NULL)
       {
              CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
              ASSERT_KINDOF(CDocTemplate, pTemplate);

              CDocTemplate::Confidence match;
              ASSERT(pOpenDocument == NULL);

              match = pTemplate->MatchDocType(szPath, pOpenDocument);
              if (match > bestMatch)
              {
                     bestMatch = match;
                     pBestTemplate = pTemplate;
              }

              if (match == CDocTemplate::yesAlreadyOpen)
                     break;      // stop here
       }
       if (pOpenDocument != NULL)
       {
              POSITION pos = pOpenDocument->GetFirstViewPosition();
              if (pos != NULL)
              {
                     CView* pView = pOpenDocument->GetNextView(pos); // get first one
                     ASSERT_VALID(pView);
                     CFrameWnd* pFrame = pView->GetParentFrame();
                     if (pFrame != NULL)
                            pFrame->ActivateFrame();
                     else
                            TRACE0("Error: Can not find a frame for document to activate.\n");

                     CFrameWnd* pAppFrame;
                     if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))
                     {
                            ASSERT_KINDOF(CFrameWnd, pAppFrame);
                            pAppFrame->ActivateFrame();
                     }
              }
              else
              {
                     TRACE0("Error: Can not find a view for document to activate.\n");
              }
              return pOpenDocument;
       }
       if (pBestTemplate == NULL)
       {
              AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);
              return NULL;
       }
       return pBestTemplate->OpenDocumentFile(szPath);
}
5.呼叫函式:CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible),該函式是多文件開啟函式,先建立文件的框架視窗,然後判斷路徑是否為空,如果為空,則重新設定文件路徑;最後,呼叫InitialUpdateFrame顯示框架視窗。其原型為:
CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible)
{
       CDocument* pDocument = CreateNewDocument();
       if (pDocument == NULL)
       {
              TRACE0("CDocTemplate::CreateNewDocument returned NULL.\n");
              AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
              return NULL;
       }

       ASSERT_VALID(pDocument);

       BOOL bAutoDelete = pDocument->m_bAutoDelete;
       pDocument->m_bAutoDelete = FALSE;   // don't destroy if something goes wrong
       CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);
       pDocument->m_bAutoDelete = bAutoDelete;
       if (pFrame == NULL)
       {
              AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
              delete pDocument;       // explicit delete on error
              return NULL;
       }

       ASSERT_VALID(pFrame);

       if (lpszPathName == NULL)
       {
              // create a new document - with default document name
              SetDefaultTitle(pDocument);

              // avoid creating temporary compound file when starting up invisible
              if (!bMakeVisible)
                     pDocument->m_bEmbedded = TRUE;

              if (!pDocument->OnNewDocument())
              {
                     // user has be alerted to what failed in OnNewDocument
                     TRACE0("CDocument::OnNewDocument returned FALSE.\n");
                     pFrame->DestroyWindow();
                     return NULL;
              }

              // it worked, now bump untitled count
              m_nUntitledCount++;
       }
       else
       {
              // open an existing document
              CWaitCursor wait;
              if (!pDocument->OnOpenDocument(lpszPathName))
              {
                     // user has be alerted to what failed in OnOpenDocument
                     TRACE0("CDocument::OnOpenDocument returned FALSE.\n");
                     pFrame->DestroyWindow();
                     return NULL;
              }
              pDocument->SetPathName(lpszPathName);
       }

       InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
       return pDocument;
}
6.最後呼叫函式:CDocument::OnOpenDocument(LPCTSTR lpszPathName),該函式一般在“***Doc.cpp”中過載(*** 為工程名),因為不同的檔案開啟的過程不同,所以可以根據需求,在“***Doc.cpp”中改寫OnOpenDocument(LPCTSTR lpszPathName)函式,從而開啟相應的檔案。其預設生成原型為:
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)
{

       if (IsModified())
              TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");

       CFileException fe;
       CFile* pFile = GetFile(lpszPathName,CFile::modeRead|CFile::shareDenyWrite, &fe);

       if (pFile == NULL)
       {
              ReportSaveLoadException(lpszPathName, &fe,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
              return FALSE;
       }

       DeleteContents();
       SetModifiedFlag();  // dirty during de-serialize

       CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete);
       loadArchive.m_pDocument = this;
       loadArchive.m_bForceFlat = FALSE;

       TRY
       {
              CWaitCursor wait;
              if (pFile->GetLength() != 0)
                     Serialize(loadArchive);     // load me
              loadArchive.Close();
              ReleaseFile(pFile, FALSE);
       }
       CATCH_ALL(e)
       {
              ReleaseFile(pFile, TRUE);
              DeleteContents();   // remove failed contents
 
              TRY
              {
                     ReportSaveLoadException(lpszPathName, e,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
              }
              END_TRY
              DELETE_EXCEPTION(e);
              return FALSE;
       }
       END_CATCH_ALL
       SetModifiedFlag(FALSE);     // start off with unmodified
       return TRUE;
}
二、總結

通過上述介紹,MFC開啟命令的響應過程如下:

         1.首先呼叫CWinApp::OnFileOpen(),該函式呼叫CDocManager::OnFileOpen()函式;

         2.CDocManager::OnFileOpen()顯示開啟檔案的對話方塊,並獲取檔案的路徑,然後該函式呼叫CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)函式;

         3.CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)函式直接呼叫CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)函式;

         4.CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)函式遍歷文件模板,對每個文件進行匹配,若該檔案已經在某個文件中開啟,則會啟用該文件檢視,否則用匹配的文件模板,呼叫CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible)函式;

         5.CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible)函式先建立文件的框架視窗,然後判斷路徑是否為空,如果為空,則重新設定文件路徑;接著,呼叫InitialUpdateFrame顯示框架視窗,最後呼叫CDocument::OnOpenDocument(LPCTSTR lpszPathName)函式;

         6.CDocument::OnOpenDocument(LPCTSTR lpszPathName)函式一般在“***Doc.cpp”中過載(*** 為工程名),因為不同的檔案開啟的過程不同,所以可以根據需求,在“***Doc.cpp”中改寫OnOpenDocument(LPCTSTR lpszPathName)函式,從而開啟相應的檔案。

三、運用

由於開啟命令的響應過程,是一系列函式依次呼叫,因此,可以呼叫其中的一個環節,來開啟檔案。以開啟圖片為例,介紹一下應用:

在開啟檔案時,彈出的對話方塊預設的檔案“所有檔案(*.*)”,如下圖:


有時候我們需要開啟特定的檔案型別,如BMP、Jpg、Tif等型別,即需要彈出下面的對話方塊:


該功能實現的過程如下:(***代表工程名)

1.在“***.cpp”中過載ID_FILE_OPEN的響應函式OnFileOpen() ,即對ID_FILE_OPEN在C***App的類中新增一個響應函式,函式名為OnFileOpen();

注:如果ID_FILE_OPEN已經過載為:ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen),要把這行程式碼遮蔽,不然點選開啟時,仍預設原來的響應,不會響應自己新過載的函式。

2.編寫C***App::OnFileOpen()函式:

void CMyIMGApp::OnFileOpen() 
{
	// TODO: Add your command handler code here
	CString strOpenFilter = "所有檔案(*.*)|*.bmp; *.dib; *.gif; *.jpg; *.jpe; *.jpeg; *.tif; *.tiff; *.raw|點陣圖檔案 (*.bmp;*.dib)|*.bmp; *.dib|GIF檔案 (*.gif)|*.gif|JPEG檔案 (*.jpg;*.jpe;*.jpeg)|*.jpg; *.jpe; *.jpeg|TIFF檔案 (*.tif;*.tiff)|*.tif; *.tiff|RAW檔案(*.raw)|*.raw|";
	CFileDialog FileDlg(TRUE, "*.bmp", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strOpenFilter);
	if (FileDlg.DoModal() == IDOK)
		OpenDocumentFile(FileDlg.m_ofn.lpstrFile);
}
該函式是直接呼叫了上述環節的CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)函式,從而實現檔案的開啟。

說明:點選開啟選單時,直接的響應函式是自己過載後的函式,通過過載只是改變了前兩個環節,最後通過呼叫OpenDocumentFile(LPCTSTR lpszFileName)函式,使後面函式依次被呼叫。

相關推薦

MfC開啟過程應用

本文主要介紹:在MFC中,選單開啟命令的響應過程。 一、MFC開啟命令的響應過程: File->Open 對應的ID為ID_FILE_OPEN,其響應過程如下: 注:如果自己已將ID_FLIE_OPEN在MFC中過載了,則會直接響應過載函式,不會按以下過程響應。 1.

Hibernate Session開啟方式應用

session 1、crud操作是由session完成的 2、與資料庫的連線是由session開啟的 3、物件的狀態和一級快取與session緊密相關 4、資料安全性的問題 開啟session的方式 openSession

SQL update select結合語句應用

應用 comm 執行 sel ron 詳解 strong 閱讀 等於 SQL update select結合語句詳解及應用 2013年10月1日 MK 數據庫 19 閱讀 157639次 QL update select語句 最常用的update語法是: 1 2

跨鏈技術之ILP應用

區塊鏈;跨鏈;托管;ilp;rippleAbstract:As the booming of BlockChain technology, the requirement of asset transfer between different ledgers is as imperative as possi

IO模型應用

邊緣 會有 通知機制 子進程 sele lex ons 中一 消息通知 如何閱讀這篇文章順序 1.1:了解同步異步和阻塞非阻塞 1.11: 同步異步 1.12:阻塞非阻塞 1.2:了解一次read操作需要的步驟 1.3:五種模型 1.1:I/O模

JavaWeb中filter的應用案例

轉載自:http://www.cnblogs.com/vanl/p/5742501.html 一:Filter介紹   Filter可認為是Servlet的一種“變種”,它主要用於對使用者請求(HttpServletRequest)進行預處理,也可以對伺服器響應(HttpServl

PCA SVD原理應用

本文分為兩大部分即PCA和SVD,每一部分下又分為原理和應用兩小部分 說明:本文程式碼參考Peter Harrington編寫的Machine Learning in Action,感興趣的小夥伴可以去看一下,筆者認為這本書還不錯 注意:本篇重在說明公式推導,關於具體使用的話python有專

WebSocket協議應用

https://blog.csdn.net/u014520745/article/details/52639452   WebSocket協議詳解及應用(一)-初識WebSocket 一、什麼是WebSocket WebSocket是一個允許Web應用程式(通常指瀏覽器)與

Oracle中的substr()函式 應用

1)substr函式格式   (俗稱:字元擷取函式)   格式1: substr(string string, int a, int b);   格式2:substr(string string, int a) ; 解釋:     格式1:  

一看就懂,Python 日誌模組應用

日誌概述 百度百科的日誌概述: Windows網路作業系統都設計有各種各樣的日誌檔案,如應用程式日誌,安全日誌、系統日誌、Scheduler服務日誌、FTP日誌、WWW日誌、DNS伺服器日誌等等,這些根據你的系統開啟的服務的不同而有所不同。我們在系統上進行一些操作時,這些日誌檔案通常會記錄下我們操作的一些

大資料技術學習筆記之Hadoop框架基礎4-MapReduceshuffer過程zookeeper框架學習

一、MapReduce Shuffle     -》MapReduce執行五個階段         input           

大資料系列之——hive(七、hive應用

目錄 2.HQL 一、HIVE概述 1.Hadoop分散式計算遇到的問題 MapReduce只能用java開發(也支援其他語言,但是不是主流)需要對Hadoop的底層原理 api比較瞭解才能順暢的開發出分散式的處

[tensorflow 應用之路]Batch Normalization 原理應用方法

批正則化(Batch Normalize,BN)是2015年由Sergey Ioffe提出的方法,用於消除神經網路上一層不同分佈的輸入導致本層引數更新困難。由於各個層的卷積核引數不同,根據反向傳播法則我們知道,∣∣W∣∣||W||∣∣W∣∣及結果∣∣h∣∣||h

構建負載均衡伺服器之二 LVS應用

在上一篇中介紹了負載均衡及叢集的原理,本篇主要介紹下下實現負載均衡的軟體之LVS的原理及應用。 一、LVS的介紹 1、  LVS的定義 一般來說,LVS採用三層結構:負載排程器、伺服器池、共享儲存。工作在TCP/IP協議的四層,其轉發是依賴於四層協議的特徵進行轉發的,由於其轉發要依賴於協議的特徵進行轉

Oracle中的substr()函數 應用

arch rep ont string類 tco -c where int mco 註:本文來源於《Oracle中的substr()函數 詳解及應用》1)substr函數格式 (俗稱:字符截取函數)   格式1: substr(string string, int a

HDMI ARC功能應用介紹

http://www.icpcw.com/Parts/Peripheral/Skill/3260/326044_2.htm 【電腦報線上】很多使用者和讀者購買了電視以後,都發現自己電視的HDMI介面上經常標準了一些字眼,比如有的寫著MHL,有的寫著ARC……MHL我們都知道是手機專屬的視訊輸出介面標準,

BPR [Bayesian Personalized Ranking] 演算法應用實踐

在推薦系統的實現中,幾乎總會遇到從較多候選集中為使用者選取特定的少數幾個物品進行推薦,這本質上是一個Ranking問題。 在推薦場景中使用者更缺乏耐性,對推薦結果的消費也十分有限。因此,排序的好壞直接決定了使用者對一個準確率為90%的推薦候選集的滿意度是否真的有90%

JAVA多執行緒 join() 方法應用場景

在某些情況下,主執行緒建立並啟動了子執行緒,如果子執行緒中需要進行大量的耗時運算,主執行緒往往將早於子執行緒結束之前結束,如果主執行緒想等待子執行緒執行完畢後,獲得子執行緒中的處理完的某個資料,就要用

推薦系統基礎演算法--餘弦相似度演算法應用

一、簡述        這幾天在看《推薦系統實戰》這本書。其中,基於領域的演算法是推薦系統中最基本的演算法,什麼是基於領域的演算法呢?簡單來說就是基於使用者(或物品)的協同過濾演算法,所謂的協同的意思就是需要使用者(或物品)共同參與。從而通過使用者的行為,

Oracle列轉行函式 Listagg() 語法應用例項

工作中用到一段比較複雜的SQL查詢指令碼,使用了listagg()函式實現了具有多個值的欄位的填充(即,列表聚合,list aggregation(我猜的))。說簡單點,listagg()函式可以實現多列記錄聚合為一條記錄,從而實現資料的壓縮、緻密化(data densifi