分类:
2008-10-13 17:08:20
VC++内部COM插件的编程实现
作者:
一、闲聊
首先,在这里向前段时间没来得及回复你们问题的朋友们说声对不起了,这段时间工作实在太忙,我快倒!哈哈!好了,让我们转入正题,今天要谈的话题是COM,稍微深入一点,不知道大家用过C++Test或者Visual
Assistant(可到工具栏目下载)之类的软件没有,它们都有个非常引人注目的功能,那就是把它们自身嵌入到VC开发环境中去。这个功能让我痴迷不已,原因只有一个:我想做一个可以嵌入VC开发环境的VC工程解析器(已被收录在第19期中),这样用户在VC开发环境中就可以直接对当前或所有工程进行各种分析,统计。那么实现它简单吗?简单,Next和Copy即可轻松完成;仅仅这些吗?不是,它的背后还有博大精深的COM做支撑。不管困难与否,还是让我们先试为快。
二、效果图
三、实现步骤:
<3.1>新建一个
<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; }
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)); }