VC++内部COM插件的编程实现

2016-02-19 18:42 8 1 收藏

只要你有一台电脑或者手机,都能关注图老师为大家精心推荐的VC++内部COM插件的编程实现,手机电脑控们准备好了吗?一起看过来吧!

【 tulaoshi.com - 编程语言 】

一、闲聊

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  今天要谈的话题是COM,稍微深入一点,不知道大家用过C++Test或者Visual Assistant之类的软件没有,它们都有个非常引人注目的功能,那就是把它们自身嵌入到VC开发环境中去。这个功能让我痴迷不已,原因只有一个:我想做一个可以嵌入VC开发环境的VC工程解析器,这样用户在VC开发环境中就可以直接对当前或所有工程进行各种分析,统计。那么实现它简单吗?简单,Next和Copy即可轻松完成;仅仅这些吗?不是,它的背后还有博大精深的COM做支撑。不管困难与否,还是让我们先试为快。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  三、实现步骤:

  3.1新建一个DevStudio Add-in Wizard类型工程,输入工程名称"CodeAnalyser".

  3.2进入第二个画面,系统要求用户输入插件的名称和描述信息。并且要求用户选择是否需要生成工具栏以及是否自动添加VC事件响应代码。

  3.3点击"Finish"结束向导,进入代码编辑窗口。

  在这里我们要说的一点是:该工程引用了ICommands接口,并从该接口上派生出 CCommands类。该类完成了所有用户自定义函数接口,VC应用程序消息响应和VC调试动作的消息响应工作。当我们真正为CCommands类添加成员函数之前我们必须先为ICommands接口添加相应的函数接口声明。在本工程中我总共为ICommands接口添加了两个函数接口,它们名字分别为:GetCurDirCommandMethod和QuitCommandMethod声明如下:(在CodeAnalyer.odl文件中)

interface ICommands : IDispatch
{
 // methods
 [id(1)] //在Vtable中的函数索引号
 HRESULT GetCurDirCommandMethod(); //得到VC当前工作目录

 [id(2)] //在Vtable中的函数索引号
 HRESULT QuitCommandMethod (); //退出VC编辑器
};

  在接口ICommands添加接口函数,那么相应的我们也要在类CCommands中声明和实现ICommands接口函数,函数的内部代码和普通工程代码没什么区别。

//Implement(CCommands类内部接口函数的声明)
public:
STDMETHOD(GetCurDirCommandMethod)(THIS);
STDMETHOD(QuitCommandMethod)(THIS);

//Function Code(Ccommands类内部接口函数的实现)
//得到当前VC开发环境的工作目录[您也可以让它成为你想要实现的功能代码]
STDMETHODIMP CCommands::GetCurDirCommandMethod()
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 VERIFY_OK(m_pApplication-EnableModeless(VARIANT_FALSE));
 BSTR bstrCurDir;
 m_pApplication-get_CurrentDirectory(&bstrCurDir);
 CString str(bstrCurDir);
 ::MessageBox(NULL, str, "VC工作目录", MB_OK | MB_ICONINFORMATION);
 VERIFY_OK(m_pApplication-EnableModeless(VARIANT_TRUE));
 return S_OK;
}

//退出VC开发环境

STDMETHODIMP CCommands::QuitCommandMethod()
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 VERIFY_OK(m_pApplication-EnableModeless(VARIANT_FALSE));
 if(::MessageBox(NULL,"您想退出VC++编辑器吗(Y/N)?","询问信息...", MB_YESNO | MB_ICONQUESTION) == IDYES)
  m_pApplication-Quit();
  VERIFY_OK(m_pApplication-EnableModeless(VARIANT_TRUE));
 return S_OK;
}

  3.4 创建工具栏,连接工具栏按钮事件

  所有的幕后工作已经准备就绪,只差个工具栏界面就一切OK了。打开类CDSAddIn,它里面有三个成员函数,其中OnConnection和OnDisconnection成员函数的意义非常重要。它们的意义如下:

  1OnConnection:插件的初始化任务都在这里完成。如COM服务的启动,工具栏/菜单栏的创建,工具栏按钮/菜单项的添加与修改等等。

  2OnDisconnection:插件的卸载工作都在这里完成。如COM服务的卸载,工具栏/菜单栏的销毁,释放等等。

  了解了它们各自的用途之后我们就可以在相应的消息事件中添加代码了。很显然工具栏的初始化应该在OnConnection事件中完成。

  在OnConnection事件中系统首先获得了VC应用程序接口,然后调用一个接口函数:AddCommand来为插件添加命令和命令影射函数。然后再使用另外一个接口函数AddCommandBarButton向工具栏中添加工具栏按钮,其中每个工具栏按钮会和一个命令标志符号相连接,这样就能实现按钮和命令(消息)之间的一一对应。下面是添加一个命令和一个工具栏按钮的代码(如果你要添加多个工具栏按钮只要重复此步骤即可):

