MFC文档视图结构框架分析
更新时间:2024-07-05 07:46:01 阅读量: 综合文库 文档下载
- mfc文档类视图类推荐度:
- 相关推荐
MFC文档视图结构框架分析 1:程序的“导火索”---theApp
CmyApp theApp;
在声明对象的同时,调用其构造函数。按C++的语法,首先要调用其基类Cwinapp的构造函数. 这个文件主要用于应用程序的一些初始化操作。
class CWinApp : public CWinThread {
DECLARE_DYNAMIC(CWinApp) public: // Constructor
CWinApp(LPCTSTR lpszAppName = NULL); ???? }
CWinApp::CWinApp(LPCTSTR lpszAppName) {
if (lpszAppName != NULL)
m_pszAppName = _tcsdup(lpszAppName); else
m_pszAppName = NULL; // initialize CWinThread state
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; ASSERT(AfxGetThread() == NULL);
pThreadState->m_pCurrentWinThread = this; ASSERT(AfxGetThread() == this); m_hThread = ::GetCurrentThread(); m_nThreadID = ::GetCurrentThreadId();
// initialize CWinApp state
ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please pModuleState->m_pCurrentWinApp = this; ASSERT(AfxGetApp() == this);
// in non-running state until WinMain m_hInstance = NULL; m_hLangResourceDLL = NULL; m_pszHelpFilePath = NULL; m_pszProfileName = NULL; m_pszRegistryKey = NULL; m_pszExeName = NULL; m_pRecentFileList = NULL; m_pDocManager = NULL;
m_atomApp = m_atomSystemTopic = NULL; m_lpCmdLine = NULL; m_pCmdInfo = NULL;
// initialize wait cursor state m_nWaitCursorCount = 0; m_hcurWaitCursorRestore = NULL; // initialize current printer state m_hDevMode = NULL; m_hDevNames = NULL;
m_nNumPreviewPages = 0; // not specified (defaults to 1) // initialize DAO state
m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called // other initialization m_bHelpMode = FALSE; m_eHelpType = afxWinHelp;
m_nSafetyPoolSize = 512; // default size }
2:theApp之后的隐藏代码,由他控制整个程序的流程。
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }
其中有宏定义:#define _tWinMain wWinMain
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
ASSERT(hPrevInstance == NULL); int nReturnCode = -1;
CWinThread* pThread = AfxGetThread();;// CWinApp是从CWinThread派生的, CWinApp* pApp = AfxGetApp(); //实质上就是pThread==pApp // AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)) //用于初始化
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication()) //用于初始化 goto InitFailure;
// Perform specific initializations
if (!pThread->InitInstance()) //注意多态性 virtual BOOL InitInstance();
//又因为pThread==pApp,所以调用pApp-> InitInstance()
{
if (pThread->m_pMainWnd != NULL) {
TRACE(traceAppMsg, 0, \n\
pThread->m_pMainWnd->DestroyWindow(); }
nReturnCode = pThread->ExitInstance(); goto InitFailure; }
nReturnCode = pThread->Run(); //控制消息循环 InitFailure: #ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0) {
TRACE(traceAppMsg, 0, \\\n\
AfxGetModuleThreadState()->m_nTempMapLock); }
AfxLockTempMaps(); AfxUnlockTempMaps(-1); #endif
AfxWinTerm(); return nReturnCode; }
由上面的程序可以看到几个很重要的函数
(1)AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)) goto InitFailure; (2) pApp->InitApplication())
(3) pThread->InitInstance() (4) pThread->Run()
其中1,2 也是完成程序的一些初始化工作,4 主要是为了处理消息,3呢,很关键,我们运行时看到的窗口就是从这里产生。下面一一介绍
3:程序自动产生的InitInstance()函数
以下是自动生成的InitInstance()源程序: BOOL CmyApp::InitInstance() {
// 如果一个运行在 Windows XP 上的应用程序清单指定要 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式, //则需要 InitCommonControls()。否则,将无法创建窗口。 InitCommonControls(); CWinApp::InitInstance(); // 初始化 OLE 库 if (!AfxOleInit()) {
AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; }
AfxEnableControlContainer(); // 标准初始化
// 如果未使用这些功能并希望减小 // 最终可执行文件的大小,则应移除下列 // 不需要的特定初始化例程 // 更改用于存储设置的注册表项 // TODO: 应适当修改该字符串, // 例如修改为公司或组织名
SetRegistryKey(_T(\应用程序向导生成的本地应用程序\
LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) // 注册应用程序的文档模板。文档模板 // 将用作文档、框架窗口和视图之间的连接 CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_myTYPE, RUNTIME_CLASS(CmyDoc),
RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CmyView)); if (!pDocTemplate) return FALSE;
AddDocTemplate(pDocTemplate); // 创建主 MDI 框架窗口
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;
m_pMainWnd = pMainFrame;
// 仅当具有后缀时才调用 DragAcceptFiles
// 在 MDI 应用程序中,这应在设置 m_pMainWnd 之后立即发生 // 分析标准外壳命令、DDE、打开文件操作的命令行 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // 调度在命令行中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
if (!ProcessShellCommand(cmdInfo)) //引发窗口注册 return FALSE;
// 主窗口已初始化,因此显示它并对其进行更新 pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE;
}
其中,注册窗口用到了一下函数,比较长,如下:
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister) {
// mask off all classes that are already registered AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); fToRegister &= ~pModuleState->m_fRegisteredClasses; if (fToRegister == 0) return TRUE;
LONG fRegisteredClasses = 0; // common initialization WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults wndcls.lpfnWndProc = DefWindowProc; //窗口处理函数 wndcls.hInstance = AfxGetInstanceHandle(); wndcls.hCursor = afxData.hcurArrow;
INITCOMMONCONTROLSEX init; init.dwSize = sizeof(init);
// work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
if (fToRegister & AFX_WND_REG) {
// Child windows - no brush, no icon, safest default class styles wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wndcls.lpszClassName = _afxWnd; if (AfxRegisterClass(&wndcls)) fRegisteredClasses |= AFX_WND_REG;
}
if (fToRegister & AFX_WNDOLECONTROL_REG) {
// OLE Control windows - use parent DC for speed
wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wndcls.lpszClassName = _afxWndOleControl; if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WNDOLECONTROL_REG; }
if (fToRegister & AFX_WNDCONTROLBAR_REG) {
// Control bar windows
wndcls.style = 0; // control bars don't handle double click wndcls.lpszClassName = _afxWndControlBar;
wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WNDCONTROLBAR_REG; }
if (fToRegister & AFX_WNDMDIFRAME_REG) {
// MDI Frame window (also used for splitter window) wndcls.style = CS_DBLCLKS; wndcls.hbrBackground = NULL;
if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
fRegisteredClasses |= AFX_WNDMDIFRAME_REG; }
if (fToRegister & AFX_WNDFRAMEORVIEW_REG) {
// SDI Frame or MDI Child windows or views - normal colors
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG; }
if (fToRegister & AFX_WNDCOMMCTLS_REG) {
// this flag is compatible with the old InitCommonControls() API init.dwICC = ICC_WIN95_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
fToRegister &= ~AFX_WIN95CTLS_MASK; }
if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG) {
init.dwICC = ICC_UPDOWN_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG) {
init.dwICC = ICC_TREEVIEW_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_TAB_REG) {
init.dwICC = ICC_TAB_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_
TAB_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG) {
init.dwICC = ICC_PROGRESS_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG) {
init.dwICC = ICC_LISTVIEW_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG) {
init.dwICC = ICC_HOTKEY_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_BAR_REG) {
init.dwICC = ICC_BAR_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG) {
init.dwICC = ICC_ANIMATE_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_
ANIMATE_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG) {
init.dwICC = ICC_INTERNET_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_COOL_REG) {
init.dwICC = ICC_COOL_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG) {
init.dwICC = ICC_USEREX_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_DATE_REG) {
init.dwICC = ICC_DATE_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);
}
if (fToRegister & AFX_WNDCOMMCTL_LINK_REG) {
init.dwICC = ICC_LINK_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_
LINK_REG);
}
// save new state of registered controls
pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
// special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG
if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)
{
pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG; fRegisteredClasses |= AFX_WNDCOMMCTLS_REG; }
// must have registered at least as mamy classes as requested return (fToRegister & fRegisteredClasses) == fToRegister; }
他是在PreCreateWindow中调用的注册,
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) {
if (cs.lpszClass == NULL) {
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background }
if (cs.style & FWS_ADDTOTITLE) cs.style |= FWS_PREFIXTITLE;
cs.dwExStyle |= WS_EX_CLIENTEDGE; return TRUE; }
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE;
// TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return TRUE; }
BOOL CView::PreCreateWindow(CREATESTRUCT & cs) {
ASSERT(cs.style & WS_CHILD); if (cs.lpszClass == NULL) {
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background }
if (cs.style & WS_BORDER) {
cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; }
return TRUE; }
BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs) {
// TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs
return CView::PreCreateWindow(cs); }
有几点要说明
(1)m_pMainWnd,头文件里并没有这个变量呀? 噢,这个在基类里定义的public 类型的变量,所以,他是通过继承得到的。
(2) 你注意过吗,当我们一点运行,会默认出来一个视图窗口,这是谁调用的呢?哦,就是下面这几行,它调用了opendocument() 函数。
CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); if (!ProcessShellCommand(cmdInfo)) return FALSE; (3)这个函数有个关键的地方 CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_myTYPE, RUNTIME_CLASS(CmyDoc),
RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CmyView)); if (!pDocTemplate) return FALSE;
AddDocTemplate(pDocTemplate); 通过它,把视图,窗口和文档结合起来。
4:主窗口CMainFrame的创建
(1)通过CMainFrame* pMainFrame = new CMainFrame;
我们得到的是不断调用的基类 CMainFrame::CMainFrame() {
// TODO: 在此添加成员初始化代码 }
CMDIFrameWnd::CMDIFrameWnd() {
m_hWndMDIClient = NULL; }
CFrameWnd::CFrameWnd() {
ASSERT(m_hWnd == NULL);
m_nWindow = -1; m_bAutoMenuEnable = TRUE; m_lpfnCloseProc = NULL; m_hMenuDefault = NULL; m_hAccelTable = NULL; m_nIDHelp = 0; m_nIDTracking = 0; m_nIDLastMessage = 0; m_pViewActive = NULL;
m_cModalStack = 0; m_phWndDisable = NULL; m_pNotifyHook = NULL; m_hMenuAlt = NULL;
m_nIdleFlags = 0; m_rectBorder.SetRectEmpty();
m_bHelpMode = HELP_INACTIVE; m_dwPromptContext = 0;
m_pNextFrameWnd = NULL;
m_bInRecalcLayout = FALSE; m_pFloatingFrameClass = NULL; m_nShowDelay = -1; AddFrameWnd();
// unknown window ID // auto enable on by default // initialize modality support// no idle work at start // not in Shift+F1 help mode // not in list yet // no delay pending
}
(2)pMainFrame->LoadFrame(IDR_MAINFRAME)所引发的一系列
BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext) {
if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext)) return FALSE;
// save menu to use when no active MDI child window is present ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd); if (m_hMenuDefault == NULL)
TRACE(traceAppMsg, 0, \\\n\
return TRUE; }
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext) {
// only do this once
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
CString strFullString;
if (strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); // attempt to create the window
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource); CString strTitle = m_strTitle;
if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault, pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext)) {
return FALSE; // will self destruct on failure normally }
// save the default menu handle ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd); // load accelerator resource
LoadAccelTable(MAKEINTRESOURCE(nIDResource)); if (pContext == NULL) // send initial update
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE); return TRUE; }
BOOL CFrameWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, LPCTSTR lpszMenuName, DWORD dwExStyle,
CCreateContext* pContext) {
HMENU hMenu = NULL;
if (lpszMenuName != NULL) {
// load in a menu that will get destroyed when window gets destroyed
HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU); if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL) {
TRACE(traceAppMsg, 0, \nd.\\n\
PostNcDestroy(); // perhaps delete the C++ object return FALSE; } }
m_strTitle = lpszWindowName; // save title for later
if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext)) {
TRACE(traceAppMsg, 0, \ if (hMenu != NULL) DestroyMenu(hMenu); return FALSE; }
return TRUE; }
因为CFrameWnd没有重新写CreateEX,所以是调用的基类的CreateEx的函数: BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam) {
// allow modification of several common create parameters CREATESTRUCT cs;
cs.dwExStyle = dwExStyle; cs.lpszClass = lpszClassName; cs.lpszName = lpszWindowName; cs.style = dwStyle; cs.x = x; cs.y = y; cs.cx = nWidth; cs.cy = nHeight;
cs.hwndParent = hWndParent; cs.hMenu = nIDorHMenu;
cs.hInstance = AfxGetInstanceHandle(); cs.lpCreateParams = lpParam;
if (!PreCreateWindow(cs)) {
PostNcDestroy(); return FALSE; }
AfxHookWindowCreate(this);
HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
#ifdef _DEBUG if (hWnd == NULL) {
TRACE(traceAppMsg, 0, \r returns 0x%8.8X\\n\
GetLastError()); } #endif
if (!AfxUnhookWindowCreate())
PostNcDestroy(); // cleanup if CreateWindowEx fails too soon
if (hWnd == NULL) return FALSE;
ASSERT(hWnd == m_hWnd); // should have been set in send msg hook return TRUE; }
可以看到,::CreateWindowEx是一个全局的函数,在其中触发WM_CREATE消息,进而调用我们自己定义的CMainFrame::OnCreate()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0(\未能创建工具栏\\n\ return -1; // 未能创建 }
if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) {
TRACE0(\未能创建状态栏\\n\ return -1; // 未能创建 }
//TODO: 如果不需要工具栏可停靠,则删除这三行 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar);
return 0; }
5:运行后为什么能产生CMainFarme,文档 ,视图以及视图外包围的farme呢?
你注意过吗,当我们一点运行,会默认出来一个视图窗口,这是谁调用的呢?哦,就是下面这几行,它调用void CWinApp::OnFileNew()函数.
CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo)) return FALSE;
你可以自己跟踪以下。这里有个小技巧,你可以在BOOL CmyDoc::OnNewDocument()处设立断点,然后“跳出”,最后你会达到起始点!ProcessShellCommand(cmdInfo)
void CWinApp::OnFileNew() {
if (m_pDocManager != NULL)
m_pDocManager->OnFileNew(); //接着调用下面的函数 }
void CDocManager::OnFileNew() {
if (m_templateList.IsEmpty()) {
TRACE(traceAppMsg, 0, \ CWinApp.\\n\
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); return; }
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead(); if (m_templateList.GetCount() > 1) {
// more than one document template to choose from // bring up dialog prompting user CNewTypeDlg dlg(&m_templateList); INT_PTR nID = dlg.DoModal(); if (nID == IDOK)
pTemplate = dlg.m_pSelectedTemplate; else
return; // none - cancel operation }
ASSERT(pTemplate != NULL);
ASSERT_KINDOF(CDocTemplate, pTemplate);
pTemplate->OpenDocumentFile(NULL); //接着调用下面的函数
// if returns NULL, the user has already been alerted }
CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible) {
CDocument* pDocument = CreateNewDocument(); //产生模板控制之一:文档 if (pDocument == NULL) {
TRACE(traceAppMsg, 0, \L.\\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
TRACE(traceAppMsg, 0, \\\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
TRACE(traceAppMsg, 0, \\\n\
pFrame->DestroyWindow();
return NULL; }
pDocument->SetPathName(lpszPathName); }
InitialUpdateFrame(pFrame, pDocument, bMakeVisible); return pDocument; }
我需要对上述函数进行进一步说明
(1)CreateNewDocument()产生文档
CDocument* CDocTemplate::CreateNewDocument() {
// default implementation constructs one from CRuntimeClass if (m_pDocClass == NULL) {
TRACE(traceAppMsg, 0, \eNewDocument.\\n\
ASSERT(FALSE); return NULL; }
CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject(); if (pDocument == NULL) {
TRACE(traceAppMsg, 0, \ failed.\\n\
m_pDocClass->m_lpszClassName); return NULL;
}
ASSERT_KINDOF(CDocument, pDocument); AddDocument(pDocument); return pDocument; }
(2)CreateNewFrame(pDocument, NULL),产生框架和视图
CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)
{
if (pDoc != NULL) ASSERT_VALID(pDoc);
// create a frame wired to the specified document
ASSERT(m_nIDResource != 0); // must have a resource ID to load from CCreateContext context;
context.m_pCurrentFrame = pOther;
}
ASSERT_KINDOF(CDocument, pDocument); AddDocument(pDocument); return pDocument; }
(2)CreateNewFrame(pDocument, NULL),产生框架和视图
CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)
{
if (pDoc != NULL) ASSERT_VALID(pDoc);
// create a frame wired to the specified document
ASSERT(m_nIDResource != 0); // must have a resource ID to load from CCreateContext context;
context.m_pCurrentFrame = pOther;
正在阅读:
MFC文档视图结构框架分析07-05
2015山西事业单位面试备考:确定目标 - 让表达有的放矢(中)06-13
定额类别 - 图文03-19
2008届9月黄冈市浠水高考复读中心月考物理部份力物体平衡直线运03-01
吴江林学术报告之:基于教-学-评一致性的策略与实践04-23
我心中的幸福作文300字06-23
爱的选择作文600字07-05
抒情散文:假如我们未曾相遇03-21
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 视图
- 框架
- 结构
- 文档
- 分析
- MFC
- 配套K12山东省临沂市兰陵县东苑高级中学2019届高三历史上
- 电气设备预试方案
- 2013-2014对口汽修期中考试题
- 高三生物复习知识点分类汇编2
- 罗马共和国的胜利与悲哀读书笔记
- cpu利用解释
- 博迪莫顿版金融学所有习题参考答案
- 年产煤矿60万吨改扩建工程融资投资立项项目可行性研究报告(中撰
- 影响PCB激光分板机精度的光学配件 - 图文
- 冀教版三年级科学上册知识点及复习题大全
- 军事理论课复习题
- 污泥制备活性炭及其应用研究进展
- 投标文件制作指南
- 部编人教版九年级化学上册《分子和原子》第二课时名师教案
- 延庆新城重大基础设施建设计划20130417 - 图文
- 基础护理学
- 2009学年第二学期徐汇区高一数学学习能力诊断卷(A、B卷)(附答
- 动画制作课程讲义new
- 2018届语文一轮教学案:专题十三第二讲 新闻和访谈 含解析
- 2018年1月北京市延庆区七上期末数学试题含答案