在vc6.0中
选择File/New
在projects标签页选择MFC Appwizard(exe)
在接下来的对话框中选择multiple document...
即可建立一多文档项目
每新建一个多文档的项目,wizard都会自动生成6个类,比如新建multid项目
自动生成的类是
CMultidApp---对应文件是multid.cpp和multid.h
CMainFrame---对应文件是MainFrm.cpp和MainFrm.h
CChildFrame---对应文件是ChildFrm.cpp和ChildFrm.h
CMultidDoc---对应文件是MultidDoc.cpp和MultidDoc.h
CMultidView---对应文件是MultidView.cpp和MultidView.h
CAboutDlg-----在multid.cpp中声明和实现。
其中
CMainFrame继承于CMDIFrameWnd-->CFrameWnd-->CWnd-->CCmdTarget
CChildFrame继承于CMDIChildWnd-->CFrameWnd-->CWnd-->CCmdTarget
看一下执行流程--参照深入浅出mfc chapter6
首先有一个全局的对象theApp属于类CMultidApp,继承于CWinApp。全部变量在winmain函数执行之前就已经创建,类CWinApp有几个函数比较重要,在AFXWIN.H
跟踪theApp->InitInstance()
在multid.cpp改写的InitInstance函数,创建并显示窗口,源码如下
跟踪theApp->Run();在CMultidApp类没有改写基类的Run()成员函数,则调用到基类CWinApp的Run,在调用到CWinThread::Run();
在创建窗口CMainFrame的时候,指定了窗口处理函数。
选择File/New
在projects标签页选择MFC Appwizard(exe)
在接下来的对话框中选择multiple document...
即可建立一多文档项目
每新建一个多文档的项目,wizard都会自动生成6个类,比如新建multid项目
自动生成的类是
CMultidApp---对应文件是multid.cpp和multid.h
CMainFrame---对应文件是MainFrm.cpp和MainFrm.h
CChildFrame---对应文件是ChildFrm.cpp和ChildFrm.h
CMultidDoc---对应文件是MultidDoc.cpp和MultidDoc.h
CMultidView---对应文件是MultidView.cpp和MultidView.h
CAboutDlg-----在multid.cpp中声明和实现。
其中
CMainFrame继承于CMDIFrameWnd-->CFrameWnd-->CWnd-->CCmdTarget
CChildFrame继承于CMDIChildWnd-->CFrameWnd-->CWnd-->CCmdTarget
看一下执行流程--参照深入浅出mfc chapter6
首先有一个全局的对象theApp属于类CMultidApp,继承于CWinApp。全部变量在winmain函数执行之前就已经创建,类CWinApp有几个函数比较重要,在AFXWIN.H
class CWinApp : public CWinThread
{
DECLARE_DYNAMIC(CWinApp)
public:
...
virtual BOOL InitApplication();
virtual BOOL InitInstance();
virtual int Run();
...
}
创建好theApp对象后,进入程序入口点_tWinMain,调用theApp的成员函数InitInstance,InitApplication,Run,其中虚函数InitInstance在multid.cpp中改写。可以看出程序的执行路径,和sdk中程序执行路径对应。_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,//入口点,appmodul.cppP
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,//winmain.cpp
LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
int nReturnCode = -1;
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication())//调用theApp->InitApplication()
goto InitFailure;
// Perform specific initializations
if (!pThread->InitInstance())//调用theApp->InitInstance()
{
if (pThread->m_pMainWnd != NULL)
{
TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
nReturnCode = pThread->Run();//调用theApp->Run()
InitFailure:
#ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE1("Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif
AfxWinTerm();
return nReturnCode;
}
跟踪theApp->InitInstance()
在multid.cpp改写的InitInstance函数,创建并显示窗口,源码如下
BOOL CMultidApp::InitInstance()
{
AfxEnableControlContainer();
// 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.
// TODO: 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_MULTIDTYPE,
RUNTIME_CLASS(CMultidDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CMultidView));
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;//创建窗口对象CMainFrame
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))//为对象加载资源,在sdk中是用CreateWindow创建的窗口
return FALSE;
m_pMainWnd = pMainFrame;
// 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;
}
窗口已经创建,下面就是怎么获取窗口消息?跟踪theApp->Run();在CMultidApp类没有改写基类的Run()成员函数,则调用到基类CWinApp的Run,在调用到CWinThread::Run();
// Main running routine until application exits
int CWinApp::Run()//appcore.cpp
{
if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
{
// Not launched /Embedding or /Automation, but has no main window!
TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
AfxPostQuitMessage(0);
}
return CWinThread::Run();
}
int CWinThread::Run()//thrdCore.cpp
{
ASSERT_VALID(this);
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}
// phase2: pump messages while available
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())//在同1cpp
return ExitInstance();
// reset "no idle" state after pumping "normal" message
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}
ASSERT(FALSE); // not reachable
}
BOOL CWinThread::PumpMessage()
{
ASSERT_VALID(this);
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
{
#ifdef _DEBUG
if (afxTraceFlags & traceAppMsg)
TRACE0("CWinThread::PumpMessage - Received WM_QUIT.\n");
m_nDisablePumpCount++; // application must die
// Note: prevents calling message loop things in 'ExitInstance'
// will never be decremented
#endif
return FALSE;
}
#ifdef _DEBUG
if (m_nDisablePumpCount != 0)
{
TRACE0("Error: CWinThread::PumpMessage called when not permitted.\n");
ASSERT(FALSE);
}
#endif
#ifdef _DEBUG
if (afxTraceFlags & traceAppMsg)
_AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
#endif
// process this message
if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);//翻译消息
::DispatchMessage(&m_msgCur);//分发消息
}
return TRUE;
}
消息已经获取,也可看到同sdk中消息获取原理一模一样,接下来就是将获取到的消息给了什么函数去处理?当然是窗口函数。在创建窗口CMainFrame的时候,指定了窗口处理函数。
本文详细介绍了在VC6.0中使用MFCAppWizard创建多文档项目的操作步骤,并深入分析了初始化过程及执行流程,包括窗口对象的创建、初始化、消息处理等关键环节。
4828

被折叠的 条评论
为什么被折叠?



