##

CCommandLineInfo cmdInfo;//定义命令行
ParseCommandLine(cmdInfo);//解析命令行
// 调度在命令行中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
if (!ProcessShellCommand(cmdInfo)) //程序启动时创建新文档
return FALSE;
m_pMainWnd->ShowWindow(SW_SHOW);// 唯一的一个窗口已初始化,因此显示它并对其进行更新
m_pMainWnd->UpdateWindow();

这几行代码是程序启动时创建新文档的关键代码 .

1: 我们首先来看看让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 = - } m_nShellCommand;
// not valid for FileNew
CString m_strFileName;
. . .
~CCommandLineInfo();
. . .
};

这里要重点注意enum {FileNew, . . . , FileNothing = -1 }m_nShellCommand;
这里联合类型定义的m_nShellCommand就是外壳程序执行的命令类型
如果m_nShellCommand设置为FileNew ,那么程序就会创建新文档 .
如果想在文档开始时不创建新文档 , 就必须将m_nShellCommand设置为FilleNothing

下面我们再看看CCommandLineInfo的构造函数 .

//in appcore.cpp
CCommandLineInfo::CCommandLineInfo()
{
m_bShowSplash = TRUE;
m_bRunEmbedded = FALSE;
m_bRunAutomated = FALSE;
m_nShellCommand = FileNew;
}

这里很明白的看出 , 构造函数中 , 缺省将 m_nShellCommand设置为 FileNew .

2:再来看看ParseCommandLine(cmdInfo)函数

void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo)
{
for (int i = ; i < __argc; i++) // extern int __argc;
{
LPCTSTR pszParam = __targv[i]; //extern char ** __argv;
extern wchar_t ** __wargv;
difine __targv __wargv
BOOL bFlag = FALSE;
BOOL bLast = ((i + ) == __argc); //参数是否是最后一个
if (pszParam[] == '-' || pszParam[] == '/') //是否有-或'/'? 并过滤
{
bFlag = TRUE;
++pszParam;
}
rCmdInfo.ParseParam(pszParam, bFlag, bLast);
}
}

可以看出ParseCommandLine主要是对输入的命令行参数做一些分析 , 并调用ParseParam来进行处理 .继续分析 ParseParam函数 , 查看如下源代码:

void CCommandLineInfo::ParseParam(const TCHAR* pszParam,BOOL bFlag,BOOL bLast)
{
if (bFlag)
{
USES_CONVERSION;
ParseParamFlag(T2CA(pszParam));
}
else
ParseParamNotFlag(pszParam);
ParseLast(bLast);
}

其它的函数撇开不看 , 我们重点来分析一下ParseParamFlag()和ParseLast()函数 .

void CCommandLineInfo::ParseParamFlag(const char* pszParam)
{
// OLE command switches are case insensitive, while
// shell command switches are case sensitive
if (lstrcmpA(pszParam, "pt") == )
m_nShellCommand = FilePrintTo;
else if (lstrcmpA(pszParam, "p") == )
m_nShellCommand = FilePrint;
else if (lstrcmpiA(pszParam, "Unregister") == ||
lstrcmpiA(pszParam, "Unregserver") == )
m_nShellCommand = AppUnregister;
else if (lstrcmpA(pszParam, "dde") == )
{
AfxOleSetUserCtrl(FALSE);
m_nShellCommand = FileDDE;
}
else if (lstrcmpiA(pszParam, "Embedding") == )
{
AfxOleSetUserCtrl(FALSE);
m_bRunEmbedded = TRUE;
m_bShowSplash = FALSE;
}
else if (lstrcmpiA(pszParam, "Automation") == )
{
AfxOleSetUserCtrl(FALSE);
m_bRunAutomated = TRUE;
m_bShowSplash = FALSE;
}
}

ParseParamFlag判断传过来的字符串 ,判断它的参数类型 , 并根据参数类型做不同的处理 .

//ParseLast会判断是否是是FileNew打开新文档 , 如果是打开新文档 , 并且打开的文档名不为空的话, 就假定用户想打开这个文档 , 把命令设置为FileOpen .
void CCommandLineInfo::ParseLast(BOOL bLast)
{
if (bLast)
{
if (m_nShellCommand == FileNew && !m_strFileName.IsEmpty())
m_nShellCommand = FileOpen;
m_bShowSplash = !m_bRunEmbedded && !m_bRunAutomated;
}
}

最后 , 我们可以总结一下ParseCommandLine的作用 . ParseCommandLine的作用主要是分析命令行参数,如果没有命令行参数,ParseCommandLine()就假定用户想新建一个文档,于是设置一个FileNew命令,如果命令行参数中有一个文件名,ParseCommandLine()就假定用户想打开该文件,于是设置一个FileOpen命令。

3: 最后 , 我们来重点看看外壳命令解析的主角 : ProcessShellCommand ();(部分源代码)

BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)
{
BOOL bResult = TRUE;
switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, , NULL, NULL))
OnFileNew();
if (m_pMainWnd == NULL)
bResult = FALSE;
break;
case CCommandLineInfo::FileOpen: . . .
case CCommandLineInfo::FilePrintTo: . . .
case CCommandLineInfo::FilePrint: . . .
case CCommandLineInfo::FileDDE: . . .
case CCommandLineInfo::AppRegister: . . .
case CCommandLineInfo::AppUnregister: . . .
. . .
}
}

