Silverlight Sample (Delphi)

The Silverlight sample demonstrates the interaction between a Delphi host and a Silverlight plugin. This sample shows how to load and show a Silverlight plugin inside a Delphi host, and how to establish communication between host and plugin.

Examine the Plugin

For this sample we have a Silverlight plugin that shows animated text and is able to send messages to the host application. If you need more information on how to create Silverlight plugins, please refer to this article.

This plugin is supposed to communicate with the host app, so it requires special security settings to be able to send data out of the Silverlight sandbox. To allow it to do so, it should run in the so-called Elevated Trust Mode.

To enable it, go to the "Silverlight" page in "Project -> Properties" and check "Enable running application out of the browser":

Click on the Out-of-Browser Settings button and check Require elevated trust when running outside the browser:

The plugin contains only one method, a button click handler that is used to send data to the host. Take a look at this code:

private void SendButton_Click(object sender, RoutedEventArgs e)
{
  if (AutomationFactory.IsAvailable)
  {
    dynamic Host = AutomationFactory.CreateObject("Hydra.Host");
    if (Host != null)
    {
      Host.SendMessage(MessageBox.Text);
    }
  }
}

Let's go through this snippet step-by-step:

  • AutomationFactory.IsAvailable - We need to perform this check first to ensure that we can use AutomationFactory methods.
  • dynamic Host = AutomationFactory.CreateObject("Hydra.Host"); - Asking for a host object with a specified name (the name of the object is user defined). The host will handle this call and return a reference to the host object.
  • Host.SendMessage(MessageBox.Text); - Now that we have a reference to the host object, we can use its properties or call its methods. Please note that since Silverlight allows only late binding, there will be no IntelliSense support or compiler warnings to help prevent errors.

As you can see, we are using dynamic. In order to do so we need to add a reference to the Microsoft.CSharp.dll assembly.

Go to Project -> Add Reference and select Microsoft.CSharp.dll.

Examine the Host

Our host is a Delphi application that is able to show the Silverlight plugin and to receive messages from the plugin. For more information on how to create a Delphi VCL host application, please refer to this article.

Let's take a look at the major parts:

type
  TMainForm = class(TForm)
    ModuleManager: THYModuleManager;
    [...]
  private
    Instance: IHYVisualPlugin;
    [...]
  end;

As you can see, the main form is a regular Delphi VCL form, and can be used in the exact same way as any regular form. There are two key items here:

First we need to load the plugin module with the OnCreate event handle:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  ModuleManager.LoadModule('SilverlightPlugin.xap');
  ModuleManager.CreateVisualPlugin('SilverlightPlugin', Instance, PluginContainer);
end;
  • ModuleManager.LoadModule - This method allows you to load a plugin module with a specified path. Module manager will automatically detect the type of the module and will use the appropriate method. It also provides a couple of methods for module loading, such as loading from a list of file names or loading using a search pattern.
  • ModuleManager.CreateVisualPlugin - This method will create an instance of a plugin with the specified name and assign this instance to the Instance variable we defined above. It can also show the plugin content in a container represented here by PluginContainer.

To be able to process calls from the plugin, we have a OnGetAutomationObject event handler. Take a look at the code:

procedure TMainForm.ModuleManagerGetAutomationObject(Sender: THYModuleManager; const ProgId: string;
  const Flags: THYGetAutomationObjectFlags; var Disp: IDispatch);
begin
  if ProgId='Hydra.Host' then
    Disp := TCustomObject.Create(LogBox);
end;

First it checks for a ProgId, and, if plugin is asking for the host object, it creates a new instance of TCustomObject and returns it to the plugin.

TCustomObject

TCustomObject is the custom object that represents the host. This object is returned to the plugin so it can call its methods. Take a look at the TCustomObject definition:

  TCustomObject = class (THYDispatchWrapper)
  private
    fListBox: TListBox;
  public
    constructor Create(ListBox: TListBox);

    //this method will be called by a plugin
    procedure SendMessage(const Message: WideString);
  end;

As you can see, the custom objects is inherited from the THYDispatchWrapper class. This class will automatically process calls from the Silverlight side and route them to the appropriate methods or properties.

Please note that in order to be visible to Silverlight, your methods must be placed in the public section and properties should be in the published section.

Putting Everything Together

Now that we've examined all major parts of the sample, we can build both plugin and host. After you launch the sample, you should get the following result:

Concepts Covered