head.WriteLine()

Mittwoch, Januar 30, 2008

Ein Command-Modell für System.AddIn, Teil 2

Nachdem ich im ersten Teil bereits mein Command-Modell und dessen Integration in die Host-Anwendung beschrieben habe, soll es nun um die Add-In-Seite gehen.

Während der Aktivierung ruft die AddInHost-Komponente die InitializeCommands()-Methode des Add-In auf. Hierbei wird eine Instanz von ICommandContext übergeben, über die das Add-In Zugriff auf ICommandService und IUIContextService hat. Über diese Interfaces läuft im weiteren Verlauf die Kommunikation. Die folgende Abbildung zeigt den grundlegenden Ablauf.

CommandCommunication

Das Add-In muss nun zunächst die vom Host angebotene Command-Struktur ermitteln, um sich im Anschluss in diese integrieren zu können.

public override void InitializeCommands(ICommandContext context)
{
  // CommandService und UICommandService ermitteln
  ICommandService cmdSrv = context.CommandService;
  IUICommandService cmdUISrv=context.UICommandService;

  // File-Commands ermitteln
  ICommand fileCmd = cmdSrv.GetCommand("Host.File");
  IUICommand fileUICmd = cmdUISrv.GetUICommand(
      fileCommand, UICommandType.MenuCommand);

  // Toolbar ermitteln
  IUICommand toolbarUICmd = cmdUISrv.GetMainToobar();

...

}

Hier werden die ICommand- und IUICommand-Objekte des File-Menüs, sowie die primäre Toolbar ermittelt. Daraufhin können neue Elemente eingefügt werden:

// "Neu"-Command erstellen
ICommand fileNewCmd = cmdSrv.CreateCommand(
  "FirstAddIn.File.New",
  fileCmd);

Hierbei werden ein eindeutiger Name, sowie das jeweils übergeordnete Command-Objekt angegeben. Dazu passend können nun entsprechende Menü- und Toolbar-UICommands erstellt werden:

// "Neu"-UICommand erstellen
IUICommand fileNewUICmd = UICmdSrv.CreateMenuItem(
  fileNewCmd,
  "&Neu",
  fileUICmd,
  0,
  ToolStripItemDisplayStyle.ImageAndText,
  UICmdSrv.GetIconArray(Properties.Resources.New));

In diesem Fall wird ein Menüelement erstellt und hierbei das zugehörige ICommand-Objekt, ein Anzeigetext, das übergeordnetes IUICommand-Objekt, ein Index, sowie der Darstellungsstil und ein Symbol angegeben. Da Bilder in Form von Byte-Arrays über die AppDomain-Grenze geschickt werden, müssen sie über die GetIconArray()-, bzw. GetImageArray()-Methode entsprechend konvertiert werden.

Darüber hinaus können zusätzliche Eigenschaften wie Visible, Checked oder ShortcutKeys festgelegt werden.

Die Erstellung von Toolbar-Elementen erfolgt analog, nur dass hierfür die CreateToolbar()-Methode aufzurufen ist. Darüber hinaus können mit der CreateSeparator()-Methode Separatorelemente für Menü und Toolbar erstellt werden.

Wurde ein Command auf Host-Seite aktiviert, so ruft der Host die NotifyCommandExecuted()-Methode des Add-In auf und übergibt hierbei die jeweilige ICommand-Instanz.

Das Add-In kann daraufhin beispielsweise seine Oberfläche anzeigen. Hierfür bietet die CommandContext-Klasse die ShowSurface()-Methode, welche als Parameter eine WindowProxy-Instanz übergeben bekommt (Details hier).

public override void NotifyCommandExecuted(ICommand command)
{
  if (command == m_fileNewCommand)
  {
    m_surface = new Surface();
    m_context.ShowSurface(new WindowProxy(m_surface));
  }
}

Surface ist ein User Control, welches von AddInSurface ableitet und die Oberfläche des Add-In enthält. Die Einzelheiten dieser Komponente habe ich bereits hier beschrieben.

Die Sourcen inkl. Beispielanwendung gibt's hier.

3 Comments:

  • Kewl...

    Ein Problem habe ich allerdings.

    Wenn ich im AddInSurface
    Form myForm = this.FindForm();
    aufrufe, kriege ich nix.

    Any idea?

    By Anonymous Anonym, at März 24, 2008 6:53 PM  

  • Zudem habe ich bemerkt, dass die Pfeil-Tasten in der TextBox eines AddIns nicht funktionieren.

    Woran mag das liegen?

    By Anonymous Anonym, at April 01, 2008 12:33 AM  

  • Zu Problem 1:
    Das Ermitteln der Form über FindForm() funktioniert nicht, da sich das Add-In-Control und die Form in zwei separaten AddDomains befinden. Eine Synchronisation macht auch nicht wirklich Sinn, da das Add-In über diesen Weg sonst die Kontrolle über den Host übernehmen könnte. Statt dessen sollte der Host die entsprechende Funktionalität über den Add-In-Contract bereitstellen.

    Zu Problem 2:
    Ich habe das Problem behoben und die aktuelle Version hier bereit gestellt (siehe auch aktuellen Blog Post).

    By Blogger Jörg Neumann, at April 22, 2008 1:19 PM  

Kommentar veröffentlichen

<< Home