用自动化接口控制 Virsual Studio .NET 2003 的工具箱
做了一套ASP.NET的自定义控件,本想把这些控件加到Virsual Studio .NET 2003 的工具箱中,看了一下MSDN,自己做代码试了一下,竟然不好使。搞了半天,查了N多资料,才知道是Virsual Studio .NET 2003的Bug,好在总算解决了。下面是源码,发出来以免大家碰到同样问题是浪费时间。
中间有几行代码可能你会觉得没必要,但如果没有,你会发现就不好用,经验之谈,希望对大家有所帮助!
控制台程序的主单元:
using System;
using EnvDTE;
namespace SuperToolboxCS
{
/// <summary>
/// ClassMain 的摘要说明。
/// </summary>
class ClassMain
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Type latestDTE = Type.GetTypeFromProgID("VisualStudio.DTE");
EnvDTE.DTE dte = Activator.CreateInstance(latestDTE) as EnvDTE.DTE;
MessageFilter.Register();
if (dte != null)
Installer.AddToolBoxTab(dte);
MessageFilter.Revoke();
}
}
sealed class Installer
{
public static void AddToolBoxTab(EnvDTE.DTE dte)
{
if (dte == null)
return;
Window win = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);
ToolBox box = win.Object as ToolBox;
if (box == null)
return;
ToolBoxTabs tabs = box.ToolBoxTabs;
if (tabs == null)
return;
foreach (ToolBoxTab t in tabs)
{
if (t.Name == TabName)
t.Delete();
}
ToolBoxTab tab = tabs.Add(TabName);
if (tab == null)
return;
dte.ExecuteCommand("View.PropertiesWindow", "");
tab.Activate();
tab.ToolBoxItems.Item(1).Select();
string fullpath = LookupSuperServerObjectFileName();
if (fullpath == "")
return;
tab.ToolBoxItems.Add(@"Unused?", fullpath, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);
System.Console.Write("SuperLib Web 窗体工具箱创建成功!");
}
private static string LookupSuperServerObjectFileName()
{
string KeyName = "";
Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine;
rk = rk.OpenSubKey(KeyName, false);
if (rk == null)
{
return "";
}
string fullpath = (string)rk.GetValue(null);
fullpath += @"\SuperLib.ServerObject.dll";
if (!System.IO.File.Exists(fullpath))
{
return "";
}
return fullpath;
}
private const string TabName = @"SuperLib Web 窗体";
private const string KeyName = @"SOFTWARE\Microsoft\VisualStudio\7.1\AssemblyFolders\SuperLibV2.4.2003";
}
}
MessageFilter 类
using System;
using System.Runtime.InteropServices;
namespace SuperToolboxCS
{
/// <summary>
/// MessageFilter 的摘要说明。
/// </summary>
public class MessageFilter : IOleMessageFilter
{
public static void Register()
{
IOleMessageFilter newfilter = new MessageFilter();
IOleMessageFilter oldfilter = null;
CoRegisterMessageFilter(newfilter, out oldfilter);
}
public static void Revoke()
{
IOleMessageFilter oldfilter = null;
CoRegisterMessageFilter(null, out oldfilter);
}
//
// IOleMessageFilter impl
int IOleMessageFilter.HandleInComingCall(int dwCallType, System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr lpInterfaceInfo)
{
System.Diagnostics.Debug.WriteLine("IOleMessageFilter::HandleInComingCall");
return 0; //SERVERCALL_ISHANDLED
}
int IOleMessageFilter.RetryRejectedCall(System.IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
{
System.Diagnostics.Debug.WriteLine("IOleMessageFilter::RetryRejectedCall");
if (dwRejectType == 2 ) //SERVERCALL_RETRYLATER
{
System.Diagnostics.Debug.WriteLine("Retry call later");
return 99; //retry immediately if return >=0 & <100
}
return -1; //cancel call
}
int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
{
System.Diagnostics.Debug.WriteLine("IOleMessageFilter::MessagePending");
return 2; //PENDINGMSG_WAITDEFPROCESS
}
//
// Implementation
[DllImport("Ole32.dll")]
private static extern int CoRegisterMessageFilter(IOleMessageFilter newfilter, out IOleMessageFilter oldfilter);
}
[ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
interface IOleMessageFilter // deliberately renamed to avoid confusion w/ System.Windows.Forms.IMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);
[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}
}
同样有 VB.NET 版本的实现,不贴了。
需要发消息。
参考 BLOG:
http://weblogs.asp.net/savanness/archive/2003/04/24/6012.aspx
http://weblogs.asp.net/savanness/archive/2003/04/15/5701.aspx
http://weblogs.asp.net/savanness/archive/2003/04/10/5352.aspx
http://weblogs.asp.net/savanness/archive/2003/03/18/4019.aspx
中间有几行代码可能你会觉得没必要,但如果没有,你会发现就不好用,经验之谈,希望对大家有所帮助!
控制台程序的主单元:
using System;
using EnvDTE;
namespace SuperToolboxCS
{
/// <summary>
/// ClassMain 的摘要说明。
/// </summary>
class ClassMain
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Type latestDTE = Type.GetTypeFromProgID("VisualStudio.DTE");
EnvDTE.DTE dte = Activator.CreateInstance(latestDTE) as EnvDTE.DTE;
MessageFilter.Register();
if (dte != null)
Installer.AddToolBoxTab(dte);
MessageFilter.Revoke();
}
}
sealed class Installer
{
public static void AddToolBoxTab(EnvDTE.DTE dte)
{
if (dte == null)
return;
Window win = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);
ToolBox box = win.Object as ToolBox;
if (box == null)
return;
ToolBoxTabs tabs = box.ToolBoxTabs;
if (tabs == null)
return;
foreach (ToolBoxTab t in tabs)
{
if (t.Name == TabName)
t.Delete();
}
ToolBoxTab tab = tabs.Add(TabName);
if (tab == null)
return;
dte.ExecuteCommand("View.PropertiesWindow", "");
tab.Activate();
tab.ToolBoxItems.Item(1).Select();
string fullpath = LookupSuperServerObjectFileName();
if (fullpath == "")
return;
tab.ToolBoxItems.Add(@"Unused?", fullpath, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);
System.Console.Write("SuperLib Web 窗体工具箱创建成功!");
}
private static string LookupSuperServerObjectFileName()
{
string KeyName = "";
Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine;
rk = rk.OpenSubKey(KeyName, false);
if (rk == null)
{
return "";
}
string fullpath = (string)rk.GetValue(null);
fullpath += @"\SuperLib.ServerObject.dll";
if (!System.IO.File.Exists(fullpath))
{
return "";
}
return fullpath;
}
private const string TabName = @"SuperLib Web 窗体";
private const string KeyName = @"SOFTWARE\Microsoft\VisualStudio\7.1\AssemblyFolders\SuperLibV2.4.2003";
}
}
MessageFilter 类
using System;
using System.Runtime.InteropServices;
namespace SuperToolboxCS
{
/// <summary>
/// MessageFilter 的摘要说明。
/// </summary>
public class MessageFilter : IOleMessageFilter
{
public static void Register()
{
IOleMessageFilter newfilter = new MessageFilter();
IOleMessageFilter oldfilter = null;
CoRegisterMessageFilter(newfilter, out oldfilter);
}
public static void Revoke()
{
IOleMessageFilter oldfilter = null;
CoRegisterMessageFilter(null, out oldfilter);
}
//
// IOleMessageFilter impl
int IOleMessageFilter.HandleInComingCall(int dwCallType, System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr lpInterfaceInfo)
{
System.Diagnostics.Debug.WriteLine("IOleMessageFilter::HandleInComingCall");
return 0; //SERVERCALL_ISHANDLED
}
int IOleMessageFilter.RetryRejectedCall(System.IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
{
System.Diagnostics.Debug.WriteLine("IOleMessageFilter::RetryRejectedCall");
if (dwRejectType == 2 ) //SERVERCALL_RETRYLATER
{
System.Diagnostics.Debug.WriteLine("Retry call later");
return 99; //retry immediately if return >=0 & <100
}
return -1; //cancel call
}
int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
{
System.Diagnostics.Debug.WriteLine("IOleMessageFilter::MessagePending");
return 2; //PENDINGMSG_WAITDEFPROCESS
}
//
// Implementation
[DllImport("Ole32.dll")]
private static extern int CoRegisterMessageFilter(IOleMessageFilter newfilter, out IOleMessageFilter oldfilter);
}
[ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
interface IOleMessageFilter // deliberately renamed to avoid confusion w/ System.Windows.Forms.IMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);
[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}
}
同样有 VB.NET 版本的实现,不贴了。
需要发消息。
参考 BLOG:
http://weblogs.asp.net/savanness/archive/2003/04/24/6012.aspx
http://weblogs.asp.net/savanness/archive/2003/04/15/5701.aspx
http://weblogs.asp.net/savanness/archive/2003/04/10/5352.aspx
http://weblogs.asp.net/savanness/archive/2003/03/18/4019.aspx