Non-Visual Plugins (.NET Framework)
In this article we will describe how to create a new non-visual plugin, and talk about what features it provides and how they can be used.
Getting Started
Before we start to create our first plugin, let's look at what a Hydra plugin project involves.
A Hydra plugin project consists of three parts:
- Plugin Module - A Class Library project that acts as a container for a module controller and can hold a set of plugins.
- Module Controller - An entry point of a module. The module controller supplies the host with information about stored plugins and provides methods that allow the host to instantiate and work with plugins.
- Plugins - Special classes stored inside the plugin module.
Now let's create and setup a Hydra plugin project and add a non-visual plugin to it.
Working with Wizards
First we need to create a new module. To do this, select File -> New -> Project in the Visual Studio menu, choose the language you need (we provide templates for C#, VB.NET and Oxygene for .NET), and then, in the RemObjects Hydra category, choose Plugin Module:
In this dialog you also need to enter a project name and a destination folder.
After you press the OK button, the wizard will create a new plugin module and add a module controller to the project. More on how to setup the module controller later in this article.
Now that we have a plugin module, we can add a plugin to it. Select Project -> Add New Item from the VS menu and then select Non-Visual Plugin:
Select a name for the new plugin and press the Add button. And with this, we are done: the wizard will add a new non-visual plugin to the project.
The plugin module can contain as much plugins as you want, and you can also have visual and non-visual plugins in the same project.
Review the project
Now let's review the project. It has three parts:
Plugin Module
The plugin module is a Class Library project that will produce an assembly file that can be used by any of the supported host platforms.
The wizard automatically adds a reference to the RemObject.Hydra.dll assembly that contains the Hydra core classes. If you use this plugin module with Delphi (VCL or FireMonkey) hosts, you will need this file to be present in the same folder with the plugin, so you may want to tune your project so it will automatically copy core dll into the destination folder. To do so, select Properties in the RemObjects.Hydra.dll:
On the Properties page set CopyLocal to true:
In the AssemblyInfo.cs, you will need to set the following assembly attribute:
[assembly: ComVisible(true)]
Please do not change this attribute, it will allow the host application to access the interfaces exposed by the plugin.
Module Controller
The module controller is a class that acts as an entry point for the plugin module. The host will instantiate this class on module load to get information about the plugins.
The wizard generates the following code for the module controller:
[ModuleController]
TheModuleController = public partial class(RemObjects.Hydra.ModuleController)
private
protected
method Dispose(aDisposing: boolean); override;
public
constructor;
end;
[ModuleController]
public partial class TheModuleController : ModuleController
{
public TheModuleController()
{
InitializeComponent();
}
}
The module controller is inherited from ModuleController
that itself descends from System.ComponentModel.Component
. By
default the controller holds two image lists that can be shared with the
host application.
Also please take note of the ModuleControllerAttribute
, it allows you to set additional meta-data, for example:
[ModuleController(Name := 'Controller', Description := 'My module controller', UserData := 'Data')]
public partial class TheModuleController : ModuleController
[..]
[ModuleController(Name = "Controller", Description = "My module controller", UserData = "Data")]
TheModuleController = public partial class(RemObjects.Hydra.ModuleController)
[..]
NonVisual Plugins
Non-Visual plugins are components that can be used from a host
application and don't provide a GUI. They are inherited from the class that
allow them to be used in a cross-platform environment, this control is
inherited from System.ComponentModel.Component,
, so it provides the same design surface as regular
.NET components does.
The code generated by the wizard looks like this:
[Plugin, NonVisualPlugin]
public partial class Plugin1 : NonVisualPlugin
{
public Plugin1()
{
InitializeComponent();
}
}
Please do not remove the PluginAttribute and the VisualPluginAttribute, they are used by the host application to indicate that the class is indeed a plugin and also used to read plugin meta-data.
As in the module controller you can set the meta-data manually:
[Plugin(Name := 'SamplePlugin', Description := 'This is sample plugin', UserData := 'Data'), VisualPlugin]
TPlugin1 = class(NonVisualPlugin)
[..]
[Plugin(Name = "SamplePlugin", Description = "This is sample plugin", UserData = "Data"), NonVisualPlugin]
public partial class Plugin1 : NonVisualPlugin
[..]
Using the plugin
By now you will have a complete project that can be loaded by all supported host platforms without any additional work.
Both the module controller and the non-visual plugin provide a set of internal methods that are used by the Hydra framework to perform specific tasks, however, they also provide some useful methods and properties that can be used in your own application.
Below we will describe the most common way to use the module controller and plugin, but first let us make a note. One of the major parts of the Hydra framework are custom interfaces. Custom interfaces are user-defined interfaces that can be used in a cross-platform environment (they can, for example, be shared between a .NET plugin and a Delphi host application) to receive access to data or to call a host or plugin method. When we talk about things like "accessing host methods", we refer to the custom interfaces, but since this is a large topic, we can't cover it all in this article, so if you feel like you need to use them, please take a look at this article: Passing Interfaces between Host and Plugins
Before we start to describe the non-visual plugin itself, let's look at how to use the module controller.
How to use Module Controller
While the main purpose of the module controller is to provide information about the plugin to the host, it can also be useful for some specific task.
The host will instantiate the module controller only once on a module load, so it can be used to initialize some global data or allow the host to gain access to global methods via custom interfaces.
By default the module controller holds two ImageList
controls, assigned to the
SmallImages and LargeImages properties. These image lists will be
passed to the host application, so you can use them to store shared
images.
The ModuleController
also has an event called HostChanged
. This is an important event if you
need to be able to access host methods or data. Since the controller is
initialized on module load, it doesn't have access to the Host property
at the time its constructor is executed. When the host assigns its
reference to the module controller, the HostChanged
event is fired
so you can safely get access to the host. One thing that you need to
consider is that this event can be called with a null
host reference (when the host
unloads a module), so you need to check this before accessing host
members.
The last thing that is available to the module controller is the Host property. This property holds the reference to the host object, and can be used to access host methods or data.
How to use the NonVisual Plugin
.NET non-visual plugins are derived from Component
and provide exactly the same
design surface, so you can use them in the same way as regular
components. The biggest difference is, of course, that you can load these
plugins into any supported host application.
Like the module controller, the NonVisualPlugin
provides access to the Host property and the
HostChanged event, so everything that was said above for the module
controller also applies to the non-visual plugin.
The non-visual plugin provides a set of events that can be called by the host application:
- OnStart
- OnStop
- OnPause
- OnResume
These events can be triggered from the host by calling the corresponding methods (Start, Stop, etc).
Non-visual plugins also provide the ability to define a set of actions that can be accessed and executed from the host. The Actions property holds a list that you can edit in design time by using the embedded editor:
Each Action
provides an ability to set things like caption, hint and assign even handlers to OnExecute
and OnUpdate
.
You can also assign an image to each action; for this purpose, the non-visual
plugin provides an Images property that takes regular ImageList
.
If you plan to use the non-visual plugin in a Delphi host, you can also use its ability to work with menus and toolbars. To do this, you need to define a set of menus or toolbars in the Toolbars property; the following screenshot shows the design-time editor:
If you need more information on how to work with actions, menus and tool-bars, please refer to the Hydra support for Menus and Toolbars article.