##

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;

最新文章

  1. C# 闭包问题-你被&rdquo;坑&ldquo;过吗?
  2. Android基础总结(七)
  3. Redis 排行榜 相同分数根据时间优先排行
  4. IOS关于UIViewController之间的切换
  5. php for循环嵌套
  6. vmware centos下配置ip
  7. Win10下E3-1231 V3开启Intel虚拟化技术(vt-x)安装HAXM
  8. Trinity 安装
  9. vs2010 配置OpenGL
  10. Delphi XE5 附破解补丁
  11. 关于git的ssh-key:解决本地多个ssh-key的问题
  12. Android: DrawerLayout 侧滑菜单栏
  13. JavaScript 和 TypeScript 交叉口 —— 类型定义文件(*.d.ts)
  14. [记录]一则清理MySQL大表以释放磁盘空间的案例
  15. Python字符串的操作
  16. 个人jQuery的使用总结
  17. java 命令查字节码文件, 查.class文件内容
  18. git配置代理
  19. sonar——Synchronized classes Vector, Hashtable, Stack and StringBuffer should not be used
  20. DOS的重定向命令及在安全方面的应用

热门文章

  1. cell设置背景颜色为啥不起作用
  2. 如何查看Firefox中保存的登录密码
  3. jsp获取ip使用request.getRemoteAddr返回0:0:0:0:0:0:0:1
  4. 10.9h5日记
  5. 使用clear来清除localStorage保存对象的全部数据
  6. mybatis进阶--输入映射和输出映射
  7. javascript 高级程序设计 十一
  8. javascript 高级程序设计 六
  9. BZOJ 1874 取石子游戏 - SG函数
  10. 深入研究 UCenter API For .NET