Вверх ↑
Главный модератор
Ответов: 2997
Рейтинг: 395
#1: 2019-11-03 15:50:22 ЛС | профиль | цитата
    Работа элемента в проекте Windows Forms

  Итак, наш элемент работает в проекте Шаблоны (Templates) пакета Core:

  С помощью проекта этого типа можно сделать:
    редактор пользовательского свойства для элементов;
    быстро отладить прототип будущей программы проекта Windows Forms;
    компилировать, запускаемую на машине с предустановленным HiAsm.NET, сборку (.exe);
  То есть, полностью самостоятельную программу, мы сделать с помощью проекта Шаблоны (Templates) не сможем. Чтобы получить полноценную программу, надо сделать её с помощью проекта «Приложение Windows Forms» (Windows Forms Application):

  Может возникнуть вопрос: зачем создавать прототип программы в проекте Шаблоны? Для схемы из десятка элементов время сборки проектов будет отличаться незначительно, но для больших схем это будет очень заметно. Поэтому, для отладки прототипа программы комфортнее это делать в проекте Шаблоны, а уже финальное тестирование в проекте Windows Forms. Это означает что элементы пакета Core должны уметь одинаково работать в обоих проектах. Значит следущим шагом мы сделаем необходимые дополнения для нашего элемента, чтобы он смог работать в проекте Windows Forms. Для этого надо создать скрипт, который в процессе построения нашего приложения, будет возвращать C# код, реализующий функционал нашего элемента. Создадим в папке C:\HiAsm.NET\elements\_base\code файл с именем wfExample.cs со следующим содержимым:
//css_ref System.Core;
//css_ref Microsoft.CSharp;

using System;
using codegen;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Reflection;
using System.Resources;
using System.IO;
using System.Text;
using System.Dynamic;
using System.Threading.Tasks;
using System.Threading;

public class Example : TElementObject
{
public override bool init(object entry)
{
Debug.WriteLine("{0}.init()".fString(this.codename));

sys.add_var(this, "local", "string", "Hello World!".toLiteral());

@this.doSayHello = (Func<TArgs, TValue>)((data) =>
{
sys.blk.println(@this.local, " = ", d("Data"), ";");

@event("onGreeting", new TValue(@this.local, true));

return TValue.empty;
});

@this.Greeting = (Func<TArgs, TValue>)((data) =>
{
return new TValue(@this.local, true);
});

return base.init(this);
}
}
  Данный скрипт реализует функционал нашего элемента для проекта Widows Forms. Теперь рассмотрим подробности построения скрипта. Имя файла скрипта состоит из двух обязательных частей: префикса «wf» от сокращения названия проекта Windows Forms и имени элемента для которого он предназначен «Example». Расположение файла в папке \code тоже имеет особое значение и это не только наследие предыдущей версии среды, но и возможность отладки скрипта без перекомпиляции сборки самого элемента. Тоже самое касается кода скрипта до определения класса:
//css_ref System.Core;
//css_ref Microsoft.CSharp;

using System;
using codegen;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Reflection;
using System.Resources;
using System.IO;
using System.Text;
using System.Dynamic;
using System.Threading.Tasks;
using System.Threading;
  Этот код нужен только на этапе отладки скрипта и в финальной версии заменяется следующим кодом:
//css_pc wfPrecompiler.cs;
  Это тегированный комментарий, который заменится развёрнутым полным кодом на этапе компиляции. Все «простые» элементы являются наследниками базового класса TElementObject:
public class Example : TElementObject
{
...
}
  В данном случае нам достаточно реализовать единственный метод init():
public override bool init(object entry)
{
...
return base.init(this);
}
  Для каждой левой точки должен быть реализован метод-обработчик с именем совпадающий с именем точки. В нашем случае это единственная левая точка doSayHello:
@this.doSayHello = (Func<TArgs, TValue>)((data) =>
{
...
return TValue.empty;
});
  Тоже самое касается и нижних точек элемента:
@this.Greeting = (Func<TArgs, TValue>)((data) =>
{
...
return TValue.empty;
});
  В самом начале метода инициализации правилом хорошего тона будет вставка кода, который выведет информацию о себе в окно отладки среды:
public override bool init(object entry)
{
Debug.WriteLine("...");
...
}
  Также нам нужна будет переменная для хранения сообщения в памяти:
public override bool init(object entry)
{
...
sys.add_var(this, "local", "string", "Hello World!".toLiteral());
}
  Здесь мы определяем переменную с именем local, типом String и инициализированную строкой «Hello World!». Все методы класса sys реализованы в файле C:\HiAsm.NET\elements\_base\code\Sys.cs и используются всеми элементами проекта Windows Forms. Поэтому изменения в этом файле очень важны для работы проекта в целом. Будьте внимательны при редактировании его содержимого, если, конечно, Вы уверены в своих силах.
  В методе точки doSayHello мы читаем данные, пришедшие в элемент через левую или верхнюю точки и сохраняем их в нашу переменную local:
@this.doSayHello = (Func<TArgs, TValue>)((data) =>
{
sys.blk.println(@this.local, " = ", d("Data"), ";");
...
});
  И сразу же отправляем данные другому элементу через правую точку onGreeting, «упаковав» их в тип TValue:
@this.doSayHello = (Func<TArgs, TValue>)((data) =>
{
...
@event("onGreeting", new TValue(@this.local, true));
...
});
  В конструкторе типа TValue мы указываем в качестве аргументов нашу переменную и признак того, что строка в данном случае является C# кодом, а не простой строковой константой "...". Тоже самое делаем для нижней точки Greeting, где мы возвращаем данные, запрошенные другим элементом у нашего, «упаковав» их в тип TValue:
@this.Greeting = (Func<TArgs, TValue>)((data) =>
{
return new TValue(@this.local, true);
});
  Финальный варинт кода скрипта будет выглядеть так:

  После того, как мы полностью отладим скрипт, мы можем поместить его в ресурсы нашего элемента и использовать напрямую оттуда. Делаем это так же как мы добавляли иконку в ресурсы элемента (смотрите первый пост темы). В результате добавления мы получим следующий вид ресурсов сборки:

  Теперь файл C:\HiAsm.NET\elements\_base\code\wfExample.cs нужно убрать в другое место или удалить с диска, так как его наличие в папке \code является приоритетным перед ресурсами сборки и при построении программы будет использован именно он. Кстати, таким образом может быть «изменена» работа любого элемента проекта Windows Forms.
  Наконец, оптимизируем скрипт для использования из ресурсов сборки. Заменим код скрипта до определения класса его эквивалентом в виде тегированного комментария:
//css_pc wfPrecompiler.cs;

public class Example : TElementObject
{
public override bool init(object entry)
{
Debug.WriteLine("{0}.init()".fString(this.codename));

sys.add_var(this, "local", "string", "Hello World!".toLiteral());

@this.doSayHello = (Func<TArgs, TValue>)((data) =>
{
sys.blk.println(@this.local, " = ", d("Data"), ";");

@event("onGreeting", new TValue(@this.local, true));

return TValue.empty;
});

@this.Greeting = (Func<TArgs, TValue>)((data) =>
{
return new TValue(@this.local, true);
});

return base.init(this);
}
}
Проверяем работу элемента в проекте Windows Forms:
Demo


Можете скачать полный код проекта элемента: MyElementCore.zip
карма: 6
Дорогу осилит идущий. Install/Update HiAsm.NET
0
Редактировалось 9 раз(а), последний 2020-01-02 20:09:14