VC6插件开发应用实例

来源:互联网 发布:淘宝生活服务类目 编辑:程序博客网 时间:2024/05/29 08:36

一、背景

Eclipse中,对于JAVA项目,可在项目或者文件上的右键菜单Show in ->System Explorer中,直接在资源管理器中显示当前项目或当前文件所在文件夹,以便于在Windows资源管理器中对文件的操作管理。同样的,在Visual Studio 2010、2013、2015、2017等版本也有类似功能,VC6为早期版本,并无相应功能。本文通过对VC6 IDE插件的开发,实现了在VC6环境中直接打开资源管理器至当前项目所在文件夹,也可以打开命令行窗口,且路径直接切换至当前工作目录。先看效果:


二、实现过程

1、VC6中新建“DevStudio Add-in Wizard”插件工程。工程名为“OpenInExplorer”,插件项目向导中均使用默认选项,点击完成。向导完成后,生成的项目代码实际上为一COM组件。



2、生成项目中各类简要介绍(略),详见Microsoft参考文档

各个文件和类的解释参考微软Understanding the Results of the Add-in Wizard

3、在ResourceView视图中修改Bitmap资源:IDR_TOOLBAR_LARGE和IDR_TOOLBAR_MEDIUM文件。


4、在ResourceView视图中修改字串表,如下表所示:

ID

标题
IDS_CMD_STRING \n在Windows资源管理器中打开-1\n在Windows资源浏览器中打开工程-2\n在Windows资源管理器中打开IDS_CMD_STRING2 \n使用记事本打开1\n使用记事本打开2 \n使用记事本打开IDS_CMD_STRING3 \n打开命令窗口1\n打开CMD窗口2\n打开命令窗口

5、在CDSAddin类的OnConnection函数中添加自己的工具栏按钮及要执行的命令,完整函数如下所示:

STDMETHODIMP CDSAddIn::OnConnection(IApplication* pApp, VARIANT_BOOL bFirstTime,long dwCookie, VARIANT_BOOL* OnConnection){AFX_MANAGE_STATE(AfxGetStaticModuleState());// Store info passed to usIApplication* pApplication = NULL;if (FAILED(pApp->QueryInterface(IID_IApplication, (void**) &pApplication))|| pApplication == NULL){*OnConnection = VARIANT_FALSE;return S_OK;}m_dwCookie = dwCookie;// Create command dispatch, send info back to DevStudioCCommandsObj::CreateInstance(&m_pCommands);m_pCommands->AddRef();// The QueryInterface above AddRef'd the Application object.  It will//  be Release'd in CCommand's destructor.m_pCommands->SetApplicationObject(pApplication);// (see stdafx.h for the definition of VERIFY_OK)VERIFY_OK(pApplication->SetAddInInfo((long) AfxGetInstanceHandle(),(LPDISPATCH) m_pCommands, IDR_TOOLBAR_MEDIUM, IDR_TOOLBAR_LARGE, m_dwCookie));// Inform DevStudio of the commands we implement// TODO: Replace the AddCommand call below with a series of calls,//  one for each command your add-in will add.// The command name should not be localized to other languages.  The //  tooltip, command description, and other strings related to this//  command are stored in the string table (IDS_CMD_STRING) and should//  be localized.LPCTSTR szCommand = _T("OpenInExplorerCommand");VARIANT_BOOL bRet;CString strCmdString;strCmdString.LoadString(IDS_CMD_STRING);strCmdString = szCommand + strCmdString;CComBSTR bszCmdString(strCmdString);CComBSTR bszMethod(_T("OpenInExplorerCommandMethod"));CComBSTR bszCmdName(szCommand);VERIFY_OK(pApplication->AddCommand(bszCmdString, bszMethod, 0, m_dwCookie, &bRet));if (bRet == VARIANT_FALSE){// AddCommand failed because a command with this name already//  exists.  You may try adding your command under a different name.//  Or, you can fail to load as we will do here.*OnConnection = VARIANT_FALSE;return S_OK;}// Add toolbar buttons only if this is the first time the add-in//  is being loaded.  Toolbar buttons are automatically remembered//  by Developer Studio from session to session, so we should only//  add the toolbar buttons once.if (bFirstTime == VARIANT_TRUE){VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));}/******添加自定义工具栏按钮 Start************************************************************/// 添加第二个工具栏按钮LPCTSTR szOpenNotepadCommand = _T("OpenInNotepad");CString strOpenNotepadCmdString;strOpenNotepadCmdString.LoadString(IDS_CMD_STRING2);strOpenNotepadCmdString = szOpenNotepadCommand + strOpenNotepadCmdString;CComBSTR bszOpenNotepadCmdString(strOpenNotepadCmdString);CComBSTR bszOpenNotepadMethod(_T("OpenInNotepad"));CComBSTR bszOpenNotepadCmdName(szOpenNotepadCommand);VERIFY_OK(pApplication->AddCommand(bszOpenNotepadCmdString, bszOpenNotepadMethod, 1, m_dwCookie, &bRet));if (bRet == VARIANT_FALSE){*OnConnection = VARIANT_FALSE;return S_OK;}if (bFirstTime == VARIANT_TRUE){VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszOpenNotepadCmdName, m_dwCookie));}// 添加第三个工具栏按钮LPCTSTR szConsoleCommand = _T("OpenInCommand");CComBSTR bszConsoleCmdName(szConsoleCommand);CString strConsoleCmdString;strConsoleCmdString.LoadString(IDS_CMD_STRING3);strConsoleCmdString = szConsoleCommand + strConsoleCmdString;CComBSTR bszConsoleCmdString(strConsoleCmdString);CComBSTR bszConsoleMethod(_T("OpenInCommand"));VERIFY_OK(pApplication->AddCommand(bszConsoleCmdString, bszConsoleMethod, 4, m_dwCookie, &bRet));if (bRet == VARIANT_FALSE){*OnConnection = VARIANT_FALSE;return S_OK;}if (bFirstTime == VARIANT_TRUE){VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszConsoleCmdName, m_dwCookie));}/**********添加自定义工具栏按钮 End*************************************************************/*OnConnection = VARIANT_TRUE;return S_OK;}


6、ClassView视图中,在CCommands类的接口上添加方法OpenInNotepad()和OpenInCommand()。并分别在CCommands类中实现这些方法。具体代码如下:

STDMETHODIMP CCommands::OpenInExplorerCommandMethod() {AFX_MANAGE_STATE(AfxGetStaticModuleState());// TODO: Replace this with the actual code to execute this command//  Use m_pApplication to access the Developer Studio Application object,//  and VERIFY_OK to see error strings in DEBUG builds of your add-in//  (see stdafx.h)VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));//获得DevStudio当前工作目录BSTR bstrCurrentDirectory;m_pApplication->get_CurrentDirectory(&bstrCurrentDirectory);char* lpszDir = _com_util::ConvertBSTRToString(bstrCurrentDirectory);        // operation params:"open", "runas", "print", "edit", "explorer", "find"       ::ShellExecute(NULL,"open",lpszDir,NULL,lpszDir,SW_SHOWNORMAL);//释放资源::SysFreeString(bstrCurrentDirectory);delete[] lpszDir;VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));return S_OK;}

以上使用了com工具,故需要引入相应头文件和依赖库文件。

//_com_util::ConvertBSTRToString()函数将要用到的头文件和库依赖文件#include "comutil.h"#pragma comment(lib, "comsupp.lib")

OpenInNotepad()

STDMETHODIMP CCommands::OpenInNotepad(){AFX_MANAGE_STATE(AfxGetStaticModuleState())VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));CHAR path[MAX_PATH] = {NULL};::GetSystemDirectory(path,MAX_PATH);HINSTANCE hinst = NULL;// hinst = ::ShellExecute(NULL, NULL, "notepad.exe", NULL, path, SW_SHOWNORMAL);// hinst = ::ShellExecute(NULL,"open","C:\\Windows\\System32\\notepad.exe",NULL,NULL,SW_SHOWNORMAL);UINT ret = ::WinExec("notepad.exe", SW_SHOWNORMAL);if( SE_ERR_NOASSOC == (int)hinst){::MessageBox(NULL, "Call notepad.exe Exception!", "OpenInNotepad", MB_OK | MB_ICONWARNING);}VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));return S_OK;}


OpenInCommand()

STDMETHODIMP CCommands::OpenInCommand(){AFX_MANAGE_STATE(AfxGetStaticModuleState())VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));HINSTANCE hinst = NULL;// 执行外部命令的几个函数:WinExec(), ShellExecute(), system(), CreateProcess()// 打开IDE当前项目路径hinst = ::ShellExecute(NULL,"open","c:\\windows\\system32\\cmd.exe",NULL,NULL,SW_SHOWNORMAL);// 打开IDE当前项目路径// hinst = ::ShellExecute(NULL,"open","cmd.exe",NULL,NULL,SW_SHOWNORMAL);// 打开C:\Windows\System32目录// hinst = ::ShellExecute(NULL, NULL, "cmd.exe", NULL, "C:\\Windows\\System32\\", SW_SHOWNORMAL);//::WinExec("cmd.exe", SW_SHOWNORMAL);// system("c:\\windows\\system32\\cmd.exe");// system("notepad.exe");// 使用浏览器打开网页// hinst = ::ShellExecute(NULL,"open","http://localhost",NULL,NULL,SW_SHOWNORMAL);// 使用邮件工具编辑邮件// hinst = ::ShellExecute(NULL,"open","mailto:who@mail.example.com?subject=Hello&Body=this is a test",NULL,NULL,SW_SHOWNORMAL);if( SE_ERR_NOASSOC == (int)hinst){::MessageBox(NULL, "Call cmd.exe Exception!", "OpenInNotepad", MB_OK | MB_ICONWARNING);}VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));return S_OK;}


7、编译链接完成后实现自动注册组件。VC6IDE中->菜单“工程”->设置->Post-Build步骤,新增命令,命令行如下

regsvr32.exe $(OutDir)\OpenInExplorer.dll /s

/s参数表示 无声,不显示注册成功与否的消息框。


7、编译、注册组件后,VC6IDE中->菜单“工具”->定制->附加项和宏文件,点击该界面的“浏览”按钮,选中本项目的OpenInExplorer.dll文件。选中插件“OpenInExplorer Developer Studio Add-in”。关闭后弹出工具栏对话框。具体也可参考CmdWnd: Issue IDE Command in a Command Window

然后IDE可增加带3个命令按钮的工具栏对话框。在任意打开的项目中点击自定义的工具栏按钮,发现已经实现目标。直接点击按钮1,可在打开的资源管理器中直接浏览本项目文件或对项目文件进行IDE之外的操作。

三、参考文档

Visual C++ Developer Studio Add-in Samples

Overview: Add-ins for the Visual C++ Developer Studio

How to: Create Add-in

微软实现步骤示例Creating Add-ins Using Visual C++

四、注意事项

如果在windows 7以上编译,请使用管理员权限打开vc6,否则因权限不足,会导致组件注册失败。

五、完整源代码下载:OpenInExplorer

原创粉丝点击