作者:朱金灿
来源:http://blog.csdn.net/clever101
继续开发一个VS插件。首先认识一下通过插件向导生成的类和函数,大致弄清一下它们的含义。创建一个基于ATL的插件工程,都生成了一个CConnect类。现在我们看看CConnect类的一些重要接口:
CConnect::OnConnection:这个接口可以说是插件的入口函数。只是这个入口函数会被调用几次,至于何时调用取决于这个函数的ConnectMode参数。
一个插件有下面几种加载模式:
- 在VS启动时,并且该插件并标记为随同VS启动时启动(所谓随同VS启动时启动请见图一),这时ConnectMode参数的值为ext_ConnectMode.ext_cm_Startup。
-
-
-
-
-
- 图一
-
-
-
-
- 在用户需要时时被调用,就是说该插件并没有被标记为VS启动时启动但用户手动在外接程序管理器上给启动一栏打上勾上时,这时ConnectMode参数的值为ext_ConnectMode.ext_cm_AfterStartup。
- 从命令行启动(使用devenv.exe去生成一个解决方案),这时ConnectMode参数的值为ext_ConnectMode.ext_cm_CommandLine。请注意这种情况在一些旧版本的Visual Studio会有一些bug并且看来只有在Visual Studio 2008才会正确运行(比VS 2008高的版本应该也可以)。
- 当插件使用常驻的工具栏、命令栏和按钮(常驻意味着即使插件没有加载用户界面也会出现)同时Visual Studio要求插件去初始化常驻用户界面,这时ConnectMode参数的值为ext_ConnectMode.ext_cm_UISetup。这种连接模式必须不同于ext_ConnectMode.ext_cm_Startup和ext_ConnectMode.ext_cm_AfterStartup的情况下。
- 假如你建的插件不是一个一般插件,而是一个和特定的解决方案相关的插件,当这个解决方案被加载时,这时ConnectMode参数的值为ext_ConnectMode.ext_cm_AfterStartup。
所以,存在两种模式:ext_ConnectMode.ext_cm_Startup和ext_ConnectMode.ext_cm_AfterStartup。这意味着它们都以相同的方式处理因为在一般情况下插件在VS启动时自动加载还是过了一些时候手动加载它们并没有什么不同。所以你可以使用下面的代码:
STDMETHODIMP CConnect::OnConnection(IDispatch *pApplication, ext_ConnectMode ConnectMode, IDispatch *pAddInInst, SAFEARRAY ** /*自定义*/ )
{
HRESULT hr = S_OK;
pApplication->QueryInterface(__uuidof(DTE2), (LPVOID*)&m_pDTE);
pAddInInst->QueryInterface(__uuidof(AddIn), (LPVOID*)&m_pAddInInstance);
switch(ConnectMode)
{
case ext_cm_Startup:
case ext_cm_AfterStartup:
{
// 初始化你的插件
break;
}
default:
break;
}
return hr;
}
然而当插件在ext_ConnectMode.ext_cm_Startup模式加载(也就是在Visual Studio启动时加载),VisualStudio并没有完全初始化。所以这是很多插件可以正确初始化,但一些却会失败。比如当你的插件加载时需要显示一个工具窗口,当插件在VS启动时加载工具窗口却并不会显示,但在外接程序管理器手动加载这个插件时可以显示这个工具窗口。
所以在VisualStudioz完全初始化之后再调用OnConnection函数会比较好。IDTExtensibility2接口提供了一个在VisualStudioz完全初始化后会被调用的叫OnStartupComplete的方法。所以正确的代码如下:
STDMETHODIMP CConnect::OnStartupComplete (SAFEARRAY ** /*自定义*/ )
{
// 初始化你的插件
return S_OK;
}
// CConnect
STDMETHODIMP CConnect::OnConnection(IDispatch *pApplication, ext_ConnectMode ConnectMode, IDispatch *pAddInInst, SAFEARRAY ** /*自定义*/ )
{
HRESULT hr = S_OK;
pApplication->QueryInterface(__uuidof(DTE2), (LPVOID*)&m_pDTE);
pAddInInst->QueryInterface(__uuidof(AddIn), (LPVOID*)&m_pAddInInstance);
switch(ConnectMode)
{
case ext_cm_Startup:
// 什么也不做,因为Visual Studio并没有完全初始化
break;
case ext_cm_AfterStartup:
{
OnStartupComplete(NULL);
break;
}
default:
break;
}
return hr;
}
参考文献:
- HOWTO: Use correctly the OnConnection method of a Visual Studio add-in,Author:Carlos J. Quintero (Microsoft MVP)