2011-08-25 28 views
7

Tôi có một công cụ đánh dấu cú pháp được quản lý bằng cách sử dụng API mở rộng mới của VS và nó mang lại cho tôi ITextBuffer, điều này thật tuyệt vời.Làm thế nào tôi có thể nhận được một ITextBuffer ra khỏi một EnvDTE.Window?

Trong phần khác của tiện ích mở rộng của tôi, tôi nhận được đối tượng DTE và đính kèm vào sự kiện đã thay đổi cửa sổ đang hoạt động, cho tôi đối tượng EnvDTE.Window.

var dte = (EnvDTE.DTE)this.GetService(typeof(EnvDTE.DTE)); 
dte.Events.WindowEvents.WindowActivated += WindowEvents_WindowActivated; 
// ... 

private void WindowEvents_WindowActivated(EnvDTE.Window GotFocus, EnvDTE.Window LostFocus) 
{ 
    // ??? 
    // Profit 
} 

Tôi muốn đưa ITextBuffer ra khỏi cửa sổ theo phương pháp này. Bất cứ ai có thể cho tôi biết một cách thẳng về phía trước để làm điều đó?

Trả lời

9

Giải pháp tôi đã sử dụng là lấy đường dẫn Windows sau đó sử dụng nó trong conjuction với IVsEditorAdaptersFactoryServiceVsShellUtilities.

var openWindowPath = Path.Combine(window.Document.Path, window.Document.Name); 
var buffer = GetBufferAt(openWindowPath); 

internal ITextBuffer GetBufferAt(string filePath) 
{ 
    var componentModel = (IComponentModel)GetService(typeof(SComponentModel)); 
    var editorAdapterFactoryService = componentModel.GetService<IVsEditorAdaptersFactoryService>(); 
    var serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(MetaSharpPackage.OleServiceProvider); 

    IVsUIHierarchy uiHierarchy; 
    uint itemID; 
    IVsWindowFrame windowFrame; 
    if (VsShellUtilities.IsDocumentOpen(
    serviceProvider, 
    filePath, 
    Guid.Empty, 
    out uiHierarchy, 
    out itemID, 
    out windowFrame)) 
    { 
    IVsTextView view = VsShellUtilities.GetTextView(windowFrame); 
    IVsTextLines lines; 
    if (view.GetBuffer(out lines) == 0) 
    { 
     var buffer = lines as IVsTextBuffer; 
     if (buffer != null) 
     return editorAdapterFactoryService.GetDataBuffer(buffer); 
    } 
    } 

    return null; 
} 
+0

+1, nhưng lưu ý rằng 'IsDocumentOpen()' đôi khi trả về false khi tài liệu vẫn đang trong quá trình được mở (VS gọi ra để mã sử dụng để làm, ví dụ như , phân tích tệp trước khi nó cập nhật danh sách cửa sổ đang mở của nó). Cách giải quyết duy nhất tôi đã tìm thấy cho rằng là liệt kê tất cả các khung cửa sổ, có được VSFPROPID_ExtWindowObject cho mỗi một, và so sánh nó với EnvDTE.Window (có FullName của tài liệu phù hợp với đường dẫn mong muốn). – Cameron

+1

Ngoài ra, các cửa sổ tài liệu được nhúng không có 'IVsWindowFrame' như tôi có thể nói, vì vậy' IsDocumentOpen' sẽ thất bại mặc dù tài liệu là "mở" trong bảng tài liệu đang chạy. Bạn vẫn có thể nhận được bộ đệm bằng cách sử dụng phương thức 'FindAndLockDocument' của' IVsRunningDocumentTable' trực tiếp (đó là những gì 'IsDocumentOpen' đang gọi nội bộ). Rõ ràng, nếu bạn có một đối tượng 'EnvDTE.Window' ở vị trí đầu tiên, điều này không áp dụng, nhưng nếu bạn chỉ có đường dẫn, điều quan trọng cần biết về trường hợp góc này. – Cameron

Các vấn đề liên quan