2011-08-25 16 views
7

Ho un evidenziatore di sintassi gestito utilizzando le nuove API di estensibilità VS e mi dà un ITextBuffer, che è ottimo.Come posso ottenere un ITextBuffer da EnvDTE.Window?

In un'altra parte della mia estensione si ottiene un oggetto DTE e si collega all'evento modificato della finestra attiva, che mi dà un oggetto 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 
} 

Mi piacerebbe ottenere ITextBuffer fuori dalla finestra in questo metodo. Qualcuno può dirmi un modo semplice per farlo?

risposta

9

La soluzione che ho usato è stata quella di ottenere il percorso di Windows, quindi usarlo in combinazione con IVsEditorAdaptersFactoryService e VsShellUtilities.

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

e

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, ma ricorda che 'IsDocumentOpen()' a volte restituisce false quando il documento è ancora in fase di apertura (VS chiama a codice utente a fare, ad esempio, , analizza il file prima che aggiorni la sua lista interna di finestre aperte). L'unica soluzione che ho trovato è quella di enumerare tutti i frame della finestra, ottenere VSFPROPID_ExtWindowObject per ognuno e confrontarlo con EnvDTE.Window (il cui FullName del documento corrisponde al percorso desiderato). – Cameron

+1

Inoltre, le finestre di documenti peek incorporate non hanno un 'IVsWindowFrame' per quanto posso dire, quindi' IsDocumentOpen' fallirà anche se il documento è "aperto" nella tabella dei documenti in esecuzione. È ancora possibile ottenere il buffer usando direttamente il metodo 'FindAndLockDocument' di' IVsRunningDocumentTable' (che è ciò che 'IsDocumentOpen' sta chiamando internamente). Ovviamente, se hai un oggetto 'EnvDTE.Window' in primo luogo, questo non si applica, ma se hai solo il percorso è importante sapere su questo caso d'angolo. – Cameron

Problemi correlati