Visual Studio 扩展:如何处理多个插入符号?
Visual Studio Extension: How do I handle multiple carets?
我正在开发一个 Visual Studio Extension/VSIX 包,用于涉及更改插入符号位置的工作。当然,处理单个插入符号很容易:
/// Get the Host of current active view
private async Task<IWpfTextViewHost> GetCurrentViewHostAsync()
{
// First get the active view:
var txtManager = (IVsTextManager)await ServiceProvider.GetServiceAsync(typeof(SVsTextManager));
Assumes.Present(txtManager);
IVsTextView vTextView = null;
const int mustHaveFocus = 1;
textManager.GetActiveView(mustHaveFocus, null, out vTextView);
if (vTextView is IVsUserData userData)
{
// Get host
IWpfTextViewHost viewHost;
object holder;
Guid guidViewHost = DefGuidList.guidWpfTextViewHost;
userData.GetData(ref guidViewHost, out holder);
viewHost = (IWpfTextViewHost)holder;
return viewHost;
}
return null;
}
// Later:
private async void ExecCommand(object sender, EventArgs e)
{
IWpfTextViewHost host = await GetCurrentViewHostAsync();
// Access single caret
host.TextView.Caret.MoveTo(/* New position here */);
}
但是假设我使用 "Insert Next Matching Caret" 命令插入另一个插入符,所以我现在有两个不同的插入符。使用上述方法移动插入符将删除第二个插入符,据我所知,IVsTextView
只有一个插入符 属性.
我的下一个想法是我应该使用 host
中的其他 IVsTextManager 接口访问其他游标,但我能找到的最接近的是它的 EnumViews(IVsTextBuffer, IVsEnumTextViews)
方法,它总是 returns 一些负的、非 S_OK
的值,并将 IVsEnumTextViews
项保留为 null
。 EnumIndependentViews
方法也会发生类似的事情。
我接近这个了吗? "Multiple Carets" 是怎么工作的?我找不到任何关于它的文件。 API 甚至让我这样做吗?
原来要用ITextView2
的(不是ITextView
)MultiSelectionBroker
属性,只能用TextView的GetMultiSelectionBroker
访问扩展方法。有关详细信息,请参阅 docs。
private async void ExecCommand(object sender, EventArgs e)
{
// ConfigureAwait(true) is just to silence warnings about adding ConfigureAwait(false)
// "false" will cause this to not function properly. (Carets won't update).
IWpfTextViewHost host = await GetCurrentViewHostAsync().ConfigureAwait(true);
// Because TextView is only ITextView and not ITextView2,
// we can only access the MultiSelectionBroker property with the extension method:
IMultiSelectionBroker selectionBroker = host.TextView.GetMultiSelectionBroker();
foreach (var selection in selectionBroker.AllSelections)
{
var nextPoint = GetSomePointHere(host, selection);
selectionBroker.TryPerformActionOnSelection(
selection,
t => t.MoveTo(nextPoint, false, PositionAffinity.Successor),
out Selection after
);
}
}
不知道为什么,但我一定是在写问题时完全错过了 ITextView2
的文档。
注意:默认Microsoft.VisualStudio.Text.UI.dll
不会包含这个方法,因为它是一个扩展方法。您可以从解决方案中删除 dll 引用并重新添加正确的引用(在扩展下)以解决此问题。
我正在开发一个 Visual Studio Extension/VSIX 包,用于涉及更改插入符号位置的工作。当然,处理单个插入符号很容易:
/// Get the Host of current active view
private async Task<IWpfTextViewHost> GetCurrentViewHostAsync()
{
// First get the active view:
var txtManager = (IVsTextManager)await ServiceProvider.GetServiceAsync(typeof(SVsTextManager));
Assumes.Present(txtManager);
IVsTextView vTextView = null;
const int mustHaveFocus = 1;
textManager.GetActiveView(mustHaveFocus, null, out vTextView);
if (vTextView is IVsUserData userData)
{
// Get host
IWpfTextViewHost viewHost;
object holder;
Guid guidViewHost = DefGuidList.guidWpfTextViewHost;
userData.GetData(ref guidViewHost, out holder);
viewHost = (IWpfTextViewHost)holder;
return viewHost;
}
return null;
}
// Later:
private async void ExecCommand(object sender, EventArgs e)
{
IWpfTextViewHost host = await GetCurrentViewHostAsync();
// Access single caret
host.TextView.Caret.MoveTo(/* New position here */);
}
但是假设我使用 "Insert Next Matching Caret" 命令插入另一个插入符,所以我现在有两个不同的插入符。使用上述方法移动插入符将删除第二个插入符,据我所知,IVsTextView
只有一个插入符 属性.
我的下一个想法是我应该使用 host
中的其他 IVsTextManager 接口访问其他游标,但我能找到的最接近的是它的 EnumViews(IVsTextBuffer, IVsEnumTextViews)
方法,它总是 returns 一些负的、非 S_OK
的值,并将 IVsEnumTextViews
项保留为 null
。 EnumIndependentViews
方法也会发生类似的事情。
我接近这个了吗? "Multiple Carets" 是怎么工作的?我找不到任何关于它的文件。 API 甚至让我这样做吗?
原来要用ITextView2
的(不是ITextView
)MultiSelectionBroker
属性,只能用TextView的GetMultiSelectionBroker
访问扩展方法。有关详细信息,请参阅 docs。
private async void ExecCommand(object sender, EventArgs e)
{
// ConfigureAwait(true) is just to silence warnings about adding ConfigureAwait(false)
// "false" will cause this to not function properly. (Carets won't update).
IWpfTextViewHost host = await GetCurrentViewHostAsync().ConfigureAwait(true);
// Because TextView is only ITextView and not ITextView2,
// we can only access the MultiSelectionBroker property with the extension method:
IMultiSelectionBroker selectionBroker = host.TextView.GetMultiSelectionBroker();
foreach (var selection in selectionBroker.AllSelections)
{
var nextPoint = GetSomePointHere(host, selection);
selectionBroker.TryPerformActionOnSelection(
selection,
t => t.MoveTo(nextPoint, false, PositionAffinity.Successor),
out Selection after
);
}
}
不知道为什么,但我一定是在写问题时完全错过了 ITextView2
的文档。
注意:默认Microsoft.VisualStudio.Text.UI.dll
不会包含这个方法,因为它是一个扩展方法。您可以从解决方案中删除 dll 引用并重新添加正确的引用(在扩展下)以解决此问题。