Рейтинг блогов

Как сделать программку с поддержкой плагинов?

дата добавления: 29 ноября 2007 / 08:32, просмотров: 18735, комментариев: 6
В данном небольшом обзоре я расскажу и покажу, как можно сделать программу с поддержкой плагинов (plug-in's) средствами Visual Basic .NET и C#.

Программа


Первым делом надо определиться с программой, и тем, что мы будем «плагинить». Чтобы далеко не ходить, создадим обычное Windows-приложение, и на форме разместим одно текстовое поле (TextBox) и одну менюшку (MenuStrip). У TextBox-а поставим свойства Multiline = True и Dock = Fill, еще можно ScrollBars изменить, если не лень :)
Также дополнительно разместим на форме диалоги OpenFileDialog и SaveFileDialog.
Далее, визуально в меню добавим следующие элементы:

Структура Имена элементов
Файл
..Создать
..Открыть
..Сохранить
..-------------
Выход
[mnuFile]
[mnuNew]
[mnuOpen]
[mnuSave]
[Separator]
[mnuExit]

Теперь напишем в нашу программку небольшой код:

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
Public Class Form1

 Private _CurrentFile As String = ""

 Private Sub mnuNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuNew.Click
  TextBox1.Text = ""
 End Sub

 Private Sub mnuOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuOpen.Click
  If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
   _CurrentFile = OpenFileDialog1.FileName
   Dim myRead As New IO.StreamReader(_CurrentFile, System.Text.Encoding.GetEncoding(1251))
   TextBox1.Text = myRead.ReadToEnd
   myRead.Close()
  End If
 End Sub

 Private Sub mnuSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuSave.Click
  If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
   _CurrentFile = SaveFileDialog1.FileName
   Dim myWrite As New IO.StreamWriter(_CurrentFile, False, System.Text.Encoding.GetEncoding(1251))
   myWrite.Write(TextBox1.Text)
   myWrite.Close()
  End If
 End Sub

 Private Sub mnuExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuExit.Click
  Me.Close()
 End Sub

 Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
  If e.CloseReason = CloseReason.UserClosing Then
   If MsgBox("Вы действительно хотие выйти из программы?", MsgBoxStyle.Question Or MsgBoxStyle.YesNo) = MsgBoxResult.No Then e.Cancel = True
  End If
  End
 End Sub

 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  OpenFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*"
  SaveFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*"
 End Sub

