一旦用户开始使用多于一个的文档模板对象,MFC就会弹出一个New对话框,让用户选择需要的文档模板类型。当在应用程序的InitInstance()函数中调用AddDocTemplate()来注册多个文档模板对象时,MFC无法知道应该使用哪一个文档模板对象来完成用户的“File->New”请求。因此,MFC弹出一个对话框,该对话框列出了 各种注册过的文档模板对象 以允许用户指出应该使用哪一个来调用CDocTemplate::OpenDocumentFile(),来创建一个新文档,以下MFC的源码,有助于理解这种逻辑:
当应用程序启动时,在InitInstance()中由标准AppWizard生成的代码ProcessShellCommand()将直接调用CWinApp::OnFileNew(),调用顺如下:
应用程序启动时,如果不想弹出对话框(直接用用户希望的 文档模板 创建新的空文档) 供用户选择文档模板,遵循以下步骤:
第一步:在应用程序的InitInstance()函数中创建各种文档模板对象,并把指向每个对象的指针存储在 应用程序类 的成员变量中。
第二步:使用ClassWizard在 应用程序类中 增加“File->New”菜单命令的句柄,在句柄内,从存储的 文档模板对象的指针 中选择你希望的文档模板对象指针,传递一个NULL参数来请求创建一个新(空)文档,如下:
void CTestApp::OnFileNew()
{
m_ptDefaultTemplate->OpenDocumentFile(NULL);
}
上面解决方案第二步时,标准的MFC消息映射机制 能够保证 在用户选择File->New菜单命令时调用自己的句柄( CMyApp::OnFileNew() ),而不是默认的CWinApp::OnFileNew()函数。
上面代码段中的CNewTypeDlg类在其表中只显示那些文档模板资源ID的fileNewName字串不为空的文档模板对象。如果只有一个文档模板对象满足这一条件,那么就自动返回该对象,作为所“选择”的模板对象,而不显示对话框。为了更好的理解这种行为,看一下CNewTypeDlg()的伪代码,程序清单如下:
每次当启动一个标准AppWizard生成的应用程序时,MFC就会自动的创建一个新(空)文档,同时还有关联的视图和框架窗口。你可能会很想知道,这个空文档是在代码的什么位置被创建的。同时,如果在应用程序启动时不初始创建任何文档?
如果不想再在应用程序启动时打开一个新(空)文档应遵循以下步骤:
解释:
从MFC4.0版本开始,在应用程序启动时,程序在何处初始化新文档就不是非常明显了。你可能理解最好要调用CWinApp::OnFileNew(),但是这种调用来自于何处呢?实际上,导致CWinApp::OnFileNew()调用的整个过程都隐藏在这3行代码中:
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);//遍历命令行,搜寻以字符'/'或'-'开头的选项,根据找到的命令行参数,设置cmdInfo对象的成员变量
if(!processShellCommand(cmdInfo))//该函数根据cmdInfo中的m_nShellCommand变量 进行不同的函数调用
return false;
1、以上代码在堆栈中创建了一个名为cmdInfo的CCommandLineInfo对象,MFC将用该对象分析各种转换开关,并把对象的信息存储在该cmdInfo对象的public成员变量中,其中的各种转换开关可能出现在应用程序的命令行中。
CCommandLineInfo类的定义如下:
class CCommandLineInfo
{
//......
enum {FileNew , FileOpen , FilePrint , FilePrintTo , FileDDE , AppUnregistr ,
FileNothing=-1 }m_nShellCommand;
//......
};
2、cmdInfo对象创建时调用该类的(CCommandLineInfo)构造函数,该构造函数初始化m_nShellCommand成员,赋值CCommandLineInfo::FileNew;
3、CWinApp::ParseCommandLine(cmdInfo)函数遍历命令行,搜寻以字符‘/’或 ‘-’开头的选项。对每一个找到的命令行参数
ParseCommandLine()就对CmdInfo对象应用CCommandLineInfo::ParaseParam()方法,该方法根据各种命令行参数设置CmdInfo对象的成员变量,这些参数由PraseCommandLine()传送。只有在命令行中找到实际参数时,才改变m_nShellCommand成员,否则m_nShellCommand保留它上一次的值(即在构造函数中设置的值CCommandLineInfo::FileNew)。
4、CWinApp::ParseCommandLine(cmdInfo)函数返回后CmdInfo对象作为一个参数调用ProcessShellCommand(cmdInfo)函数,该函数执行基于cmdInfo.m_nShellCommand值的相应动作。最常发生的动作如下表所示:
cmdInfo.m_nShellCommand的数值 ProcessShellCommand()进行的函数调用
CCommandLineInfo::FileNew CWinApp::OnFileNew();//这个函数不是虚函数
CCommandLineInfo::FileOpen OpenDocumentFile(cmdInfo.m_strFileName);
CCommandLineInfo::FilePrint m_pMainWnd->SendMessage(WM_COMMAND,
CCommandLineInfo::FilePrintTo ID_FILE_PRINT_DIRECT);
CCommandLineInfo::FileNothing None
因此,可以看出cmdInfo对象的成员变量m_nShellCommand在第2步中,被初始化为了FileNothing,最终导致了ProcessShellCommand()内部调用什么也不做,正好达到了我们的目的。