zoukankan      html  css  js  c++  java
  • CCommandLineInfo类

    ##

    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 = -1 } 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 = 1; 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 + 1) == __argc); //参数是否是最后一个
             if (pszParam[0] == '-' || pszParam[0] == '/') //是否有-或'/'? 并过滤
             {
                 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") == 0)
             m_nShellCommand = FilePrintTo;
         else if (lstrcmpA(pszParam, "p") == 0)
             m_nShellCommand = FilePrint;
         else if (lstrcmpiA(pszParam, "Unregister") == 0 ||
                 lstrcmpiA(pszParam, "Unregserver") == 0)
             m_nShellCommand = AppUnregister;
         else if (lstrcmpA(pszParam, "dde") == 0)
         {
             AfxOleSetUserCtrl(FALSE);
             m_nShellCommand = FileDDE;
         }
         else if (lstrcmpiA(pszParam, "Embedding") == 0)
         {
             AfxOleSetUserCtrl(FALSE);
             m_bRunEmbedded = TRUE;
             m_bShowSplash = FALSE;
         }
         else if (lstrcmpiA(pszParam, "Automation") == 0)
         {
             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, 0, 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;

  • 相关阅读:
    c#自动更新+安装程序的制作
    VS2013项目受源代码管理向源代码管理注册此项目时出错
    WinDbg配置和使用基础
    InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET程序)
    PowerDesigner 如何生成数据库更新脚本
    用户故事(User Story)
    Troubleshooting Record and Playback issues in Coded UI Test
    Coded UI
    compare two oracle database schemas
    How to: Use Schema Compare to Compare Different Database Definitions
  • 原文地址:https://www.cnblogs.com/tinaluo/p/7850604.html
Copyright © 2011-2022 走看看