为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

MFC文档视图结构框架分析

2011-04-20 26页 doc 100KB 49阅读

用户头像

is_162882

暂无简介

举报
MFC文档视图结构框架分析MFC文档视图结构框架分析 1:程序的“导火索”---theApp CmyApp theApp; 在声明对象的同时,调用其构造函数。按C++的语法,首先要调用其基类Cwinapp的构造函数. 这个文件主要用于应用程序的一些初始化操作。 class CWinApp : public CWinThread {     DECLARE_DYNAMIC(CWinApp) public: // Constructor     CWinApp(LPCTSTR lpszAppName = NULL);  ………… }   CWinApp::...
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, "Warning: Destroying non-NULL m_pMainWnd\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, "Warning: Temp map lock count non-zero (%ld).\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;                 // unknown window ID     m_bAutoMenuEnable = TRUE;       // auto enable on by default     m_lpfnCloseProc = NULL;     m_hMenuDefault = NULL;     m_hAccelTable = NULL;     m_nIDHelp = 0;     m_nIDTracking = 0;     m_nIDLastMessage = 0;     m_pViewActive = NULL;     m_cModalStack = 0;              // initialize modality support     m_phWndDisable = NULL;     m_pNotifyHook = NULL;     m_hMenuAlt = NULL;     m_nIdleFlags = 0;               // no idle work at start     m_rectBorder.SetRectEmpty();     m_bHelpMode = HELP_INACTIVE;    // not in Shift+F1 help mode     m_dwPromptContext = 0;     m_pNextFrameWnd = NULL;         // not in list yet       m_bInRecalcLayout = FALSE;     m_pFloatingFrameClass = NULL;     m_nShowDelay = -1;              // no delay pending     AddFrameWnd(); } (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, "Warning: CMDIFrameWnd without a default menu.\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, "Warning: failed to load menu for CFrameWnd.\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, "Warning: failed to create CFrameWnd.\n");        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, "Warning: Window creation failed: GetLastError 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, "Error: no document templates registered with 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);        I
/
本文档为【MFC文档视图结构框架分析】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索