zoukankan      html  css  js  c++  java
  • MFC之CCommandLineInfo

    CCommandLineInfo类

    CObject

    └CCommandLineInfo

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

    首先 我们来看一下

     

    //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;

    --------------------------------------------------------------

    类CCommandLineInfo用于分析启动应用时的命令行参数。
    MFC应用一般都会在它的应用对象中使用函数InitInstance创建这个类的一个本地实例。然后把该对象传给CWinApp::ParseCommandLine,ParseCommandLine又重复调用ParseParam填充CCommandLineInfo对象。最后,CCommandLineInfo对象被传给CWinApp::ProcessShellCommand来处理命令行参数和选项。
    类CCommandLineInfo可以用来封装以下的命令行选项和参数:

    命令行参数 执行的命令
    app      建立新文件
    app       文件名 打开文件
    app /p   文件名 在缺省打印机上打印文件
    app /pt   文件名 打印机 驱动程序 打印端口 在指定的打印机上打印文件
    app /dde   启动程序并等待DDE命令
    app /Automation 启动为一个OLE自动服务器
    app /Embedding 启动来编辑嵌入的OLE项
    要处理其它的选项,可以从类CCommandLineInfo派生一个子类,然后覆盖函数ParseParam进行相应的处理。


    CWinApp::ParseCommandLine

    void ParseCommandLine( CCommandLineInfo& rCmdInfo );

    参数:

    rCmdInfo 对CCommandLineInfo对象的引用。

    说明:
    调用这个函数以解析命令行并将参数发送到CCommandLineInfo::ParseParam,每次一个。
    当你通过AppWizard开始一个新的MFC项目时,AppWizard将会创建一个Ccommand-LineInfo的本地实例,然后在InitInstance成员函数中调用ProcessShellCommand 和 ParseCommandLine。命令行的过程描述如下:
    1.在InitInstance中被创建之后,CCommandLineInfo对象被传递给ParseCommandLine。
    2.随后ParseCommandLine反复调用CCommandLineInfo::ParseParam,每次解析出一个参数。
    3.ParseParam填充CCommandLineInfo对象,随后该对象被传递给ProcessShellCommand。
    4.ProcessShellCommand处理命令行参数和标志。
    注意:
    如果需要的话,你可以直接调用ParseCommandLine。
    有关命令行标志的描述参见CCommandLineInfo::m_nShellCommand。

    CWinApp::ProcessShellCommand

    BOOL ProcessShellCommand( CCommandLineInfo& rCmdInfo );

    返回值:如果成功地处理了外壳命令,则返回非零值。如果InitInstance返回了FALSE,则返回0。

    参数:

    rCmdInfo 对CCommandLineInfo对象的引用。

    说明:
    这个成员函数被InitInstance调用,用以接收rCmdInfo所标识的CCommandLineInfo对象传递的参数,并执行指定的动作。
    当你通过AppWizard开始一个MFC的新项目时,AppWizard将创建CCommandLineInfo的一个本地实例,然后在InitInstance成员函数中调用ProcessShellCommand和ParseCommandLine。命令行按照下面描述的路线传递:
    1.在InitInstance中被创建以后,CCommandLineInfo对象将它传递给ParseCommand-Line。
    2.随后ParseCommandLine反复调用CCommandLineInfo::ParseParam,每次解析一个参数。
    3.ParseParam填充CCommandLineInfo对象,然后将之传递给ProcessShellCommand。
    4.ProcessShellCommand处理命令行参数和标志。
    CCommandLineInfo对象中用CCommandLineInfo::m_nShellCommand标识的数据成员属于下面的枚举类型,它在CCommandLineInfo类中定义。
    enum{ FileNew,FileOpen,FilePrint,FilePrintTo,FileDDE,};


    CCommandLineInfo类的成员
    构造函数

    CCommandLineInfo 构造一个缺省的CCommandLineInfo对象

    操作
    ParseParam 可以覆盖这个回调函数以分析命令行参数

    数据成员
    m_bShowSplash 指明是否显示飞溅型的屏幕
    m_bRunEmbedded 指明是否在命令行找到了/Embedding选项
    m_bRunAutomated 指明是否在命令行找到了/Automation选项
    m_nShellCommand 要执行的命令
    m_strFileName 待打开或打印的文件名,在命令为New或DDE时为空
    m_strPrinterName 命令为Print To时指明打印机名;否则为空
    m_strDriverName 命令为Print To时指明驱动程序名;否则为空
    m_strPortName 命令为Print To时指明打印端口名;否则为空 

    示例:

    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);


    ————————————————


  • 相关阅读:
    VS 2008潜在强大的功能:提取EXE文件中的ICO等资源
    园友们注意:淘宝网上QQ会员 4钻 3元 等都为骗子行为
    Comet Async Process Request Handler
    WCF(Sender) to MSMQ to WCF(Receiver)
    ASP.NET Web Form GridView DetailsView Query Edit
    WCF NetTcp AsyncQueue Service
    Xml CDATA 序列化
    Sync Invoke Remoting Async Invoke
    .Net 4.0 Remoting ConcurrentQueue
    Socket Async Receive Data to LinkedList Buffer (telnet proxy server)
  • 原文地址:https://www.cnblogs.com/rosesmall/p/14785416.html
Copyright © 2011-2022 走看看