
- •Добавление к com-серверу поддержки событий
- •Создание модели взаимодействия приложения хоста с плагинами
- •Описание com-интерфейсов, связанных с поддержкой плагинов
- •Создание com-интерфейсов, связанных с поддержкой плагинов
- •Создание com-классов, связанных с поддержкой плагинов
- •Создание класса, отвечающего за взаимодействие с плагинами
- •Код класса Plugin.Cs
- •Внесение косметических изменений в серверную часть
- •Строим своё меню с плагинами и идентификаторами
- •Вносим изменения в главную форму сервера
- •Создание первого плагина
- •Импорт типов с сервера
- •Создание класса для хранения внутреннего представления точек
- •Создание форм редактирования данных о точках
- •Реализация форм редактирования данных о точках
- •Реализация класса первого плагина
- •Создание третьего плагина
- •Делаем наш плагин com-видимым
- •Создание главной формы плагина
- •Реализация класса третьего плагина
- •Создание инсталлятора для плагина
- •Создание второго плагина
- •Создание главной формы плагина
- •Создание библиотеки типов
- •Реализация формы второго плагина
- •Реализация класса второго плагина
- •Добавление метода GetComClassName
- •Data Execution Prevention и его отключение
- •Тестирование совместной работы клиента и плагинов
- •Исходный код
Строим своё меню с плагинами и идентификаторами
Мы договорились, что действия наших плагинов будут доступны через меню главного окна сервера. У меня оно выглядит вот так:
Для этого я решил унаследовать класс от ToolStripMenuItem, элемента меню. Я хотел сделать так, чтобы при нажатии на пункт меню генерировалось событие, содержащие в себе некоторый идентификатор плагина и идентификатор вызываемого в нём действия.
Чтобы повторить мои шаги, создадим новый класс
Сначала мы подключим пару неймспейсов.
using System.Windows.Forms;
using System.Runtime.InteropServices;
Теперь опишем аргументы события выбора пункта меню. Для этого мы унаследуемся от класса EventArgs, как это принято в .NET. Обратите внимание на то, что класс помечен как COM-невидимый, ведь COM-клиентам он не нужен. То же самое справедливо и для всех остальных классов, которые будут заданы в этом конкретном файле – ВСЕ они будут с аттрибутом [ComVisible(false)].
/// <summary>
/// Аргументы события нажатия на элемент меню действий плагина.
/// </summary>
[ComVisible(false)]
public class PluginToolStripMenuItemClickEventArgs : EventArgs
{
int pluginId;
int actionId;
/// <summary>
/// Конструктор аргументов события.
/// </summary>
/// <param name="pluginId">Уникальный идентификатор плагина, для которого запрошено действие.</param>
/// <param name="actionId">Уникальный идентификатор действия данного плагина.</param>
public PluginToolStripMenuItemClickEventArgs(int pluginId, int actionId)
{
this.pluginId = pluginId;
this.actionId = actionId;
}
/// <summary>
/// Уникальный идентификатор плагина, для которого запрошено действие.
/// </summary>
public int PluginId
{
get
{ return pluginId; }
}
/// <summary>
/// Уникальный идентификатор действия данного плагина.
/// </summary>
public int ActionId
{
get { return actionId; }
}
}
Прямо в этом же файле описываем делегат обработчика события нажатия на пункт меню.
/// <summary>
/// Делегат обработчика события нажатия на элемент меню действий плагина.
/// </summary>
/// <param name="sender">Источник события.</param>
/// <param name="e">Аргументы события.</param>
[ComVisible(false)]
public delegate void PluginToolStripMenuItemClickEventHandler(object sender, PluginToolStripMenuItemClickEventArgs e);
И, наконец, описываем класс-наследник ToolStripMenuItem.
[ComVisible(false)]
public partial class PluginToolStripMenuItem : ToolStripMenuItem
{
}
Сначала добавим в него непосредственно нужное нам событие.
/// <summary>
/// Событие нажатия на элемент меню действий плагина.
/// </summary>
public event PluginToolStripMenuItemClickEventHandler PluginActionRequested;
И пару необходимых переменных для хранения идентификаторов плагина и действия.
private int pluginId, actionId;
Теперь определим конструктор класса, в который необходимо будет передавать эти самые идентификаторы.
/// <summary>
/// Конструктор PluginActionRequested.
/// </summary>
/// <param name="pluginId">Уникальный идентификатор плагина.</param>
/// <param name="actionId">Уникальный идентификатор действия плагина.</param>
public PluginToolStripMenuItem(int pluginId, int actionId)
{
this.pluginId = pluginId;
this.actionId = actionId;
}
Затем переопределим метод базового класса, вызывающий событие OnClick и будем генерировать перед событием клика по пункту меню наше событие.
/// <summary>
/// Переопределение метода OnClick базового класса.
/// </summary>
protected override void OnClick(EventArgs e)
{
if (PluginActionRequested != null)
PluginActionRequested(this, new PluginToolStripMenuItemClickEventArgs(pluginId, actionId));
base.OnClick(e);
}
Этот клас тоже готов.