End Class

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PluginSample
{
 public partial class Form1 : Form
 {

  private string _CurrentFile = "";

  public Form1()
  {
   InitializeComponent();
  }

  private void mnuNew_Click(object sender, EventArgs e)
  {
   textBox1.Text = "";
  }

  private void mnuOpen_Click(object sender, EventArgs e)
  {
   if (openFileDialog1.ShowDialog() == DialogResult.OK)
   {
    _CurrentFile = openFileDialog1.FileName;
    System.IO.StreamReader myRead = new System.IO.StreamReader(_CurrentFile, System.Text.Encoding.GetEncoding(1251));
    textBox1.Text = myRead.ReadToEnd();
    myRead.Close();
   }
  }

  private void mnuSave_Click(object sender, EventArgs e)
  {
   if (saveFileDialog1.ShowDialog() == DialogResult.OK)
   {
    _CurrentFile = saveFileDialog1.FileName;
    System.IO.StreamWriter myWrite = new System.IO.StreamWriter(_CurrentFile, false, System.Text.Encoding.GetEncoding(1251));
    myWrite.Write(textBox1.Text);
    myWrite.Close();
   }
  }

  private void mnuExit_Click(object sender, EventArgs e)
  {
   this.Close();
  }

  private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
  {
   if (e.CloseReason == CloseReason.UserClosing)
   {
    if (MessageBox.Show("Вы действительно хотие выйти из программы?", "Выход?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) e.Cancel = true;
   }
  }

  private void Form1_Load(object sender, EventArgs e)
  {
   openFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*";
   saveFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*";
  }
 }
}

Как видите, это нечто похожее на блокнот, естественно здесь много сырых моментов, но для примера этого вполне достаточно.

Интерфейс


Для реализации поддержки плагинов, нам понадобится интерфейс. Чтобы опять таки далеко не ходить, добавим интерфейс прямо в нашу программку, для этого просто нужно создать новый класс (меню Проект => Добавить класс (Project => Add class...), или меню Проект => Добавить... (Project => Add item...)). Назовем его IPlugin.
Интерфейс IPlugin будет описывать стандартные свойства, события, методы и функции наших будущих плагинов. Собственно, чтобы интерфейс стал интерфейсом, его надо объявить оператором Interface:

VB .NET
001:
002:
003:
Public Interface IPlugin
'...
End Interface

C#
001:
002:
003:
004:
005:
006:
007:
namespace PluginSample
{
 public interface IPlugin
 {
 // ...
 }
}

Чтобы все слишком сильно не усложнять, в нашем интерфейсе будет описано всего несколько свойств и процедур:

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
Public Interface IPlugin

 ReadOnly Property Name() As String
 ReadOnly Property Version() As Version
 ReadOnly Property Description() As String
 ReadOnly Property AuthorName() As String

 Sub Initialize(ByVal MainContainer As Object)
 Sub Dispose()

End Interface

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
namespace PluginSample
{
 public interface IPlugin
 {
  string Name { get; }
  Version Version { get; }
  string Description { get; }
  string AuthorName { get; }

  void Initialize(object MainContainer);
  void Dispose();
 }
}

Свойство Name будет содержать название плагина, свойство Version – его версию, свойство Description – краткое описание плагина, а свойство AuthorName – имя автора плагина. Хотя информацию о плагине можно передавать и в любом другом виде, например через функцию.

Процедура Initialize, будет выполняться при инициализации плагина, а Dispose, соответственно, при его удалении.

В принципе интерфейс у нас готов, теперь можно компилировать весь проект, и заняться разработкой самих плагинов.

Плагины


Сделаем один небольшой плагин, который будет добавлять дополнительные элементы в меню нашей основной программы, и выполнять какие-нибудь хитрые действия над текстом в текстовом поле. Плагин мы будем делать в новом проекте. Для этого можно добавить новый проект, типа ClassLibrary в уже имеющийся солюшин (Solution): меню Файл => Добавить => Новый проект... (File => Add => New Project...). В появившемся окне выберите ClassLibrary.
Назовем этот проект Text2Hex. Как вы уже, наверное, догадались из названия, этот плагин будет преобразовывать текст в Hex (шестнадцатеричное представление) и обратно.
Имя класса, по большому счету, значения не имеет, поэтому его можно оставить без изменений. Далее, нам надо подключить нашу основную программу к нашему плагину. Если вы помните, интерфейс IPlugin находится у нас именно в нашей основной программе, и для реализации этого интерфейса в нашем плагине, нам нужно включить сборку программы в проект плагина. В будущем, вы уже самостоятельно, при желании, можете вынести интерфейс в отдельную сборку.
Для добавления ссылки на предыдущий проект, выберите меню Проект => Добавить ссылку (Project => Add Reference..), в появившемся окне выберите вкладку «Обзор» (Browser) и найдите файл нашей компилированной программы (см. первую часть статьи), выберите его, и нажмите «Ok»
Также добавьте ссылку на System.Windows.Forms (на кладке .NET) (в C# также может потребоваться ссылка на System.Drawing).
Далее, импортируем пространство Namespace нашей программы, у меня это PluginSample и System.Windows.Forms, и затем, используя оператор Implements (в C# - двоеточие (:)), реализуем интерфейс IPlugin в нашем будущем плагине:

VB .NET
001:
002:
003:
004:
005:
006:
007:
Imports PluginSample
Imports System.Windows.Forms

Public Class Class1
 Implements IPlugin
'...
End Class

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using PluginSample;

namespace Text2Hex
{
 public class Class1 : IPlugin
 {
 // ...
 }
}

Далее, пропишем значения свойств плагина:

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
Public ReadOnly Property AuthorName() As String Implements PluginSample.IPlugin.AuthorName
 Get
  Return "Aleksey S Nemiro"
 End Get
End Property

Public ReadOnly Property Description() As String Implements PluginSample.IPlugin.Description
 Get
  Return "Плагин преобразует текст в шестнадцатеричный код и обратно"
 End Get
End Property

Public ReadOnly Property Name() As String Implements PluginSample.IPlugin.Name
 Get
  Return "Text2Hex"
 End Get
End Property

Public ReadOnly Property Version() As System.Version Implements PluginSample.IPlugin.Version
 Get
  Return New Version(1, 0, 0, 0)
 End Get
End Property

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
public string AuthorName
{
 get { return "Aleksey S Nemiro"; }
}

public string Description
{
 get { return "Плагин преобразует текст в шестнадцатеричный код и обратно"; }
}

public string Name
{
 get { return "Text2Hex"; }
}

public Version Version
{
 get { return new Version(1, 0, 0, 0); }
}

А теперь самое главное, займемся написанием процедупы Initialize. В процедуру Initialize, согласно нашему интерфейсу, у нас передается объект MainContainer, который должен содержать ссылку на форму нашей программы. Собственно, в интерфейсе можно было бы сразу прописать тип данных, но для большей универсальности, у нас используется тип Object.
В нашей программе, как вы помните, есть меню, и текстовое поле. Чтобы с ними работать, нам надо их найти, и искать мы их будет по имени.

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
Dim frm As Form = CType(MainContainer, Form)
Dim mnu As MenuStrip = Nothing
'получаем меню формы
If frm.Controls.Find("MenuStrip1", False) IsNot Nothing AndAlso frm.Controls.Find("MenuStrip1", False).Length > 0 Then
 mnu = frm.Controls.Find("MenuStrip1", False)(0)
End If
'получаем текстовое поле
If frm.Controls.Find("TextBox1", False) IsNot Nothing AndAlso frm.Controls.Find("TextBox1", False).Length > 0 Then
 _textBox = frm.Controls.Find("TextBox1", False)(0)
End If

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
Form frm = (Form)MainContainer;
//получаем меню формы
MenuStrip mnu = null;
if (frm.Controls.Find("MenuStrip1", false) != null && frm.Controls.Find("MenuStrip1", false).Length > 0)
{
 mnu = (MenuStrip)frm.Controls.Find("MenuStrip1", false)[0];
}
//получаем текстовое поле
if (frm.Controls.Find("TextBox1", false) !=null && frm.Controls.Find("TextBox1", false).Length > 0)
{
 _textBox = (TextBox)frm.Controls.Find("TextBox1", false)[0];
}

Теперь, у нас есть ссылка на меню, и на текстовое поле формы основной пограммы, и мы можем делать с ними все, что захотим. Первым делом добавим новые пункты в меню:

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
'создаем новые элементы меню
Dim myText2HexMenu As New ToolStripMenuItem
myText2HexMenu.Text = "Text2Hex"
Dim myConvertText2HexMenu As New ToolStripMenuItem
Dim myConvertHex2TextMenu As New ToolStripMenuItem
Dim myAboutMenu As New ToolStripMenuItem
AddHandler myConvertText2HexMenu.Click, AddressOf ConvertText2HexMenu_Click
AddHandler myConvertHex2TextMenu.Click, AddressOf ConvertHex2TextMenu_Click
AddHandler myAboutMenu.Click, AddressOf AboutMenu_Click
myConvertText2HexMenu.Text = "Конвертировать текст в hex"
myConvertHex2TextMenu.Text = "Конвертировать hex в текст"
myAboutMenu.Text = "О Text2Hex..."
myText2HexMenu.DropDownItems.Add(myConvertText2HexMenu)
myText2HexMenu.DropDownItems.Add(myConvertHex2TextMenu)
myText2HexMenu.DropDownItems.Add(New ToolStripSeparator())
myText2HexMenu.DropDownItems.Add(myAboutMenu)
'добавляем новые элементы меню на форму
mnu.Items.Add(myText2HexMenu)

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
//создаем новые элементы меню
ToolStripMenuItem myText2HexMenu = new ToolStripMenuItem();
myText2HexMenu.Text = "Text2Hex";
ToolStripMenuItem myConvertText2HexMenu = new ToolStripMenuItem();
ToolStripMenuItem myConvertHex2TextMenu = new ToolStripMenuItem();
ToolStripMenuItem myAboutMenu = new ToolStripMenuItem();
myConvertText2HexMenu.Click += new EventHandler(ConvertText2HexMenu_Click);
myConvertHex2TextMenu.Click += new EventHandler(ConvertHex2TextMenu_Click);
myAboutMenu.Click += new EventHandler(AboutMenu_Click);
myConvertText2HexMenu.Text = "Конвертировать текст в hex";
myConvertHex2TextMenu.Text = "Конвертировать hex в текст";
myAboutMenu.Text = "О Text2Hex...";
myText2HexMenu.DropDownItems.Add(myConvertText2HexMenu);
myText2HexMenu.DropDownItems.Add(myConvertHex2TextMenu);
myText2HexMenu.DropDownItems.Add(new ToolStripSeparator());
myText2HexMenu.DropDownItems.Add(myAboutMenu);
//добавляем новые элементы меню на форму
mnu.Items.Add(myText2HexMenu);

Далее напишем код обработки событий нажатий элементов меню:

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
'обработка события нажания на меню ConvertText2Hex (Конвертировать Текст в Шестнадцатеричный код)
Public Sub ConvertText2HexMenu_Click(ByVal sender As Object, ByVal e As EventArgs)
 If String.IsNullOrEmpty(_textBox.Text) Then Return 'нет текста, выходим
 Dim sResult As String = ""
 For Each s As Char In _textBox.Text
  sResult += IIf(Hex(Asc(s)).Length < 2, "0" & Hex(Asc(s)), Hex(Asc(s)))
 Next
 _textBox.Text = sResult
End Sub

'обработка события нажания на меню ConvertHex2TextMenu (Конвертировать Шестнадцатеричный код в Текст)
Public Sub ConvertHex2TextMenu_Click(ByVal sender As Object, ByVal e As EventArgs)
 If String.IsNullOrEmpty(_textBox.Text) Then Return 'нет текста, выходим
 Dim sResult As String = ""
 'удаляем все символы, которые нельзя преобразовать в hex
 Dim myRegEx As New System.Text.RegularExpressions.Regex("[^0-9ABCDEF]*")
 _textBox.Text = myRegEx.Replace(_textBox.Text.ToUpper(), "")
 If String.IsNullOrEmpty(_textBox.Text) Then Return 'нет текста, выходим
 For i As Integer = 1 To _textBox.Text.Length Step 2
  If CType("&H" & Mid(_textBox.Text, i, 2), Integer) <= 255 Then
   sResult += Chr(CType("&H" & Mid(_textBox.Text, i, 2), Integer))
  End If
 Next
 _textBox.Text = sResult
End Sub

'обработка события нажания на меню AboutMenu (О программе)
Public Sub AboutMenu_Click(ByVal sender As Object, ByVal e As EventArgs)
 MsgBox("Простой пример плагина", MsgBoxStyle.Information)
End Sub

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
//обработка события нажания на меню ConvertText2Hex (Конвертировать Текст в Шестнадцатеричный код)
public void ConvertText2HexMenu_Click(object sender, EventArgs e)
{
 if (string.IsNullOrEmpty(_textBox.Text)) return; //нет текста, выходим
 string sResult = "";
 foreach (char s in _textBox.Text)
 {
  sResult += Encoding.GetEncoding(1251).GetBytes(new char[] { s })[0].ToString("x").Length < 2 ? "0" + Encoding.GetEncoding(1251).GetBytes(new char[] { s })[0].ToString("x") : Encoding.GetEncoding(1251).GetBytes(new char[] { s })[0].ToString("x");
 }
 _textBox.Text = sResult;
}

//обработка события нажания на меню ConvertHex2TextMenu (Конвертировать Шестнадцатеричный код в Текст)
public void ConvertHex2TextMenu_Click(object sender, EventArgs e)
{
 if (string.IsNullOrEmpty(_textBox.Text)) return; //нет текста, выходим
 string sResult = "";
 //удаляем все символы, которые нельзя преобразовать в hex
 _textBox.Text = _textBox.Text.ToUpper();
 System.Text.RegularExpressions.Regex myRegEx = new System.Text.RegularExpressions.Regex("[^0-9ABCDEF]*");
 _textBox.Text = myRegEx.Replace(_textBox.Text, "");
 if (string.IsNullOrEmpty(_textBox.Text)) return; //нет текста, выходим
 for (int i = 0; i <= _textBox.Text.Length - 2; i = i + 2)
 {
  if (int.Parse(_textBox.Text.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier) <= 255)
  {
   sResult += Encoding.GetEncoding(1251).GetString(new byte[] { byte.Parse(_textBox.Text.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier) });
  }
 }
 _textBox.Text = sResult;
}

//обработка события нажания на меню AboutMenu (О программе)
public void AboutMenu_Click(object sender, EventArgs e)
{
 MessageBox.Show("Простой пример плагина", "О плагине..", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

Вот и все, плагин готов! Компилируем его, и помещаем в папку с нашей компилированной программой. Теперь осталась самая малость, написать функцию в нашу основную программу, которая будет искать и подключать плагины:

VB .NET
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
Private Sub LoadPlugins()
 Dim sPath As String = Application.StartupPath
 Dim lPlugins As New List(Of IPlugin)
 For Each f As String In IO.Directory.GetFiles(sPath, "*.dll")
  Dim a As Reflection.Assembly = Reflection.Assembly.LoadFile(f)
  For Each t As Type In a.GetTypes()
   For Each i As Type In t.GetInterfaces()
    If i.Equals(GetType(IPlugin)) Then
     Dim p As IPlugin = CType(Activator.CreateInstance(t), IPlugin)
     lPlugins.Add(p)
     p.Initialize(Me)
     Exit For
    End If
   Next
  Next
 Next
End Sub

C#
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
private void LoadPlugins()
{
 string sPath = Application.StartupPath;
 List<IPlugin> lPlugins = new List<IPlugin>();
 foreach (string f in System.IO.Directory.GetFiles(sPath, "*.dll"))
 {
  System.Reflection.Assembly a = System.Reflection.Assembly.LoadFile(f);
  foreach (Type t in a.GetTypes())
  {
   foreach (Type i in t.GetInterfaces())
   {
    if (i.Equals(Type.GetType("PluginSample.IPlugin")))
    {
     IPlugin p = (IPlugin)Activator.CreateInstance(t);
     lPlugins.Add(p);
     p.Initialize(this);
     break;
    }
   }
  }
 }
}

Функция готова, теперь добавляем в обработчик события загрузки формы вызов этой функции, запускаем проект, и любуемся результатом :)

VB .NET
001:
002:
003:
004:
005:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 OpenFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*"
 SaveFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*"
 LoadPlugins()
End Sub

C#
001:
002:
003:
004:
005:
006:
private void Form1_Load(object sender, EventArgs e)
{
 openFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*";
 saveFileDialog1.Filter = "Текстовые документы (*.txt)|*.txt|Все файлы (*.*)|*.*";
 LoadPlugins();
}

Как видите, все довольно просто. Каким образом будут работать ваши плагины, и какие функции они будут выполнять, уже зависит лишь от вашей фантазии.

Если у вас возникнут какие-либо вопросы, вы всегда можете задавать их на форуме Kbyte.Ru, либо Экспертам в систему Эксперт Kbyte.Ru. Если у вас есть собственные проекты (сайты, программы, компоненты), то вы можете добавить их в раздел «Наши проекты» Kbyte.Ru. Вы также всегда можете воспользоваться уникальным сервисом по обмену кодами - Кодообменник Kbyte.Ru.

Удачи!

Комментарии (всего: 6)

Добавить комментарий rss
Автор: arab_nadjib @ 22 марта 2008, 19:27   ·   ссылка
Спс за материал. Статья почти эталонная!!! Нет типа "это вы и так знаете". Ничего лишнего все только по теме! +5 :)
Автор: Виталий @ 17 мая 2008, 22:40   ·   ссылка
Спасибо автору, всё четко и ясно. Нет слов)
Автор: Bender @ 21 мая 2008, 08:42   ·   ссылка
Большое спасибо. Статья действительно эталонная!
Автор: maza @ 27 мая 2008, 13:03   ·   ссылка
статья неплохая, но
не в обиду автору, но с реализацией Initialize в плагине Class1 он конечно поступил жосско.
Если так хотелось добавлять что-то в меню главного окна, то почему бы в Initialize не передавать типизированый объект хоста с соответсвующими свойствами?
Автор: Алексей Немиро @ 04 июня 2008, 12:36   ·   ссылка
Если так хотелось добавлять что-то в меню главного окна, то почему бы в Initialize не передавать типизированый объект хоста с соответсвующими свойствами?

Статья носит обучающий характер и всего лишь показывает, как это можно сделать наиболее простым способом. Остальные наворты и замуты авторы программ уже сами смогут реализовать экспериментальным путем. К слову, в проекте «Лена Цтулховна» у нас работа с плагинами реализована довольно неплохо с технической стороны, и максимально удобно для плагин-мейкеров: http://kbyte.ru/Forum/Show.aspx?id=8079 Рефлектором можно посмотреть, как сделано ядро.
Автор: RatHat @ 29 августа 2009, 15:53   ·   ссылка
Спасибо большое. Толково расписано. Чтобы разобраться, хватило даже моих убогих знаний :)

Добавить комментарий

Добавлять комментарии могут только зарегистрированные пользователи сайта.
Если у Вас уже есть учётная запись на этом сайте, пройдите процудуру авторизации.
В противном случае, зарегистрируйтесь на сайте.