Hosting Code Editor in Tool Windows

Deploying Visual Studio 2003 managed VSPackages(Reposted here)

Hosting Code Editor in a ToolWindow

I am pretty sure you have thought about doing this. Come on! I know you have. I had been thinking about implementing it for quite some time now. But one of our resident surgeons Ed Dore beat me to it. Read on and have fun.

 

       Hosting the Visual Studio code editor in a tool window and attaching a language service to it is very simple. The bigger unknown to me is how to hook up intellisense. As soon as I figure it out I will add to this article. If you beat me to that, which I know you can, do post it here.

§          Create the Text Buffer using the ILocalRegistry interface

§          Site the Text Buffer

§          Create the Code Window, to be used as Tool window, using the ILocalRegistry

§          Attach the Text Buffer to the Code Window

§          Create the Tool window using the IVsUIShell::CreateToolWindow

§          Set an appropiate language service for the text buffer

§          Optionally set the Key Bindings to the editor of your choice

Sample Code using VB Code Editor in a ToolWindow

// Define the following in Guids.cs file

public static Guid guidVBLangSvc =

new Guid("{E34ACDC0-BAAE-11D0-88BF-00A0C9110049}");

public static Guid guidCmdUI_TextEditor =

new Guid("{8B382828-6202-11d1-8870-0000F87579D2}");

// Using

using Microsoft.VisualStudio.Shell.Interop;

using OleInterop = Microsoft.VisualStudio.Ole.Interop;

Guid guidTextLines = typeof(IVsTextLines).GUID;

Guid guidCodeWindow = typeof(IVsCodeWindow).GUID; ;

Guid guidNull = Guid.Empty;

int[] position = new int[1];

IntPtr objPtr = IntPtr.Zero;

// Use ILocalRegistry to create text buffer and code window

ILocalRegistry localRegistry = (ILocalRegistry)GetService(typeof(ILocalRegistry));

Debug.Assert(localRegistry != null, "Unable to retrieve ILocalRegistry");

// Create a new text buffer

int hr = localRegistry.CreateInstance(typeof(VsTextBufferClass).GUID, null, ref

guidTextLines, Microsoft.VisualStudio.NativeMethods.CLSCTX_INPROC_SERVER, out objPtr);

Debug.Assert(hr == 0, "Failed to create instance of TextBuffer");

IVsTextLines textLines = Marshal.GetObjectForIUnknown(objPtr) as IVsTextLines;

Marshal.Release(objPtr);

objPtr = IntPtr.Zero;

// site it

OleInterop.IServiceProvider sp =

(OleInterop.IServiceProvider)

GetService(typeof(OleInterop.IServiceProvider));

IObjectWithSite ows = (IObjectWithSite)textLines;

ows.SetSite(sp);

// Create a codewindow to use as our toolwindow.

hr = localRegistry.CreateInstance(typeof(VsCodeWindowClass).GUID,

null, ref guidCodeWindow,

Microsoft.VisualStudio.NativeMethods.CLSCTX_INPROC_SERVER,

out objPtr);

Debug.Assert(hr == 0, "Failed to create instance of

CodeWindow");

IVsCodeWindow codeWindow =

Marshal.GetObjectForIUnknown(objPtr) as IVsCodeWindow;

Marshal.Release(objPtr);

objPtr = IntPtr.Zero;

// Attached codewindow to buffer

codeWindow.SetBuffer(textLines);

// Use IVsUIShell::CreateToolWindow to create the frame.

IVsUIShell vsUiShell =

(IVsUIShell)GetService(typeof(SVsUIShell));

hr = vsUiShell.CreateToolWindow((uint)

( __VSCREATETOOLWIN.CTW_fForceCreate),

0, codeWindow,

ref guidNull,

ref guidPersistenceSlot,

ref guidNull,

null,

"VB Code Editor ToolWindow",

position,

out windowFrame);

if(NativeMethods.Failed(hr))

return hr;

// Make it a VB code window by default

hr = textLines.SetLanguageServiceID(ref GuidList.guidVBLangSvc);

// enable editor key bindings

hr = windowFrame.SetGuidProperty(

(int) __VSFPROPID.VSFPROPID_InheritKeyBindings,

ref GuidList.guidCmdUI_TextEditor);

Comments

  • Anonymous
    August 29, 2004
    Are these all of the steps necessary to deploy a VSIP to a user's machine or is this just what an individual developer should do on his or her machine to get started writing their own VSIP? I think it's the former, but wanted to check to be sure.
  • Anonymous
    August 29, 2004
    I am not sure you can hook up intellisense. Assigning language service to the text buffer provides colorization, but that is pretty much it. For example, when you choose Open With... and open HTML file in Text Editor, it still gets colorized even when you don't see Design and Source tabs. This is because colorizer is still getting invoked. HOWEVER, HTML editor does not gets instantiated. I am sure that HTML editor (that I own) cannot be hosted in a random toolwindow, sorry :-) As far as I know, VB intellisense is driven from a compiler parse tree so you'll have to create a compiler probject, provide all required references and create all required helper objects.
  • Anonymous
    August 30, 2004
    There is a rather timely article about VSIP package deployment on the Microsoft extensibility blog (Dr Ex). Due to some recent Clover.NET experiences I think there are a few additional points to be made. Most of the problems we had...
  • Anonymous
    September 01, 2004
    Is it possible to do the hosting in .NET as well? Are there any examples available?

    Great article. Congrats.

    Cris
  • Anonymous
    September 10, 2004
    Is there any programatically way to reset package inforations without calling devenv /setup ? The devenv /setup reset any toolbars which sometimes is not what the user want.