如何判断活动文档是否为文本文档?

时间:2017-10-10 16:07:34

标签: visual-studio visual-studio-extensions vsix

我正在开发一个Visual Studio扩展,其中只有当活动文档是文本文档时才能使用其中一个已实现的命令(例如Visual Studio'' Toggle Bookmark&# 34;确实如此。问题是,我无法弄清楚该怎么回事。

现在我有一个半工作的解决方案。在包的Initialize方法中,我订阅了DTE的WindowActivated事件,然后每当窗口被激活时,我都会检查窗口DocumentData属性是否为{ {1}}:

TextDocument

这种方法的问题在于1)Window.DocumentData is documented as ".NET Framework internal use only",2)当同时具有代码视图和设计视图的文档(例如protected override void Initialize() { base.Initialize(); var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; dte.Events.WindowEvents.WindowActivated += WindowEventsOnWindowActivated; //More initialization here... } //This is checked from command's BeforeQueryStatus public bool ActiveDocumentIsText { get; private set; } = false; private void WindowEventsOnWindowActivated(Window gotFocus, Window lostFocus) { if (gotFocus.Kind != "Document") return; //It's not a document (e.g. it's a tool window) TextDocument textDoc = gotFocus.DocumentData as TextDocument; ActiveDocumentIsText = textDoc != null; } 文件)时,这会产生误报。在设计模式下打开。

我也试过使用IVsTextManager.GetActiveView,但这会返回打开的 last 活动文本视图 - 所以如果我打开.txt文件然后打开.png文件,那么返回.txt文件的数据,即使它不再是活动文档。

那么,我如何检查活动文档是文本文档,还是可以拥有设计者的文档的代码视图......如果可能的话,不使用"未记录的"类/成员?

更新:我找到了一个更好的解决方案。在窗口内激活处理程序:

.visxmanifest

至少this one is properly documented,但我仍然遇到设计师误报的问题。

1 个答案:

答案 0 :(得分:0)

我终于明白了。这有点棘手,但它有效,并且是100%"合法"。这是食谱:

1-制作包类实现IVsRunningDocTableEvents。只需return VSConstants.S_OK;

即可完成所有方法

2-将以下字段和以下辅助方法添加到包类:

private IVsRunningDocumentTable runningDocumentTable;

private bool DocIsOpenInLogicalView(string path, Guid logicalView, out IVsWindowFrame windowFrame)
{
    return VsShellUtilities.IsDocumentOpen(
        this,
        path,
        VSConstants.LOGVIEWID_TextView,
        out var dummyHierarchy2, out var dummyItemId2,
        out windowFrame);
}

3-将以下内容添加到包类的Initialize方法中:

runningDocumentTable = GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
runningDocumentTable.AdviseRunningDocTableEvents(this, out var dummyCookie);

4- 不要眨眼,这就是魔术!按如下方式实施IVsRunningDocTableEvents.OnBeforeDocumentWindowShow方法:

public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
    runningDocumentTable.GetDocumentInfo(docCookie,
        out var dummyFlags, out var dummyReadLocks, out var dummyEditLocks,
        out string path, 
        out var dummyHierarchy, out var dummyItemId, out var dummyData);

    IVsWindowFrame windowFrameForTextView;
    var docIsOpenInTextView =
        DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_Code, out windowFrameForTextView) ||
        DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_TextView, out windowFrameForTextView);

    //Is the document open in the code/text view,
    //AND the window for that view is the one that has been just activated?

    ActiveDocumentIsText = docIsOpenInTextView && pFrame == logicalViewWindowFrame;

    return VSConstants.S_OK;
}