一.为SolidWorks开发一个Visual Studio扩展
二.实现右击查看Api Help
三.使用Roslyn分析代码
四.如何新建一个Visual Studio ToolBox
五.获取注册表中的SolidWorks信息
六.实现SolidWorks Api的Quick Info
七.实现SolidWorks Api 的 Signature 签名帮助
八.为扩展添加模板
[九.发布Visual Studio 扩展]
源码地址-Github
二.实现右击查看Api Help
2.1 添加一个Command
首先我们要实现的是在代码编辑界面右击出现SolidWorks Api Help的上下文命令,首先我们需要添加一个自定义命令,在解决方案管理器中的VSIX项目右击,添加 => 新建项 => Extensibility => Command
如图所示:
选择确定,我们项目中出现如下文件
2.2 获取用户选择位置和内容
- 1.DuSolidWorkToolsPackage.cs 作为VSIX的的主要文件,类似于SolidWorks的SwAddin类,提供了对扩展对象的一个全局访问点。我们可以看到这个类初始化了我们刚才添加的ApiHelpCommand.
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
{
// When initialized asynchronously, the current thread may be a background thread at this point.
// Do any initialization that requires the UI thread after switching to the UI thread.
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
await ApiHelpCommand.InitializeAsync(this);
}
- 2.ApiHelpCommand.cs 实现对激活命令的响应等。其中Excute便是执行改命令的事件响应函数。
private void Execute(object sender, EventArgs e)
{
ThreadHelper.ThrowIfNotOnUIThread();
//初始化窗口
SolidWorksToolBoxCommand.Instance.Execute(null, null);
//查询选择的命名空间
TextViewSelection selection = GetSelectionAsync(ServiceProvider);
string activeDocumentPath = GetActiveFilePath(ServiceProvider);
ViewApiHelp(activeDocumentPath, selection);
}
可以看在在此函数中我激活了SolidWorksToolBoxCommand以便显示Api,这部分在下面介绍。然后通过GetSelectionAsync获取用户选择的内容或者光标位置,
接下来GetActiveFilePath来获取当前编辑的文件路径。有了文件路径和选择位置与选择内容,我们就可以对解决方案进行预编译从而获取当先用户选择内容的Symbol信息。
关于Symbol信息,可以了解关于Rosly的相关知识,关于Roslyn将在下一节介绍。
- 3.获取选中内容
private TextViewSelection GetSelectionAsync(Microsoft.VisualStudio.Shell.IAsyncServiceProvider serviceProvider)
{
var ServiceResult = serviceProvider.GetServiceAsync(typeof(SVsTextManager)).GetAwaiter().GetResult();
// service.Wait();
var textManager = ServiceResult as IVsTextManager2;
IVsTextView view;
int result = textManager.GetActiveView2(1, null, (uint)_VIEWFRAMETYPE.vftCodeWindow, out view);
//获取缓存视图
IVsTextLines lines;
view.GetBuffer(out lines);
//获取选中位置
view.GetSelection(out int startLine, out int startColumn, out int endLine, out int endColumn);//end could be before beginning
lines.GetPositionOfLineIndex(startLine, startColumn, out int StartPostion);
lines.GetPositionOfLineIndex(endLine, endColumn, out int EndPostion);
var start = new TextViewPosition(startLine, startColumn,StartPostion);
var end = new TextViewPosition(endLine, endColumn,EndPostion);
view.GetSelectedText(out string selectedText);
TextViewSelection selection = new TextViewSelection(start, end, selectedText);
return selection;
}
- 4.获取当前编辑文件的路径
private string GetActiveFilePath(Microsoft.VisualStudio.Shell.IAsyncServiceProvider serviceProvider)
{
ThreadHelper.ThrowIfNotOnUIThread();
var serviceResult = serviceProvider.GetServiceAsync(typeof(DTE)).GetAwaiter().GetResult() ;
//service.Wait();
DTE2 applicationObject = serviceResult as DTE2;
Assumes.Present(applicationObject);
return applicationObject.ActiveDocument.FullName;
}
- 5.TextViewSelection 和 TextViewPostion
public struct TextViewSelection
{
public TextViewPosition StartPosition { get; set; }
public TextViewPosition EndPosition { get; set; }
public string Text { get; set; }
public TextViewSelection(TextViewPosition a, TextViewPosition b, string text)
{
StartPosition = TextViewPosition.Min(a, b);
EndPosition = TextViewPosition.Max(a, b);
Text = text;
}
}
public struct TextViewPosition
{
private readonly int _column;
private readonly int _line;
private readonly int _postion;
public TextViewPosition(int line, int column,int postion)
{
_line = line;
_column = column;
_postion = postion;
}
public int Line { get { return _line; } }
public int Column { get { return _column; } }
public int Postion { get { return _postion; } }
public static bool operator <(TextViewPosition a, TextViewPosition b)
{
if (a.Line < b.Line)
{
return true;
}
else if (a.Line == b.Line)
{
return a.Column < b.Column;
}
else
{
return false;
}
}
public static bool operator >(TextViewPosition a, TextViewPosition b)
{
if (a.Line > b.Line)
{
return true;
}
else if (a.Line == b.Line)
{
return a.Column > b.Column;
}
else
{
return false;
}
}
public static TextViewPosition Min(TextViewPosition a, TextViewPosition b)
{
return a > b ? b : a;
}
public static TextViewPosition Max(TextViewPosition a, TextViewPosition b)
{
return a > b ? a : b;
}
}
- 可以查看Michael Shpilt的博客
2.3 把命令添加到右击上下文
- 在上面我们有三个文件,还有一个DuSolidWorksToolsPackage.vsct 我们没有提到。这是一个Xml格式的文件,用来定义我们的命令类型。我们需要修改这个文件以便将ApiHelpCommand添加到右击菜单。
添加修改Menuns和Groups节点为如下
修改ApiHelpCommand的Button节点
添加属性名为EditorContextMenuGroup的IDSymbol节点
2.4 运行Visual Studio
点击运行,Visual Studio将启动另外一个实例,打开一个文件,在编辑器右击,可以看到出现了一个查看SolidWork Api Help的选项。
如果想获取到Api帮助,我们需要使用Roslyn来对解决方案进行预编译,从而解析当前Api的类型信息,命名空间,再根据这些信息来定位Api的位置。