2017-10-10 15 views
1

私は、アクティブなドキュメントがテキストドキュメント(Visual Studioの "Toggle Bookmark"など)の場合にのみ、実装されたコマンドの1つを使用できるようにするVisual Studio拡張機能を開発しています。問題は、そのような場合にどのように通知するのか分かりません。アクティブなドキュメントがテキストドキュメントであるかどうかを確認するには?

今は半分の解決策があります。パッケージのInitialize方法では、私は、DTEのWindowActivatedイベントをサブスクライブし、ウィンドウがアクティブになるたびウィンドウDocumentDataプロパティがタイプTextDocumentであるならば、私がチェックします。

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; 
} 

このアプローチの問題点は、1)Window.DocumentData is documented as ".NET Framework internal use only"で、 2)これは、コード・ビューとデザイン・ビューの両方を持つ文書(例えば、.visxmanifestファイル)がデザイン・モードで開いているときに誤ったポジティブを示します。

私もIVsTextManager.GetActiveViewを使用しようとしましたが、これは最後アクティブなテキストビューが開いて戻っている - ので、私はその後、.txtファイルと.pngのファイルを開く場合は、それも.txtファイルのデータを返しますそれはもはやアクティブな文書ではない場合。

アクティブなドキュメントがテキストドキュメントであるか、デザイナを持つことができるドキュメントのコードビューであるかを確認するにはどうしたらいいですか?可能であれば、ドキュメント化されていないクラスやメンバを使用しないでください。

更新日:少し良い解決策が見つかりました。ウィンドウに起動されるハンドラ内:

ActiveDocumentIsText = gotFocus.Document.Object("TextDocument") != null; 

少なくともthis one is properly documentedが、私はまだデザイナーと偽陽性の問題を抱えています。

答えて

0

私はついにそれを手に入れました。多少トリッキーですが、動作し、100% "合法"です。

1-レシピは次のとおりです。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; 
} 
関連する問題