代码看到这里 , 一切都很明白了 . ProcessShellCommand分析m_nShellCommand ,并根据m_nShellCommand不同的类型值进行不同的处理 .
再来分析下面两行代码:

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
  • 当CCommandLineInfo cmdInfo进行定义时 , 首先调用构造函数 , 构造函数中m_nShellCommand被设置为FileNew
  • 然后执行ParseCommandLine(cmdInfo);对命令进行分析 .
  • 最后执行ProcessShellCommand (cmdInfo) , ProcessShellCommand ()判断m_nShellCommand为FileNew , 于是调用OnFileNew()创建了一个新的文档 .

这也就是创建新文档的来龙去脉 .

最后, 我们看怎么样解决不想在应用程序启动时的创建新文档的问题:

直接在InitInstance()函数中用如下代码代替原来的几行即可:

CCommandLineInfo cmdInfo;
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
ParseCommandLine(cmdInfo);
       if (!ProcessShellCommand(cmdInfo)) return FALSE;

CCommandLineInfo类的更多相关文章

  1. MFC命令行及CCommandLineInfo类

    获取命令行的方法: 1.GetCommandLine() 获取输入的所有信息,包括程序所在路径及参数 2.AfxGetApp()->m_lpCmdLine 只包含参数 一般情况下,获取到命令行后 ...

  2. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  3. MFC的命令行

    一个程序,我们通过输入不同的命令行参数,就可以实现一个可执行文件,多种功能,通过命令行来控制它的行为,例如,我们在控制台的时候,就是遇到最多的,如一个exe程序,加入为test..exe,我们可以设置 ...

  4. MFC中SDI程序创建流程的回顾

    SDI程序创建流程的回顾 从CWinApp.InitialInstance()开始, 1.首先应用程序对象创建文档模板; CSingleDocTemplate* pDocTemplate; pDocT ...

  5. MFC中小笔记(二)

    6.有三个API函数可以运行可执行文件WinExec.ShellExecute和CreateProcess.  关于这三者的概述总结,有好几篇,自己选择. 1.CreateProcess因为使用复杂, ...

  6. MFC中获取命令行参数的几种方法

    在MFC程序中,可以用以下几种方法来获取命令行参数. 为方便说明,我们假设执行了命令:C:\test\app.exe -1 -2 方法一 ::GetCommandLine(); 将获取到 " ...

  7. MFC类目录及头文件(转)

    类 描述 头文件 CAnimateCtrl 自动化通用控件 afxcmn.h CArchive afx.h CArchiveException afx.h CArray afxtempl.h CAsy ...

  8. Visual C++中最常用的类与API函数

    这篇文章能让初学者快速了解visual C++ MFC中常见的核心的类与函数,虽然全部看下来有点枯燥,但对初学者快速了解MFC的框架结构很有好处. 常用类 CArchive类:用于二进制保存档案 CB ...

  9. C++ 可配置的类工厂

    项目中常用到工厂模式,工厂模式可以把创建对象的具体细节封装到Create函数中,减少重复代码,增强可读和可维护性.传统的工厂实现如下: class Widget { public: virtual i ...

随机推荐

  1. chorem浏览器无法下载

    下载的时候指定字节的长度 context.Response.AddHeader("Content-Length", bytes.Length.ToString()); contex ...

  2. Windows 获取unix timestamp

    #include <stdio.h> #include <time.h> int main(){ SYSTEMTIME lpSysTime; GetLocalTime(& ...

  3. Linux 任务管理 && 常用指令

    A.linux死机 转自:https://www.deleak.com/blog/2010/10/20/sysrq/ linux死机了怎么办? 曾经啊,对着键盘上 Print Screen/SysRq ...

  4. 如何提高php应用的性能?

    1. 如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍.2.$row[’id’] 的速度是$row[id]的7倍.3.echo 比 print快,并且使用echo的 ...

  5. 10.Mysql索引

    10.索引的设计和使用10.1 索引概述BTREE索引:Mysql(MyIASM和Innodb)默认的索引类型.前缀索引:对索引字段的前N个字符创建索引.N的最大取值和存储引擎有关,MyIASM支持最 ...

  6. (转)Java程序员简历模板

    本简历模板由国内首家互联网人才拍卖网站「 JobDeer.com 」提供. (括号里的是我们的顾问编写的说明,建议在简历书写完成后统一删除) 先讲讲怎样才是一份好的技术简历 首先,一份好的简历不光说明 ...

  7. less 官网讲解 ( http://www.bootcss.com/p/lesscss/ )

    变量 变量允许我们单独定义一系列通用的样式,然后在需要的时候去调用.所以在做全局样式调整的时候我们可能只需要修改几行代码就可以了. // LESS @color: #4D926F; #header { ...

  8. h5 微信分享朋友和朋友圈

    生成JS-SDK权限验证签名 实现发送给朋友和分享到朋友圈时内容参数自定义 一.微信JS-SDK 1. 获得Access Token access token的获得方法在前面有介绍,详情见 微信公众平 ...

  9. 11. pt-heartbeat

    pt-heartbeat [OPTIONS] [DSN] --update|--monitor|--check|--stop ------------------------------------- ...

  10. 用VS2010打开VS2012项目

    1.修改解决方案文件,即.sln文件: 用记事本打开.sln文件,把其中的 Microsoft Visual Studio Solution File, Format Version 12.00 # ...