Thursday, October 12, 2006

Brief guide to building a Delphi IDE AddIn

Someone in the Delphi IDE newsgroup asked the question, "Is there a guide anywhere about writing IDE addins"? After experiencing my own pain in building a small add-in (or is it plug-in?), I decided to make up a quick post. The answer to his question is a resounding "no." Well, you might consider this as something of a guide, but I had better luck getting started with these 2 docs:

The first thing to note is that I found that writing the add-in in .Net seemed to make it work for both Win32 and .Net Delphi projects.

When I started mine, I was really naive and thought there'd be some API with calls like GetStartNextMethod or something. You only get the buffer.

So here's the start - getting the source editor (sorry - snippets lost their formatting - too much work to put back in using blogger):

using Borland.Studio.ToolsAPI;

public class SourceViewer // base class
{
protected IOTASourceEditor fSourceEditor;
public IOTASourceEditor sourceEditor { get { return fSourceEditor; } }
public SourceViewer()
{
IOTAModuleServices moduleServices = BorlandIDE.ModuleServices;
if ( moduleServices == null )
{
fSourceEditor = null;
}
else
{
try
{
fSourceEditor = moduleServices.CurrentModule.CurrentEditor as IOTASourceEditor;
}
catch
{
fSourceEditor = null;
}
}
}
}


Then you use the source editor to get a reader to get the text of the buffer:

IOTAFileReader reader = fSourceEditor.CreateReader();

private string getRawSourceText( IOTAFileReader reader )
{
const int READ_CHUNK = 1600;

if (reader == null)
throw new Exception( "No file reader" );

StringBuilder sb = new StringBuilder();
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
Byte[] source = reader.Read( READ_CHUNK, 0 );
while ( source.Length > 0 )
{
sb.Append( enc.GetString(source) );
source = reader.Read( READ_CHUNK, 0 );
}

return sb.ToString();
}



To get the IDE to integrate your AddIn, implement IOTAMenuWizard:

public class TestPlugIn: IOTAMenuWizard
{

public static void Register()
{
IOTAWizardService WizService = (IOTAWizardService)BorlandIDE.GetService( typeof( IOTAWizardService ) );
wizardID = WizService.AddWizard( new TestPlugIn() );
}
....

Then implement the other methods of IOTAMenuWizard such as execute and enabled. I wanted mine to be enabled when any source file is open (referencing the first class above):

return new SourceViewer().sourceEditor != null;

Once your assembly is ready to go, register it with the IDE (so the IDE will load it on startup):
  • Create a key under HKEY_CURRENT_USER\Software\Borland\BDS\4.0\Known IDE Assemblies.
  • Give the key a name (don't recall if the name matters / where it might show up, but I think it has to have a name).
  • Add the path to your assembly there.

No comments: