2017-10-10 5 views
1

활성 문서가 텍스트 문서 (예 : Visual Studio의 "토글 북마크")와 같은 경우에만 구현 된 명령 중 하나를 사용해야하는 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- 패키지 클래스를 IVsRunningDocTableEvents으로 구현하십시오.

다음 패키지 클래스의 Initialize 방법에 다음을 추가

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 : 모든 방법을 그냥 return VSConstants.S_OK;

2 패키지 클래스에 다음 필드 다음과 같은 보조 방법을 추가 확인

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