让MFC程序支持命令行参数
一般情况下,如果我们的VC工程是Console控制台类型或者是Win32类型的情况下,这两类的工程类型比较容易获得命令行参数,即,通过其入口点函数
- int main(int argc, char *argv[])
- int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
但是,如果我们的工程类型是MFC对话框或单文档类型的话,如何让我们的程序支持命令行参数呢?系统没有为我们提供好,那我们只有自己获取了……
一般情况下,需要在MFC程序的主线程初始化函数中进行处理,主线程的初始化函数即:BOOL CProjCleanerApp::InitInstance(),这里面我们假设工程的名字是ProjCleaner,CProjCleanerApp 即主线程类。在 BOOL CProjCleanerApp::InitInstance() 函数中进行程序的初始化以及对话框界面的显示工作,其大致代码如下:
- BOOL CProjCleanerApp::InitInstance()
- {
- //省略的其他代码……;
- CWinApp::InitInstance();
- //省略的其他代码……;
- CProjCleanerDlg dlg; //新建主对话框类型对象;
- m_pMainWnd = &dlg;
- INT_PTR nResponse = dlg.DoModal(); //进行模态对话框的显示;
- if (nResponse == IDOK)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with OK
- }
- else if (nResponse == IDCANCEL)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with Cancel
- }
- return FALSE;
- }
我们要获取程序的命令行参数,一般是在主对话框界面显示之前,即 CProjCleanerDlg dlg; 之前获取。获取的方法主要是调用 GetCommandLine 和 CommandLineToArgvW 函数。
GetCommandLine 函数的原型定义如下:
- LPTSTR WINAPI GetCommandLine(void);
没有参数,返回值是一个LPTSTR类型的字符串指针,即命令行参数的字符串。
默认情况下,每个程序都会有一个命令行参数,即可执行程序本身的路径,第二个参数才是真正的附加命令行参数。举个例子,调用GetCommandLine函数获取到的命令行参数的字符串大致如下:
- "E:/SoftWare/ProjCleaner.exe" "-help"
其中,"E:/SoftWare/ProjCleaner.exe" 为可执行文件的路径,"-help" 为附加的参数。
调用完 GetCommandLine 函数获取到了命令行参数之后,我们就要调用 CommandLineToArgvW 函数去分解得到的命令行参数字符串,CommandLineToArgvW 函数的原型定义如下:
- LPWSTR *CommandLineToArgvW(
- LPCWSTR lpCmdLine,
- int *pNumArgs
- );
他有两个参数,第一个参数 lpCmdLine 即通过 GetCommandLine 函数获取到的命令行参数字符串指针,第二个参数是一个 int 类型的指针,用这个参数返回命令行参数中的参数个数,默认情况下,pNumArgs 会返回1,如果有附加的命令行参数,该值会大于1,比如:
- "E:/SoftWare/ProjCleaner.exe" "-help"
则,pNumArgs 会返回2。
CommandLineToArgvW 函数的返回值是一个宽字节LPWSTR类型的字符串指针数组,数组中的每一个字符串指针代表着一个命令行参数,根据上面的示例,
设返回值为:LPWSTR *lpszArgv,则 lpszArgv[0] 就是 "E:/SoftWare/ProjCleaner.exe",lpszArgv[1] 就是 "-help",这样大家明白了吧?
通过 GetCommandLine、CommandLineToArgvW 两个函数就可以成功的获取并拆分命令行参数了。
下面再给大家演示一个小例子……
前言:《工程目录清理器》是我前段时间写的一个小软件:
帖子地址:http://www.cctry.com/thread-254-1-1.html
功能简介:大家可能会遇到:当写好一个工程想与其他人分享源码或从网络上下载工程源码时,压缩工程目录后得到的压缩文件会很大,携带或网络上传输很不方便,本程序默认可清理由Microsoft Visual C++ 编译器在编译、链接过程中所产生的中间文件,如:obj、ilk 等等。将其清除,如果大家设定好目录树结构后,可以支持其他各种编译器:VB、C#、Delphi 等等。之后还可以保存成 xml 文件,下次加载即可。
可有部分网友说:“这样的软件使用起来感觉麻烦,我就用一个批处理,而且集成到文件夹的右键菜单里面,点一下就清理了,比你这个方便。”
刚开始我还不以为然,可是最近从网上搜集到了一些软件的例子源码,想转帖到我们 VC驿站 - WwW.CcTry.CoM ,在清理工程目录过程中确实感到有点不方便,于是我就想也让我的这个《工程目录清理器》支持命令行参数,同时集成到文件夹的系统右键菜单里面,这样执行起来就方便多了。说做就做,于是把《工程目录清理器》的代码修改了一下,主要的核心代码就是上面提到的。此外,再给大家说一下如何集成到文件夹的系统右键菜单:
1、在[HKEY_CLASSES_ROOT/Directory/shell] 分支下建立一个自己命名的子键,例如,我的叫做:ProjCleaner;
2、将新建子键ProjCleaner下的默认键值设置为你想在文件夹右键菜单中显示的字符串,比如我的设置为:工程目录清理器;
3、在刚才新建的子键ProjCleaner下面再新建一子键,但是名字必须是command;
4、将刚才新建子键command下面的默认键值设置为:E:/SoftWare/ProjCleaner.exe "%1",其中 E:/SoftWare/ProjCleaner.exe 是工程目录清理器软件所在的路径,这个大家可以根据自己的程序位置来写,但是后面的 "%1" 大家一定要记得加上,他代表的就是右键单击文件夹所在的路径,即我们调用 GetCommandLine 函数所获得的附加参数。
具体,见如下两幅图:
经过了以上4个步骤之后,当我们右键单击某个文件夹之后,在弹出的菜单中就已经有我们添加的一项即“工程目录清理器”,如下图:
修改后的 InitInstance() 函数代码如下:
- BOOL CProjCleanerApp::InitInstance()
- {
- //省略的其他代码……;
- CWinApp::InitInstance();
- //省略的其他代码……;
- //for the command line;
- int argc = 0;
- LPWSTR *lpszArgv = NULL;
- LPTSTR szCmdLine = GetCommandLine(); //获取命令行参数;
- lpszArgv = CommandLineToArgvW(szCmdLine, &argc); //拆分命令行参数字符串;
- if (argc >= 2) {
- WCHAR szPath[500] = {0};
- swprintf(szPath, _T("%s%s%s"), _T("确定要清理 [ "), lpszArgv[1], _T(" ] 目录吗?")); //格式化字符串;
- if (MessageBox(NULL, szPath, _T("友情提示"), MB_OKCANCEL|MB_ICONQUESTION) == IDOK) { //进行删除提示;
- m_bStartFromCmd = TRUE;
- CleanStart(...); //调用CleanStart函数进行工程目录的清理工作;
- }
- return FALSE;
- }
- //command line end;
- CProjCleanerDlg dlg;
- m_pMainWnd = &dlg;
- INT_PTR nResponse = dlg.DoModal();
- if (nResponse == IDOK)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with OK
- }
- else if (nResponse == IDCANCEL)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with Cancel
- }
- return FALSE;
- }
具体代码见《工程目录清理器》帖子地址:http://www.cctry.com/thread-254-1-1.html 中的源码信息。
具体开启关联文件夹右键菜单的设置在:运行“工程目录清理器”-> “设置信息”按钮 -> “关联文件夹右键菜单”勾上 -> "应用设置" 即可!
说道这里也差不多讲完了,大家有什么问题再跟帖提问吧……