The CCommandLineInfo class in MFC is used to parse command-line arguments when an app is launched.
MFC applications typically create a local instance of this class using the function InitInstance () in its Application object. The object is then passed to CWinApp::P Arsecommandline (), ParseCommandLine () and repeatedly calls ParseParam () to populate the CCommandLineInfo object. Finally, the CCommandLineInfo object is passed to CWinApp::P Rocessshellcommand () to handle command-line arguments and options. So we'll find the following lines of code in the App class InitInstance () function:
CCommandLineInfo Cmdinfo; ParseCommandLine (cmdinfo);//Dispatch commands specified on the command Lineif (! ProcessShellCommand (Cmdinfo)) return FALSE;
These lines of code are the key code to create a new document when the program starts.
1: Let's start by looking at the structure of the CCommandLineInfo class
In Afxwin.hclass 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_nshellcomm and;//not valid for filenew CString m_strfilename; . . . ~ccommandlineinfo (); . . .};
Here to focus on the enum {filenew, ..., filenothing =-1} m_nshellcommand;
The M_nshellcommand defined by the union type here is the type of command that the shell executes. If M_nshellcommand is set to FileNew, the program creates a new document, and if you want to not create a new document at the beginning of the document, you must set the M_nshellcommand to fillenothing.
Let's look at the CCommandLineInfo constructor:
In Appcore.cppccommandlineinfo::ccommandlineinfo () { M_bshowsplash = TRUE; m_brunembedded = FALSE; m_brunautomated = FALSE; M_nshellcommand = FileNew;}
It is clear here that, in the constructor, the M_nshellcommand is set to FileNew by default.
2: Look again at the ParseCommandLine (cmdinfo) function
void CWinApp::P arsecommandline (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] = = '/') { //Remove flag specifier bflag = TRUE; ++pszparam; } Rcmdinfo.parseparam (Pszparam, Bflag, bLast);} }
It can be seen that parsecommandline () does some parsing on the input command-line parameters and calls ParseParam () to handle it. Continue analyzing the ParseParam () function to see the following source code:
void CCommandLineInfo::P arseparam (const tchar* pszparam,bool bflag,bool bLast) { if (bflag) { Uses_ CONVERSION; Parseparamflag (T2CA (Pszparam)); } else Parseparamnotflag (pszparam); Parselast (bLast);}
Other functions aside, let's focus on analyzing the Parseparamflag () and Parselast () functions.
void CCommandLineInfo::P arseparamflag (const char* Pszparam) {//OLE command switches is case insensitive, while/ /shell command switches is 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 () Judge the passed string, determine its parameter type, and do different processing according to the parameter type.
void CCommandLineInfo::P arselast (BOOL bLast) { if (bLast) { if (M_nshellcommand = FileNew &&!m_ Strfilename.isempty ()) M_nshellcommand = FileOpen; M_bshowsplash =!m_brunembedded &&!m_brunautomated; }}
Parselast () will determine if it is filenew open a new document, if the new document is opened, and if the open document name is not empty, assume that the user wants to open the document and set the command to FileOpen.
Therefore, we can summarize the function parsecommandline () functions: ParseCommandLine () function is mainly to analyze the command line parameters, if there is no command line arguments, ParseCommandLine () assume that the user wants to create a new document, A filenew command is set, and if there is a file name in the command line argument, ParseCommandLine () assumes that the user wants to open the file, and then sets a FileOpen command.
3: Next, let's focus on the main character of shell command parsing: ProcessShellCommand ()
BOOL CWinApp::P rocessshellcommand (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: ... . . . }}
This function returns a value other than 0 if the shell command was successfully processed, otherwise false. Code see here, everything is clear. ProcessShellCommand () analyzes the M_nshellcommand and handles different types of processing based on m_nshellcommand different type values.
4: Finally, let's analyze a few lines of code in the App class InitInstance () function that was originally mentioned in the article.
1) When CCommandLineInfo cmdinfo is defined, the constructor is called first, and the M_nshellcommand in the constructor is set to FileNew;
2) then execute ParseCommandLine (cmdinfo) to analyze the command;
3) Finally call ProcessShellCommand (Cmdinfo) to handle the command line arguments and flags. ProcessShellCommand () determines that M_nshellcommand is filenew, and calls OnFileNew () to create a new document.
This is how the new document is created.
If we want the application to start without opening a blank document by default, you should:
CCommandLineInfo Cmdinfo; ParseCommandLine (Cmdinfo); if (CmdInfo.m_strFileName.IsEmpty ()) {Cmdinfo.m_nshellcommand = CCommandLineInfo:: filenothing;} if (! ProcessShellCommand (Cmdinfo)) return FALSE;
Note: Many of the solutions available online here are
CCommandLineInfo Cmdinfo;cmdinfo.m_nshellcommand = ccommandlineinfo::filenothing; ParseCommandLine (Cmdinfo); if (! ProcessShellCommand (Cmdinfo)) return FALSE;
This behavior may seem to work the same way, but when you invoke the application execution with the command line or the resource manager, you cannot open the document normally. Because regardless of misbehavior the M_nsellcommand set to filenothing.
MFC parsing start command line arguments--ccommandlineinfo class