LPCTSTR szCommand = _T("GetCurDirCommand");
VARIANT_BOOL bRet;
CString strCmdString;
strCmdString.LoadString(IDS_CMD_STRING);
strCmdString = szCommand + strCmdString;
CComBSTR bszCmdString(strCmdString);
CComBSTR bszMethod(_T("GetCurDirCommandMethod"));

CComBSTR bszCmdName(szCommand); //和下面添加工具栏按钮对应

VERIFY_OK(pApplication-AddCommand(bszCmdString,bszMethod,0,dwCookie,&bRet));
//AddCommand 参数含义:
//bszCmdString:命令字符串。
//bszMethod:Icommands接口函数名。
//第三个参数代表位图偏移量。
//第四和第五个参数分贝为系统参数和返回值(参照MSDN的IApplication介绍)

if (bRet == VARIANT_FALSE)
{
 *OnConnection = VARIANT_FALSE;
 return S_OK;
}

//添加工具栏按钮
if (bFirstTime == VARIANT_TRUE)
{
 VERIFY_OK(pApplication-AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
}

  3.5 编译,连接及在VC中引入插件

  以上就是我们所有的代码工作,接下来赶快Build以下吧。编译通过的话,在你的工程Debug目录下会有个dll文件。然后打开VC编辑器,在VC任何一个工具栏上点击鼠标右键,弹出如下图所示菜单。然后选择”Customize”子菜单,打开如下图所示的工具栏定制窗口:

  接着选择该窗口的最后一页"Add-Ins and Macro Files"出现下图所示窗口。

  然后点击”Browse...”按钮,这时打开你工程下的Debug目录中的DLL文件,这样你就可以看到你制作的工具栏了。同样你再次打开上面的菜单,这次可以看到多了一个工具栏,并且名字乱七八糟的,怎么改变工具栏的名字呢?方法很简单:打开上面窗口中的”Toolbars”选项页,在工具栏列表框中找到你的工具栏,然后在”Toolbar name”编辑框中输入你想要的名字即可。再打开上面的菜单看看名字是不是变了,哈哈!  

  OK,今天的话题就聊到这里。

来源:http://www.tulaoshi.com/n/20160219/1618683.html

延伸阅读
*假设调试机IP 192.168.0.182   远程机IP 192.168.0.161 *远程机为调试机分配权限,使调试机可以使用远程桌面登陆到远程机器上(这样调试起来方便)。 *调试机上安装visual studio .net 2003 共享调试机上的Visual Studio上的远程调试目录(以我的机器为例) C:Program FilesMicrosoft Visual Studio .NET 2003Common7PackagesDe...
概述 管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信...
在VC++实现数据加密 作者:惠州市东晓电子有限公司 龚辉斌 下载本文示例源代码 为了保证数据的安全性与完整性,常常要对数据进行加密,在数据传输过程进行数据加密可以防止中途非法截获。我们通常称原始数据叫做源文,用约定的加密算法进行加密处理。加密算法的输入是源文与加密键,而输出的则是密文...
VC++中轻松实现滑动控件 作者: 上海同济大学计算机系 小鹰 下载本文示例代码 滑动控件是Windows中最常用的控件之一。一般而言它是由一个滑动条,一个滑块和可选的刻度组成,用户可以通过移动滑块在相应的控件中显示对应的值。通常,在滑动控件附近一定有标签控件或编辑框控件,用...
一、函数调用捆绑   1、定义 捆绑:把函数体与函数调用相联系称为捆绑。当捆绑在程序运行之前(由编译器和连接器)完成时,称为早捆绑。(C编译只有一种函数调用,就是早捆绑)如果捆绑发生在运行时,则称为晚捆绑(或动态捆绑、运行时捆绑。 虚函数:如果我们在定义基类时在函数前加关键字virtual,则会告诉编译器对于此函数...

经验教程

831

收藏

35
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部