mfcÎĵµÊÓͼ½á¹¹ÄÚÄ»(×ªÔØ)
////////////////////////////////////////////////////////////////////////////////////
/********* ÎÄÕÂϵÁУºMFC¼¼ÊõÄÚĻϵÁÐ***********/
/************MFC¼¼ÊõÄÚĻϵÁÐÖ®£¨¶þ£©***********/
/**** ÎÄÕÂÌâÄ¿£ºMFCÎĵµÊÓͼ½á¹¹ÄÚÄ» *****/
/* Copyright(c)2002 bigwhite */
/* All rights Reserved */
/*********¹Ø¼ü×Ö£ºMFC£¬ÎĵµÊÓͼ½á¹¹************/
/* ʱ¼ä£º2002.7.23 */
/* ×¢ÊÍ£º±¾ÎÄËùÉæ¼°µÄ³ÌÐòÔ´´úÂë¾ùÔÚMicrosoft */
/ Visual Studio.Net Enterprise Architect Edition /
/* ¿ª·¢¹¤¾ß°üÌṩµÄÔ´´úÂëÖÐ */
//////////////////////////////////////////////////////////////////////////////////////////////////////////
ÒýÑÔ£ººî½ÝÀÏʦµÄ"ÉîÈëdz³öMFC"Ò»ÊéµÄµÚ8ÕÂÖÐÓС°"Document/View"ÊÇMFCµÄ»ùʯ¡£¡±Ò»Ëµ£¬¿ÉÒÔ¿´³öÎĵµÊÓͼ½á¹¹ÔÚMFC FrameworkÖеĵØÎ»ÊǶàôµÄÖØÒª¡£±¾ÎĽ«ÒÔÒ»¸ö±ê×¼MFCÓ¦ÓóÌÐòÏòµ¼×÷³ÉµÄMDI³ÌÐòΪÀý£¬À´ºÍ´ó¼ÒÒ»ÆðÏêϸÍÚ¾òÎĵµÊÓͼ½á¹¹µÄÄÚÄ»¡£
ÕýÎÄ£º
/////////////////////////////////////////////
/* 1.»Ø¹Ë"InitInstanceº¯Êý" */
/////////////////////////////////////////////
ÔÚÎҵġ¶MFCÓ¦ÓóÌÐò¡°ÉúËÀÒò¹û¡±ÄÚÄ»¡·Ò»ÎÄÖУ¬µ±Ì¸µ½CMyWinApp::InitInstance()ʱ£¬ÎÒÖ»ÊÇ´ÖÂԵĽ²Á˽éÉÜÁËһϸ÷¸öº¯ÊýµÄ¹¦ÄÜ£¬¶øºöÂÔÁ˺ܶàϸ½Ú£¬ÕâÀïÈÃÎÒÃÇÔڻعËÒ»ÏÂCMyWinApp::InitInstance()º¯Êý£¬²¢½«ÀïÃæÓëÎĵµÊÓͼ½á¹¹ÓйصĴúÂëÉîÈë̽ÌÖһϣº
BOOL CMyApp::InitInstance()//Ö»ÁгöÁËÓëÎĵµÊÓͼ½á¹¹Ïà¹ØµÄÔ´´úÂë
{
//...
//ÎĵµÄ£°å½«ÓÃ×÷Îĵµ¡¢¿ò¼Ü´°¿ÚºÍÊÓͼ֮¼äµÄÁ¬½Ó
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_MyTYPE,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CChildFrame), // ×Ô¶¨Òå MDI ×Ó¿ò¼Ü
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
// ´´½¨Ö÷ MDI ¿ò¼Ü´°¿Ú
CMainFrame* pMainFrame = new CMainFrame;
if (!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;
}
////////////////////////////////////////////
/* 2.³õʼ»¯ÎĵµÄ£°å */
////////////////////////////////////////////
·ÖÎöÒÔÏ´úÂ룺
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_MyTYPE,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CChildFrame), // ×Ô¶¨Òå MDI ×Ó¿ò¼Ü
RUNTIME_CLASS(CMyView));
Ó¦ÓóÌÐòÊ×ÏÈʵÀý»¯Ò»¸öCMultiDocTemplate¶ÔÏ󣬴˹ý³ÌÒ²ÊǶÔCMultiDocTemplateÀàÊý¾Ý³ÉÔ±µÄ³õʼ»¯¹ý³Ì¡£°´µ÷ÓôÎÐòÎÒÁгöÁËÒÔÏÂÔ´´úÂ룺
×¢ÊÍ1: CDocTemplate¹¹Ô캯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcdoctempl.cpp
CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)//²¿·ÖÔ´´úÂë
{
ASSERT_VALID_IDR(nIDResource);
ASSERT(pDocClass == NULL ||
pDocClass->IsDerivedFrom(RUNTIME_CLASS(CDocument)));
ASSERT(pFrameClass == NULL ||
pFrameClass->IsDerivedFrom(RUNTIME_CLASS(CFrameWnd)));
ASSERT(pViewClass == NULL ||
pViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));
m_nIDResource = nIDResource;
...//
m_pDocClass = pDocClass;
m_pFrameClass = pFrameClass;
m_pViewClass = pViewClass;
m_pOleFrameClass = NULL;
m_pOleViewClass = NULL;
...//
}
ÒÔÉÏΪCMultiDocTemplateÀàµÄ»ùÀàCDocTemplate¹¹Ô캯ÊýµÄ²¿·ÖÔ´´úÂ룬¸Ãº¯Êý³õʼ»¯ÁËËĸöÖØÒªµÄ³ÉÔ±
m_nIDResource£¬m_pDocClass£¬m_pFrameClassºÍm_pViewClass¡£
×¢ÊÍ2: CMultiDocTemplate¹¹Ô캯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcdocmulti.cpp
CMultiDocTemplate::CMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
: CDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass)
{
ASSERT(m_docList.IsEmpty());
m_hMenuShared = NULL;
m_hAccelTable = NULL;
m_nUntitledCount = 0; // start at 1
// load resources in constructor if not statically allocated
if (!CDocManager::bStaticInit)
LoadTemplate();
}
¿´ÍêÒÔÉÏ´úÂëºó£¬À´»Ø¹ýÍ·¿´Ò»¿´InitInstanceº¯Êý½«Ê²Ã´²ÎÊýÖµ´«¸øÁËCMultiDocTemplateµÄ¹¹Ô캯Êý¡£
ÔÀ´ÊÇһЩRUNTIME_CLASSºê¡£ÒÔÏÂÊÇRUNTIME_CLASSºêµÄ¶¨Òå:
×¢ÊÍ3: ÒÔϵĺ궨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcincludeafx.hÖÐ
#define RUNTIME_CLASS(class_name) _RUNTIME_CLASS(class_name)
#define _RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
Õâ¸öµØ·½ÊǸöÄѵ㣬Õâ½«Éæ¼°µ½MFCµÄÁíÒ»¸öÖØÒª¼¼Êõ---"Ö´ÐÐÆÚÀàÐÍʶ±ð"¡£´ËÏî¼¼ÊõÎÒ½«ÔÚ
MFC¼¼ÊõÄÚĻϵÁÐÖ®£¨Èý£©---¡¶MFCÖ´ÐÐÆÚÀàÐÍʶ±ðÓ붯̬´´½¨¼¼ÊõÄÚÄ»¡·ÖÐÏêϸ½²½â¡£»Øµ½ÑÛǰÀ´£¬Ô´´úÂëÖÐÕâÑù×÷ÊÇΪÁ˽«CMyDoc£¬CChildFrame£¬CMyView¸÷ÀàÖеÄstatic CRuntimeClass class##class_nameµØÖ·¸³ÓèCMultiDocTemplateÀàµÄ¸÷CRuntimeClass*Ö¸Õë³ÉÔ±m_pDocClass£¬m_pFrameClassºÍm_pViewClass£¬ÕâλÒÔºóµÄ¶¯Ì¬´´½¨Document/Frame/View"Èý¿Ú×é"´òÏÂÁË»ù´¡¡£
///////////////////////////////////////////
/* 3.ÎĵµÄ£°åÁÐ¶Ó */
///////////////////////////////////////////
ÎĵµÄ£°å³õʼ»¯½áÊøºó£¬InitInstanceº¯Êýµ÷ÓÃÁËCWinApp::AddDocTemplate(pDocTemplate)º¯Êý£¬ÆäÖ÷ҪĿµÄÊǽ«ÒÔ³õʼ»¯ºóµÄÄǸöÎĵµÄ£°å¼ÓÈëµ½ÎĵµÄ£°åÁ´±íÖÐ,²¢ÓÉCDocManagerÀà¶ÔÏó½øÐйÜÀí¡£ÒÔϲÙ×÷¾ÍÊÇΪÁËÍê³É´Ë¹¤×÷¡£
×¢ÊÍ1: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcappui2.cpp
void CWinApp::AddDocTemplate(CDocTemplate* pTemplate)//½«CMultiDocTemplate* pDocTemplate
{ //´«¸øpTemplate
if (m_pDocManager == NULL)
m_pDocManager = new CDocManager;
m_pDocManager->AddDocTemplate(pTemplate);
}
×¢ÊÍ2: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcdocmgr.cpp
CDocManager::CDocManager()
{
}//ĿǰÊÇÒ»¸ö¿Õº¯Êý£»
void CDocManager::AddDocTemplate(CDocTemplate* pTemplate)//²¿·ÖÔ´´úÂë
{
if (pTemplate == NULL)
{
...//
}
else
{
ASSERT_VALID(pTemplate);
ASSERT(m_templateList.Find(pTemplate, NULL) == NULL);// must not be in list
pTemplate->LoadTemplate();
m_templateList.AddTail(pTemplate);//CPtrList m_templateList is a member //of CDocManager
}
}
///////////////////////////////////////////////
/* 4.´´½¨³ÌÐòÖ÷¿ò¼Ü´°¿Ú */
///////////////////////////////////////////////
Ó¦ÓóÌÐòʵÀý»¯ÁËÒ»¸öCMainFrameÀà¶ÔÏ󣬲¢µ÷ÓÃLoadFrameº¯Êý¼ÓÔØ´°¿Ú×ÊÔ´´´½¨Ö÷¿ò¼Ü´°¿Ú¡£ÒÔÏÂÊÇ´´½¨Ö÷¿ò¼Ü´°¿ÚµÄÁ÷³Ì¡£
´´½¨´°¿ÚµÄÖ÷Òª´úÂëÊÇ£ºpMainFrame->LoadFrame(IDR_MAINFRAME)£»LoadFrameº¯ÊýÊÇMFC°ü×°ÁË´°¿Ú´´½¨¹ý³ÌµÄº¯Êý£¬ÔÚºóÃæ¶¯Ì¬´´½¨Child´°¿Úʱ£¬Ëü»¹½«Åû¹ÒÉÏÕó(µ«ÉÔÓв»Í¬£©¡£ÏÂÃæÊÇËüµÄÔ´´úÂë,ÈÃÎÒÃÇ×Ðϸ·ÖÎöÒ»ÏÂ:
×¢ÊÍ1: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcwinmdi.cpp
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.
");
return TRUE;
}
CMDIFrameWnd::LoadFrameµ÷ÓÃÁËÆä»ùÀàCFrameWndµÄLoadFrame£¬²¢½«²ÎÊýÔ·â²»¶¯µÄ´«¸øËü¡£
×¢ÊÍ2: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcwinfrm.cpp
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext) //²¿·ÖÔ´´úÂë
{
...//
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
}
...//
if (pContext == NULL) // send initial update
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
return TRUE;
}
//////////////////////////////////////////////////////
/* 4.1×¢²áÓ¦ÓóÌÐòÖ÷¿ò¼Ü´°¿ÚÀà */
//////////////////////////////////////////////////////
ÔÚ´«Í³µÄWin32API±à³ÌÖУ¬´´½¨´°¿ÚÒ»°ã²½ÖèÊǶ¨Òå´°¿ÚÀ࣬ע²á´°¿ÚÀ࣬²¢µ÷ÓÃ::CreateWindowº¯ÊýÀ´´´½¨¡£Ç°ÃæËµ¹ýLoadFrameº¯Êý·â×°ÁËMFC´´½¨´°¿ÚµÄ¹ý³Ì£¬ÄÇôҲ¾ÍÊÇ˵LoadFrameº¯Êý½«¸ºÔð¶¨Òå´°¿ÚÀ࣬ע²á´°¿ÚÀàµÈËöË鹤×÷¡£ÏÂÃæÎÒÃǾÍͨ¹ýÍÚ¾òÔ´´úÂëÀ´¿´¿´LoadFrameº¯ÊýÊÇÈçºÎÍê³ÉÕâЩ¹¤×÷µÄ¡£
LoadFrameÊ×Ïȵ÷ÓÃAfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)£¬
×¢ÊÍ1: ÒÔϺ궨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcafximpl.h
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
×¢ÊÍ2: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcwincore.cpp
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_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;
}
...//
// must have registered at least as mamy classes as requested
return (fToRegister & fRegisteredClasses) == fToRegister;
}
MFCÔ¤¶¨ÒåÁËÈô¸É¸ö¡°´°¿ÚÀàÄ£°å¡±£¬±ÈÈç"AFX_WNDMDIFRAME_REG","AFX_WNDFRAMEORVIEW_REG"µÈ£¬MFCÔÚ
LoadFrameº¯ÊýÖе÷ÓÃAfxEndDeferRegisterClassº¯ÊýΪÄãµÄÓ¦ÓóÌÐòԤע²áÁËÊʵ±µÄ´°¿ÚÀà¡£±¾ÀýÖÐԤע²áµÄ´°¿ÚÀàΪAFX_WNDFRAMEORVIEW_REG¡££¨×¢ÒâÊÇԤע²á£¬Èç¹ûÄãÔÚºóÃæ¸ü¸ÄÁËCREATESTRUCT½á¹¹µÄÓò³ÉÔ±£¬MFC»¹»á¸ù¾ÝÄãµÄ¸ü¸ÄÖØÐÂΪÄãµÄÓ¦ÓóÌÐòÕýʽע²áеĴ°¿ÚÀ࣬ÉÔºò»áÓÐÏêϸÐðÊö£©
Ԥע²áÍê´°¿ÚÀ࣬MFC½«ÅжÏÄãÊÇ·ñÏë¸ü¸Ä´°¿ÚÀàµÄ¸÷²ÎÊý¡£ÈôÄã¸ü¸ÄÁË£¬ÔòMFC»áÖØÐÂ×¢²áÐÂÀࣻ·ñÔòԴԤע²áµÄ´°¿ÚÀà¾Í½«³ÉΪÕýʽµÄ´°¿ÚÀà¡£ÏÂÃæÎÒÃÇÀ´¿´¿´MFCµÄÅжϹý³Ì£º´ËÅжϹý³ÌÓÉGetIconWndClass¿ªÊ¼
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
×¢ÊÍ3: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcwinfrm.cpp
LPCTSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle, UINT nIDResource)//²¿·ÖÔ´´úÂë
{
...//
HICON hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource));
if (hIcon != NULL)
{
CREATESTRUCT cs;
memset(&cs, 0, sizeof(CREATESTRUCT));
cs.style = dwDefaultStyle;
PreCreateWindow(cs);
// will fill lpszClassName with default WNDCLASS name
// ignore instance handle from PreCreateWindow.
WNDCLASS wndcls;
if (cs.lpszClass != NULL &&
GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndcls) &&
wndcls.hIcon != hIcon)
{
// register a very similar WNDCLASS
return AfxRegisterWndClass(wndcls.style,
wndcls.hCursor, wndcls.hbrBackground, hIcon);
}
}
return NULL; // just use the default
}
GetIconWndClassº¯Êý½«µ÷ÓÃCMainFrame::PreCreateWindow(CREATESTRUCT& cs)À´¿´¿´Ó¦ÓóÌÐòÊÇ·ñÐÞ¸ÄÁËCREATESTRUCT½á¹¹µÄÓò³ÉÔ±¡£CMainFrame::PreCreateWindowµ÷Óà CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs)£¬ºóÕߵĴúÂëÈçÏÂ:
BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs)//in winmdi.cpp
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG));
cs.lpszClass = _afxWndMDIFrame;
}
return TRUE;
}
MFC½«ÎªÓ¦ÓóÌÐò×¢²áAFX_WNDMDIFRAME_REGÔ¤¶¨Òå´°¿ÚÀ࣬²¢ÉèÖÃcs.lpszClass = _afxWndMDIFrame¡£
ÔÚÓ¦ÓóÌÐòµÄ´úÂëÖÐÎÒ¸ü¸ÄÁËcs½á¹¹£º
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CMDIFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: ÔÚ´Ë´¦Í¨¹ýÐÞ¸Ä CREATESTRUCT cs À´Ð޸Ĵ°¿ÚÀà»ò
// Ñùʽ
cs.dwExStyle=~WS_EX_CLIENTEDGE;
return TRUE;
}
CMainFrame::PreCreateWindow·µ»Øºó£¬GetIconWndClassº¯Êýµ÷ÓÃGetClassInfoº¯ÊýÖØÐÂÊÕ¼¯csÐÅÏ¢£¨´ËʱµÄÐÅÏ¢ÒÑÊǸü¸ÄºóµÄÁË)£¬²¢µ÷ÓÃAfxRegisterWndClassº¯ÊýÖØÐÂ×¢²á¸Ã´°¿ÚÀࣨ´Ë´°¿ÚÀàΪ¸ÃÓ¦ÓóÌÐòµÄÕýʽ´°¿ÚÀࣩ¡£µ½´ËΪֹ´°¿ÚÀà×¢²áÍê±Ï£¬ÒÔºó³ÌÐò»¹»áµ÷ÓÃÒ»´ÎCMainFrame::PreCreateWindow£¬²»¹ýÄÇ´ËÖ»ÊÇ"¹ýÃŲ»Èç"¶øÒÑ¡£
/////////////////////////////////////////////////
/* 4.2Ö÷¿ò¼Ü´°¿Ú´´½¨¿ªÊ¼ */
/////////////////////////////////////////////////
¿ªÊ¼½øÈë´´½¨¿ò¼Ü´°¿ÚµÄʵÖʽ׶Ρ£¿´LoadFrameº¯Êý×öÁËʲô?ÔÀ´Ëüµ÷ÓÃÁËCreateº¯Êý¡£
×¢ÊÍ1: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcwinfrm.cpp
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.
");
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.
");
if (hMenu != NULL)
DestroyMenu(hMenu);
return FALSE;
}
return TRUE;
}
¼òµ¥µØËµCFrameWnd::Createº¯Êýµ÷ÓÃÁË»ùÀàµÄCWnd::CreateEx£»
×¢ÊÍ2: ÒÔϺ¯Êý¶¨ÒåÔÚ£º..Visual Studio.NETvc7atlmfcsrcmfcwincore.cpp
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);
...//
return TRUE;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CMDIFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: ÔÚ´Ë´¦Í¨¹ýÐÞ¸Ä CREATESTRUCT cs À´Ð޸Ĵ°¿ÚÀà»ò
// Ñùʽ
cs.dwExStyle=~WS_EX_CLIENTEDGE;
return TRUE;
}
BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG));
cs.lpszClass = _afxWndMDIFrame;
}
return TRUE;
}
CWnd::CreateExµ÷ÓÃÁËCMainFrame::PreCreateWindow£¬µ«´Ë´ÎAfxDeferRegisterClass½«²»»á±»µ÷Óá£Ò²¾ÍÊÇÎÒÉÏÃæËù˵µÄ¡°¹ýÃŲ»È롱¡£
CWnd::CreateExº¯Êý»¹µ÷ÓÃÁËAfxHookWindowCreate(this);ºóÕßÊǸÉʲôµÄÄØ£¿ÆäʵËüÓëÏûÏ¢Ó³ÉäºÍÃüÁî´«µÝÓйأ¬ÎÒ½«ÔÚMFC¼¼ÊõÄÚĻϵÁÐÖ®£¨ËÄ£©--¡¶MFCÏûÏ¢Ó³ÉäÓëÏûÏ¢´«µÝÄÚÄ»¡·Ò»ÎÄÖÐÏê½â¡£
CWnd::CreateExµ÷ÓÃWin32API ::CreateWindowExº¯Êý£¨´«Í³µÄWin32API³ÌÐòÔ±Ò»¶¨²»Ä°ÉúÕâ¸öº¯Êý£©£¬
¾ÍÕâÑùÖ÷¿ò¼Ü´°¿Ú´´½¨½áÊø¡£
//////////////////////////////////////////////
/* 5.±ê×¼Íâ¿ÇÃüÁî½âÎö */
///////////////////////////////////////////////
MFCÏòµ¼ÖÆ×÷µÄ±ê×¼MDIÓ¦ÓóÌÐòÆô¶¯Ê±£¬Ó¦ÓóÌÐò»á×Ô¶¯Æô¶¯Ò»¸ö×Ó´°¿Ú¿ò¼Ü£¨Êµ¼ÊÉÏÊÇÒ»Ì×ÎĵµÄ£°å£©£¬ÕâÊÇΪºÎÄØ£¿ÏÂÃæÎÒ½«Ïêϸ½²½âÒ»ÏÂÕâ¸ö´´½¨¹ý³Ì.
ÆäʵÕâÒ»¹ý³ÌÒ²ÊÇÔÚCMyWinApp::InitInstance()º¯ÊýÖÐÍê³ÉµÄ£¬¿´¿´ÏÂÃæ´úÂ룺
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
º¯ÊýÊ×ÏÈʵÀý»¯Ò»¸öCCommandLineInfoÀà¶ÔÏócmdInfo£¬ÈÃÎÒÃÇ¿´¿´CCommandLineInfoÊǸöʲô¶«¶«?
//in afxwin.h
class CCommandLineInfo : public CObject//²¿·ÖÔ´´úÂë
{
public:
// Sets default values
CCommandLineInfo();
...//
BOOL m_bShowSplash;
BOOL m_bRunEmbedded;
BOOL m_bRunAutomated;
enum { FileNew, FileOpen, FilePrint, FilePrintTo, FileDDE, AppRegister,
AppUnregister, FileNothing = -1 } m_nShellCommand;
// not valid for FileNew
CString m_strFileName;
// valid only for FilePrintTo
CString m_strPrinterName;
CString m_strDriverName;
CString m_strPortName;
~CCommandLineInfo();
// Implementation
...//
};
ÔÙÈÃÎÒÃÇÀ´¿´¿´ËüµÄ¹¹Ô캯ÊýµÄʵÏÖ£º
//in appcore.cpp
CCommandLineInfo::CCommandLineInfo()
{
m_bShowSplash = TRUE;
m_bRunEmbedded = FALSE;
m_bRunAutomated = FALSE;
m_nShellCommand = FileNew;
}
m_nShellCommand = FileNew;ÕâÒ»¾ä¶ÔÎÒÃÇ×îÖØÒª£»ÖÁÓÚCWinApp::ParseCommandLineÎÒÏëÓÃMFCÎĵµÖеÄÒ»¾ä»°À´½âÊÍ£º
Call this member function to parse the command line and send the parameters, one at a time, to CCommandLineInfo::ParseParam.
ÏÂÃæÎÒÃÇÀ´¿´¿´Íâ¿ÇÃüÁî½âÎöµÄÖ÷½Ç£ºCWinApp::ProcessShellCommand
//in appui2.cpp
//DDE and ShellExecute support
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)//²¿·ÖÔ´´úÂë
{
BOOL bResult = TRUE;
switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))
OnFileNew();
if (m_pMainWnd == NULL)
bResult = FALSE;
break;
// If we've been asked to open a file, call OpenDocumentFile()
case CCommandLineInfo::FileOpen:
if (!OpenDocumentFile(rCmdInfo.m_strFileName))
bResult = FALSE;
break;
case CCommandLineInfo::FilePrintTo:
case CCommandLineInfo::FilePrint:
...//
case CCommandLineInfo::FileDDE:
...//
case CCommandLineInfo::AppRegister:
...//
case CCommandLineInfo::AppUnregister:
...//
}
return bResult;
}
ÍÚ¾òÔ´´úÂëµÄÈ·ÊÇÁ˽âMFCÔËÐÐÄÚÄ»µÄ×îºÃÊֶΣ¬´ó¼ÒÒ»¿´Ô´´úÂë±ãÖªµÀÈçÖ®ºÎÁË¡£CCommandLineInfo¹¹Ô캯ÊýÖÐm_nShellCommand = FileNew;ËùÒÔÔÚProcessShellCommandÖжÔÓ¦µÄ´úÂë×ÔÈ»¾ÍһĿÁËÈ»ÁË£ºCWinApp::OnFileNew()±»µ÷ÓÃÁË¡£
//////////////////////////////////////////////////
/* 6.Ò»Ì×Îĵµ/ÊÓͼ¼´½«µ®Éú */
//////////////////////////////////////////////////
ÉÏÎÄ˵CWinApp::OnFileNew()±»µ÷ÓÃÁË£¬ÄÇô¾ÍÈÃÎÒÀ´¿´¿´Æä´úÂë°É£¡
//in appdlg.cpp
void CWinApp::OnFileNew()
{
if (m_pDocManager != NULL)
m_pDocManager->OnFileNew();
}
//in docmgr.cpp
void CDocManager::OnFileNew()//²¿·ÖÔ´´úÂë
{
...//
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
}
//in docmulti.cpp
CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)//²¿·ÖÔ´´úÂë
{
CDocument* pDocument = CreateNewDocument();
...//
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 (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, "CDocument::OnNewDocument returned FALSE.
");
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, "CDocument::OnOpenDocument returned FALSE.
");
pFrame->DestroyWindow();
return NULL;
}
pDocument->SetPathName(lpszPathName);
}
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}
//////////////////////////////////////////////
/* 6.1.×ÓÎĵµ¶¯Ì¬Éú³É */
//////////////////////////////////////////////
CMultiDocTemplate::OpenDocumentFileµ÷ÓÃÁËCreateNewDocument()£¬Õâ¾ÍÊÇ×ÓÎĵµ¶¯Ì¬Éú³ÉµÄÖ÷º¯Êý¡£
//in doctempl.cpp
CDocument* CDocTemplate::CreateNewDocument()//²¿·ÖÔ´´úÂë
{
// default implementation constructs one from CRuntimeClass
...//
CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
...//
AddDocument(pDocument);//½«¶¯Ì¬Éú³ÉµÄÎĵµ¶ÔÏóµÄÖ¸Õë¼ÓÈëµ½Ó¦ÓóÌÐòµÄÎĵµÁбíÖÐ
return pDocument;
}
CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject()£»ÕâÒ»¾ä¾ÍÊǶ¯Ì¬²úÉúµÄºËÐÄ£¬Ëü½èÖúÓÚCRuntimeClass¶¯Ì¬Éú³ÉÒ»¸öCDocument¶ÔÏó¡£Æä¶¯Ì¬Éú³ÉµÄ°ÂÃØÎÒ½«ÔÚMFC¼¼ÊõÄÚĻϵÁÐÖ®£¨Èý£©---
¡¶MFCÖ´ÐÐÆÚÀàÐÍʶ±ðÓ붯̬´´½¨¼¼ÊõÄÚÄ»¡·Ò»ÎÄÖÐÏê½â¡£
//////////////////////////////////////////////////
/* 6.2.×Ó´°¿Ú¿ò¼Ü¶¯Ì¬Éú³É */
/////////////////////////////////////////////////
CMultiDocTemplate::OpenDocumentFileµ÷ÓÃÁËCreateNewFrame£¬Õâ¾ÍÊÇ×Ó´°¿Ú¿ò¼Ü¶¯Ì¬Éú³ÉµÄÖ÷º¯Êý¡£
// Default frame creation
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;
context.m_pCurrentDoc = pDoc;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
...//
CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
if (pFrame == NULL)
{
TRACE(traceAppMsg, 0, "Warning: Dynamic create of frame %hs failed.
",
m_pFrameClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CFrameWnd, pFrame);
...//
// create new from resource
if (!pFrame->LoadFrame(m_nIDResource,
WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, // default frame styles
NULL, &context))
{
TRACE(traceAppMsg, 0, "Warning: CDocTemplate couldn't create a frame.
");
// frame will be deleted in PostNcDestroy cleanup
return NULL;
}
// it worked !
return pFrame;
}
CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();ÕâÒ»¾ä¾ÍÊǶ¯Ì¬²úÉúµÄºËÐÄ£¬Ëü½èÖúÓÚCRuntimeClass¶¯Ì¬Éú³ÉÒ»¸öCDocument¶ÔÏó¡£Æä¶¯Ì¬Éú³ÉµÄ°ÂÃØÎÒ½«ÔÚMFC¼¼ÊõÄÚĻϵÁÐÖ®£¨Èý£©---
¡¶MFCÖ´ÐÐÆÚÀàÐÍʶ±ðÓ붯̬´´½¨¼¼ÊõÄÚÄ»¡·Ò»ÎÄÖÐÏê½â¡£Ö®ºóº¯Êýµ÷ÓÃLoadFrameÀ´´´½¨×Ó´°¿Ú¡£Æä¹ý³ÌÓë´´½¨Ö÷¿ò¼Ü´°¿ÚµÄ¹ý³Ì´óÖÂÏàͬ£¬µ«Ò²ÓÐһЩ²»Í¬µÄµØ·½£¬ÏÂÃæÎҾͽ«ËµËµÕâµã²»Í¬¡£
//////////////////////////////////////////////
/* 6.3.×ÓÊÓͼ¶¯Ì¬Éú³É */
//////////////////////////////////////////////
µÉ´óÑÛ¾¦×Ðϸ²ì¿´OpenDocumentFileµÄÔ´´úÂ룬ÒÉ»óÁË,"ÔõôûÓÐÀàËÆCView* pView =CreateNewView();
µÄ´úÂë?","ÄÇô×ÓÊÓͼÊÇÈçºÎÉú³ÉµÄÄØ"ÏÂÃæÎÒ¾ÍΪÄãÏêϸ½âÊÍһϰɣ¡Æäʵ×ÓÊÓͼ¶¯Ì¬Éú³Éº¯Êý±»·Åµ½ÁíÒ»¸öµØ·½ÁË¡£ÈÃÎÒÃÇÏêϸÀ´¿´¿´°É¡£
Æäʵ£¬¹Ø¼ü»¹ÊÇÔÚLoadFrame£¬µ«Óë´´½¨Ö÷´°¿Ú¿ò¼ÜµÄÄǸöLoadFrame²»Í¬µÄÊÇ´«½øÁËÒ»¸ö²»Í¬µÄ²ÎÊý
&context£¬Äã»Ø¹ýÍ·¿´¿´Ö÷´°¿Ú¿ò¼ÜµÄÄǸöLoadFrame£¬µ÷ÓÃËüʱʹÓÃÁËĬÈϲÎÊý£¬¶øÄǸöĬÈϲÎÊýֵΪNULL,
ÏÂÃæ¿´¿´CCreateContext ½á¹¹¡£
//in afxext.h
struct CCreateContext // Creation information structure
// All fields are optional and may be NULL
{
// for creating new views
CRuntimeClass* m_pNewViewClass; // runtime class of view to create or NULL
CDocument* m_pCurrentDoc;
// for creating MDI children (CMDIChildWnd::LoadFrame)
CDocTemplate* m_pNewDocTemplate;
// for sharing view/frame state from the original view/frame
CView* m_pLastView;
CFrameWnd* m_pCurrentFrame;
// Implementation
CCreateContext();
};
¶øÔÚCDocTemplate::CreateNewFrameÖгõʼ»¯Á˸ýṹÈçÏ£º
CCreateContext context;
context.m_pCurrentFrame = pOther;
context.m_pCurrentDoc = pDoc;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
context.m_pNewViewClass = m_pViewClass;//¹Ø¼üµÄ³ÉÔ±
ÏÂÃæ¿´¿´Õâ¸ö´´½¨µÄ¾ßÌå¹ý³Ì£º
LoadFrame(...,&context)-->CFrameWnd::Create(...,&context)--> CWnd::CreateEx(...,&context)
-->::CreateWindowEx
::CreateWindowEx APIº¯Êý½«²úÉúWM_CREATEÏûÏ¢£¬²¢½«&context´«µÝÖ®,CMainFrame::OnCreate½«ÏìÓ¦ÏûÏ¢,²¢ÒýÆðһϵÁеĺ¯Êýµ÷Ó㬿´ÏÂÃæ:
//in mainfrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
...//
return 0;
}
// in winfrm.cpp
int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs)
{
CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;
return OnCreateHelper(lpcs, pContext);
}
// in winfrm.cpp
int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext)//²¿·ÖÔ´´úÂë
{
if (CWnd::OnCreate(lpcs) == -1)
return -1;
// create special children first
if (!OnCreateClient(lpcs, pContext))
{
TRACE(traceAppMsg, 0, "Failed to create client pane/view for frame.
");
return -1;
}
...//
return 0; // create ok
}
// in winfrm.cpp
BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
{
// default create client will create a view if asked for it
if (pContext != NULL && pContext->m_pNewViewClass != NULL)
{
if (CreateView(pContext, AFX_IDW_PANE_FIRST) == NULL)
return FALSE;
}
return TRUE;
}
// in winfrm.cpp
CWnd* CFrameWnd::CreateView(CCreateContext* pContext, UINT nID)//²¿·ÖÔ´´úÂë
{
...//
// Note: can be a CWnd with PostNcDestroy self cleanup
CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
if (pView == NULL)
{
TRACE(traceAppMsg, 0, "Warning: Dynamic create of view type %hs failed.
",
pContext->m_pNewViewClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CWnd, pView);
// views are always created with a border!
if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0,0,0,0), this, nID, pContext))
{
TRACE(traceAppMsg, 0, "Warning: could not create view for frame.
");
return NULL; // can't continue without a view
}
...//
return pView;
}
CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();ºËÐĺ¯ÊýÖÕÓÚ³öÏÖÁË¡£×ÓÊÓͼ¶¯Ì¬Éú³ÉÍê±Ï¡£
/////////////////////////////////////////
/* 7.ÊÕβ¹¤×÷ */
/////////////////////////////////////////
ÖÁ´Ë£¬Ò»Ì×ÍêÕûµÄDocument/ChildFrame/View½á¹¹Éú³É,´Ë¡°Èý¿Ú×顱¹²ÊôͬһÌ×ÎĵµÄ£°å£¬Èç¹ûÄãÒª¶¨ÒåÁíÒ»Ìײ»Í¬µÄÎĵµÄ£µµÐèÔÙ¶¨ÒåÁíÒ»×鲻ͬ¡°Èý¿Ú×顱£¨ChildFrame¿ÉÒÔʹÓÃÏàͬµÄ£©¡£²¢µ÷ÓÃAddDocTemplate½«¸ÃÎĵµÄ£°å¼ÓÈëµ½Ó¦ÓóÌÐòµÄÎĵµÄ£°åÁÐ±í¡£±ÈÈ磺
CMultiDocTemplate* pOtherDocTemplate;
pOtherDocTemplate = new CMultiDocTemplate(IDR_MyOtherTYPE,
RUNTIME_CLASS(CMyOtherDoc),
RUNTIME_CLASS(CChildFrame), // ×Ô¶¨Òå MDI ×Ó¿ò¼Ü
RUNTIME_CLASS(CMyOtherView));
AddDocTemplate(pOtherDocTemplate);
¡°Èý¿Ú×顱Éú³Éºó³ÌÐòµ÷ÓÃShowWindow£¬UpdateWindow½«Ó¦ÓóÌÐòµÄÖ÷´°¿ÚÕ¹ÏÖÔÚÄãÑÛǰ¡£
×¢ÊÍ:µ±ÄãÔÚFile²Ëµ¥ÖÐÑ¡Ôñnew»òÔÚ¹¤¾ßÀ¸Öе¥»÷¡°Ð½¨¡±Ê±£¬Ó¦ÓóÌÐò½«Ñ¡Ôñµ±Ç°Ä¬ÈϵÄÎĵµÄ£°å²¢ÒÔËüΪ»ù´¡¶¯Ì¬Éú³É Document/ChildFrame/View¡°Èý¿Ú×顱£¬ÆäÉú³É¹ý³ÌÓëÎÒÉÏÊö½²µÄÒ»°ã²»¶þ¡£
////////////////////////////////////////
/* 8. "ϼ¯Ô¤¸æ" */
////////////////////////////////////////
MFC¼¼ÊõÄÚĻϵÁÐÖ®£¨Èý£©---¡¶MFCÖ´ÐÐÆÚÀàÐÍʶ±ðÓ붯̬´´½¨¼¼ÊõÄÚÄ»¡·