LIRA-FEM позволяет преобразовывать в расчетные схемы файлы определенных форматов, таких как .DXF или .IFC, а также изменять расчетные схемы при помощи методов LIRA-FEM API.
Расширения LIRA-FEM, являясь частью LIRA-FEM API, позволяют внешним программам подключать свои команды к ленте LIRA-FEM, свои расчёты к любому из этапов расчётов LIRA-FEM, свои отчёты к системе документирования LIRA-FEM, включать свои данные в состав Lir-файла и передавать их во внешние приложения с поддержкой редактирования.
Эта статья поясняет, как создавать расширения LIRA-FEM и пользоваться вышеперечисленными возможностями расширений. Статья построена так, что более простые техники описаны в ней выше, а более сложные - ниже. Простейшее расширение можно создать, пользуясь только сведениями из подраздела "Быстрый старт". В конце статьи находится справочник по подключению модулей расширений, написанных на разных языках программирования.
- Быстрый старт
- Поддерживаемые языки программирования
- Идентификатор расширения
- Регистрация функций расширения для запуска из LIRA-FEM
- Управление видом кнопки на ленте
- Вызов контекстной справки
- Визуализация данных расширения при помощи мозаик
- Более глубокая интеграция
- Объекты и интерфейсы LIRA-FEM API для расширений
- Реализация программных интерфейсов в расширении LIRA-FEM
- Создание экземпляра объекта расширения и подключение его к LIRA-FEM
- Основной программный интерфейс расширения ILiraExtension
- Встраивание данных расширения в LIR-файлы с помощью интерфейса ILiraExtensionTableHelper
- Требования к именованию файлов результатов
- Документирование таблиц результатов и таблиц исходных данных
- Создание для Книги отчетов обновляемых снимков экрана
- Другие методы объектов LIRA-FEM API, предназначенные для расширений
- Автономная работа расширения
- Справочник по разделам и параметрам реестра Windows, относящихся к расширениям LIRA-FEM
- Технические спецификации технологии расширений LIRA-FEM
Простейшее расширение LIRA-FEM состоит из исполняемого файла и записи в реестре. Давайте создадим расширение, которое выводит на экран традиционное приветствие наподобие "Здравствуй, мир!" по кнопке, которая появится на ленте LIRA-FEM. Для этого создадим текстовый файл с функцией HelloLira на языке VBScript, как в листинге ниже, и сохраним его с путем C:\Users\Public\Documents\Hello.vbs.
Sub HelloLira
MsgBox "Well, hello there, LIRA!"
End Sub
Теперь необходимо создать на ленте LIRA-FEM кнопку, которая будет вызывать эту функцию. Для этого необходимо внести в реестр Windows несколько разделов и параметров. Проще всего это сделать, перечислив необходимые разделы с их параметрами в файле с расширением *.reg, а затем выполнить его. Создадим текстовый файл C:\Users\Public\Documents\Hello.reg с содержимым как в листинге ниже.
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli] @="Script:VBS" [HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli\HelloLira] @="C:\\Users\\Public\\Documents\\Hello.vbs"
Теперь необходимо выполнить его. Для этого вызовите окно "Выполнить" ("Run") при помощи комбинации клавиш Win+R, введите в появившееся окно путь к файлу со разделами и параметрами реестра C:\Users\Public\Documents\Hello.reg, и нажмите кнопку ОК.
Операционная система запросит подтверждение на выполнение этого действия, разрешите его. После этого редактор реестра ("Registry Editor") повторно запросит разрешение на добавление в реестр нужных нам разделов и параметров, разрешите и это, нажав на кнопку "Да" ("Yes").
И, наконец, редактор реестра должен показать окно, на котором подтверждается внесение данных в реестр. Это окно можно просто закрыть.
Теперь убедимся, что кнопка добавилась в ленту LIRA-FEM. Запустим LIRA-FEM. Если во время выполнения действий выше она уже была запущена, необходимо ее перезапустить. После запуска можно убедиться, что в ленте LIRA-FEM появилась новая закладка "Инструменты" ("Tools") и на ней появилась кнопка без пиктограммы, но с надписью "HelloLira". Появилось также меню "Инструменты hli" с пунктом "HelloLira".
Давайте нажмем на кнопку "HelloLira", чтобы убедиться, что она действительно вызовет нашу функцию HelloLira. После нажатия на нее появляется окно, которое спрашивает разрешение на загрузку в память исполнимого модуля, неизвестного LIRA-FEM и не имеющего надежной цифровой подписи. Поскольку мы сами только что написали этот исполнимый модуль, беспокоиться не о чем, и мы просто разрешаем его работу, выбрав опцию "Разрешить загрузку и выполнение этой программы-расширения LIRA-FEM и больше не спрашивать" ("Allow this LIRA-FEM extension to load and run, and do not ask again") и нажав OK.
После этого наша функция выполняется, показав окошко "Ну, здравствуй, ЛИРА!" ("Well, hello there, LIRA!")
Нажмем в этом окошке кнопку OK и запустим нашу команду еще раз. На этот раз окно с запросом разрешения на загрузку не появляется, и окошко "Ну, здравствуй, ЛИРА!" ("Well, hello there, LIRA!") вызывается немедленно.
Кнопка без пиктограммы на совершенно пустой вкладке "Инструменты" ("Tools") на первый взгляд кажется излишне аскетичной, но ведь и усилий на ее создание мы потратили только самую малость. Возможности расширений LIRA-FEM по созданию кнопок на ленте ничем не уступают возможностям самой программы LIRA-FEM, и подтверждением этому может служить вкладка "Дерево" ("Timber"), которая полностью построена одноименным расширением LIRA-FEM.
Новые вкладки, панели и пиктограммы команд - все это можно добавить в ленту LIRA-FEM при помощи соответствующих функций LIRA-FEM API или параметров реестра Windows. Подробный перечень последних приведен в конце этого раздела справочной системы.
В подразделе "Быстрый старт" мы познакомились с блиц-способом создания расширений LIRA-FEM, однако не всегда удобно вовлекать функции расширений только по нажатию кнопок на ленте. Следующие подразделы описывают важные подробности и полезные возможности LIRA-FEM API для редактирования расчетной схемы.
Простейшее расширение, которое мы создали в подразделе "Быстрый старт" было написано на интерпретируемом языке VBScript. Чтобы указать программе LIRA-FEM, интерпретатор какого языка загружать, мы добавили в реестр параметр @="Script:VBS". Кроме интерпретируемого языка VBScript, LIRA-FEM поддерживает следующие интерпретируемые языки программирования для создания расширений: JScript и V8Script. Если VBScript и JScript это хорошо известные языки, уже давно встроенные в операционную систему Microsoft Windows, то язык V8Script, или V8 JavaScript, – это относительно молодая разновидность языка JavaScript, разработанная Google. Если бы мы написали наше расширение на языке JScript или V8, нам бы пришлось в файле с разделами и параметрами реестра написать вместо @="Script:VBS" соответственно @="Script:JS" или @="Script:V8".
Кроме трех интерпретируемых языков программирования, LIRA-FEM поддерживает расширения, написанные на компилируемых языках программирования, которые поддерживают технологию COM (Component object Model) или .NET, каковыми являются практически все современные языки программирования. Расширения, написанные на компилируемом языке программирования, могут быть двух видов: исполняемый модуль *.EXE или динамическая библиотека *.DLL. Для написания приложений предпочтение следует отдавать динамическим библиотекам, так как они позволяют вызывать методы LIRA-FEM API без необходимости выполнять дополнительно маршаллинг параметров. Если вызов одного метода LIRA-FEM API из исполняемого модуля *.EXE может занять несколько миллисекунд, то вызов того же метода из динамической библиотеки *.DLL может занять наносекунды, то есть в миллионы раз быстрее. Тем не менее для регистрации расширений в исполняемых модулях *.EXE предусмотрен параметр реестра @="Exe:App". Динамические библиотеки *.DLL могут быть скомпилированы в код .NET CLR (Common Language Runtime), из таких языков как C# или VB.NET и т. п. или в код native из таких языков как C, C++ и т. п. Параметры реестра для регистрации расширений *.DLL в LIRA-FEM зависят от выбранного языка программирования. Для регистрации библиотеки классов, написанной на .NET CLR языке C# или VB.NET предусмотрен параметр @="Dll:Net4", а для библиотеки на native коде, написанной на С/С++ или других языках строка регистрации будет либо @="Dll:stdcall", либо @="Dll:cdecl" – в зависимости от соглашения на вызовы функций расширения, вызываемых из LIRA-FEM. Соглашение вызова stdcall является наиболее распространенным, однако в С/С++ требует при объявлении функции ключевого слова __stdcall. Если ключевое слово __stdcall отсутствует при объявлении функций, вызываемых из расширения программой LIRA-FEM, то для регистрации расширения следует внести в реестр параметр @="Dll:cdecl".
В подразделе "Быстрый старт" для того, чтобы идентифицировать наше блиц-расширение, мы добавили в раздел реестра Windows HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS параметр hli. Как видно, этот параметр состоит из трех букв латинского алфавита. Это ограничение связано с расширениями файлов и будет подробнее объяснено в подразделе "Требования к именованию файлов результатов" ниже.
Идентификатор расширения – трехбуквенный параметр, который может состоять только из букв латинского алфавита и цифр.
Для регистрации расширения LIRA-FEM необходимо в разделе реестра Windows HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS создать новый раздел, с именем – идентификатором расширения.
Как параметр по умолчанию раздела реестра – идентификатора расширения следует указать инструкцию, как загружать такое расширение, одно из следующих строковых значений:
*.DLL, скомпилированной в код CLR на языках, поддерживающих .NET Framework версии 4 (С#, VB.NET, managed C++ и т.п.).*.DLL, скомпилированной в код native на языках, поддерживающих работу с COM-объектами (C/С++ и т.п.), функции имеют соглашение вызова stdcall.*.DLL, скомпилированной в код native на языках, поддерживающих работу с COM-объектами (C/С++ и т.п.), функции имеют соглашение вызова cdecl..EXE.
В подразделе "Быстрый старт" мы создали пользовательское расширение, которое состоит из одной функции, которая запускается при нажатии на соответствующую кнопку на ленте. Чтобы указать программе, какую кнопку на ленте создавать и какую функцию следует вызывать по ее нажатию, мы создали в разделе реестра с именем – идентификатором расширения HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli подраздел HelloLira.
Важно, что имя подраздела HelloLira совпало у нас с именем функции в файле C:\Users\Public\Documents\Hello.vbs, а путь к этому файлу мы указали для подраздела в качестве параметра по умолчанию:
[HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli\HelloLira] @="C:\\Users\\Public\\Documents\\Hello.vbs"
Так мы сообщили программе LIRA-FEM, в каком файле и с каким именем функцию искать. Поскольку мы не указали, в какой момент следует вызывать функцию HelloLira, программа поступила по умолчанию, то есть разместила кнопку с таким названием на вкладке по умолчанию, т.е. на вкладке "Tools" ("Инструменты").
Вызов функции расширения API по нажатию на кнопке ленты или выбору пункта меню – это только один из способов подключения функций расширения к LIRA-FEM. Чтобы указать способ и момент вызова функции расширения, следует в разделе реестра Windows с именем функции создать строковый параметр с именем "CallAfter", значение которого может быть одним из следующих:
Если ни один из вышеперечисленных параметров не указан, то принимается параметр по умолчанию, то есть параметр Button.
Может случиться так, что одна функция расширения должна быть вызвана после выполнения функции какого-то другого расширения на том же этапе выполнения. Тогда важно указать не просто этап, но и последовательность выполнения функций расширения. Для этого после любого значения от AppStartup и до AnalysisCSV может быть указан момент запуска в виде числа double после знака "+", например: в одном расширении можно указать AnalysisFEA + 10.0, а в другом AnalysisFEA + 20.0. Чем больше указанное число double, тем позже будет запускаться функция расширения, то есть сразу после конечно-элементного расчета сначала будет вызвана функция со значением AnalysisFEA + 10.0, а потом AnalysisFEA + 20.0.
Регистрацию функций расширения можно производить не только при помощи ключей реестра, но и при помощи методов LIRA-FEM API, при чем последняя предоставляет больше возможностей, однако в реестре Windows в любом случае должна быть зарегистрирована по меньшей мере одна функция расширения, чтобы передать ей управление и таким образом дать расширению возможность вызывать методы LIRA-FEM API. Нетрудно предположить, что, как правило, это будет функция, указанная с параметром "CallAfter"="AppStartup".
В своем примере в подразделе "Быстрый старт" мы создали кнопку, которая получила имя по умолчанию, разместилась на вкладке ленты LIRA-FEM по умолчанию, а пиктограммы вообще не имела. Все это легко настроить при помощи соответствующих параметров раздела реестра Windows c именем - идентификатором расширения и с именем вызываемой функции расширения, в нашем примере это разделы HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli и HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli\HelloLira.
В разделе реестра с именем - идентификатором расширения допускаются строковые параметры со следующими именами:
В разделе реестра с именем - именем функции расширения допускаются строковые параметры со следующими именами:
Значение параметра RibbonTabImageListSmall, RibbonTabImageListLarge, RibbonImageSmall, RibbonImageLarge может содержать путь к изображению .PNG, .BMP или .ICO для одной или нескольких кнопок. Можно указать либо полный путь к файлу изображения, который хранится на диске, либо полный путь к изображению, которое хранится в ресурсах native приложения или динамической библиотеки .EXE или .DLL. В последнем случае после пути к файлу .EXE или .DLL должна следовать косая черта и идентификатор изображения-ресурса. Например: C:\path\to\dll\file.dll/#1001 - ресурс имеет численный идентификатор "1001". Еще пример: C:\path\to\dll\file.dll/PNG1 - ресурс имеет строковый идентификатор "PNG1". Можно вставить подсказку-тип ресурса, например: C:\path\to\dll\file.dll/PNG/#1001 - ресурс типа изображение .PNG имеет численный идентификатор, равный "1001". Еще пример: C:\path\to\dll\file.dll/PNG/PNG1 - ресурс типа изображение .PNG имеет строковый идентификатор "PNG1".
Вместо /PNG/ можно указать /BMP/ или /2/ для изображений типа .BMP или /ICO/ или /14/ для изображений типа .ICO. Если подсказки нет, то загружается .PNG, если он не найден, то .BMP, если он не найден, то .ICO.
RibbonTabImageListSmall, RibbonTabImageListLarge должен содержать горизонтальный спрайт из изображений размером соответственно 16x16 и 32x32. Если включена настройка "Крупные значки на ленте", то горизонтальный спрайт должен состоять из изображений соответственно 24x24 и 48x48. Если размеры изображений в спрайте другие, они будут масштабированы до требуемых.
RibbonImageSmall, RibbonImageLarge может содержать не только путь к изображению соответствующей кнопки, но и номер изображения в спрайте, соответственно, RibbonTabImageListSmall и RibbonTabImageListLarge, начиная от 0. Если для всех кнопок параметры RibbonImageSmall, RibbonImageLarge указаны в виде путей к соответствующим изображениям, то нет необходимости создавать спрайты кнопок и указывать их в параметрах RibbonTabImageListSmall, RibbonTabImageListLarge. И наоборот, нет необходимости создавать отдельное изображение для кнопки, если оно уже есть в спрайте. В этом случае достаточно просто указать номер изображения в соответствующем спрайте в параметре RibbonImageSmall или RibbonImageLarge.
Если вы создаете расширение, которым будут пользоваться не только вы, но и другие люди, то скорее всего, вы захотите добавить в команды своего расширения также и команду для вызова справки. Одной команды для вызова справки небольшого расширения обычно бывает вполне достаточно. Но если у вас много команд, и для каждой из них предусмотрен свой раздел справочной системы, то логичнее воспользоваться так называемой контекстной справкой, то есть по нажатию клавиши F1 на клавиатуре вызывать тот раздел вашей справочной системы, который соответствует кнопке, над которой в настоящий момент находится курсор мыши. Другой способ вызвать контекстную справку на команду ленты - это нажать комбинацию клавиш Shift+F1 и, после того как курсор мыши превратится в стрелочку со знаком вопроса, щёлкнуть этим курсором на интересующую кнопку ленты. LIRA-FEM имеет встроенную контекстную справку, которая так работает, и расширения LIRA-FEM также могут подключиться к этой справке.
Для того, чтобы контекстная справка вызывалась для вашей кнопки на ленте, необходимо в параметры раздела реестра Windows с именем команды расширения добавить параметр "HelpCommand". Например, следующее значение параметра закрепляет за кнопкой контекстную справку в виде открытия файла PDF: "HelpCommand"="c:\Users\Public\Documents\ReadMe.pdf". А вот пример с вызовом справки из Интернет: "HelpCommand"="https://sites.google.com/view/help/home". И, наконец, пример вызова раздела из файла формата .CHM - такого же, какой использует LIRA-FEM для своей справочной системы: "HelpCommand"="HH.EXE C:\Program Files (x86)\LIRALAND\LIRA-FEM 2026\bin\x64\help\ru\LiraFEM.chm::/Explain/_LiraSaprApi.htm"
Предположим, что ваше расширение вычитало что-то из исходных данных, а что-то из результатов расчета LIRA-FEM, выполнило свой собственный расчет и записало файл с результатами своего расчета. Теперь перед пользователем вашего расширения стал вопрос о качественной оценке результатов вашего расчета. Для качественной оценки можно воспользоваться возможностями, которые предоставляют таблицы ввода LIRA-FEM для построения пользовательских мозаик. Фактически это метод построения мозаики, которая на узлах или элементах расчетной схемы в виде мозаики изображает произвольные пользовательские значения.
Например, следующая функция создает в окне ранее открытой расчетной схемы мозаику, раскрашивая ее 1 и 2 элементы.
Sub CreateMosaic() ' Подключаемся к объекту LiraApplication и получаем активный документ с расчетной схемой Set LiraApp = CreateObject("LiraFEM.Application") Set Doc = LiraApp.ActiveDocument ' Создаём таблицу мозаики (46=kLiraTable_UserMosaicData) Params1 = Array("Element text mosaic" , 11 , 1) Set Mosaic1 = Doc.AllTables.CreateNewItem ( 46 , (Params1) ) ' Данные для мозаики (массив 2D) Dim Data1(1,4) Data1(0,1) = 1 : Data1(0,3) = "1.1 Красный цвет" : Data1(0,4) = "#ff4444" Data1(1,1) = 2 : Data1(1,3) = "2.2 Зеленый цвет" : Data1(1,4) = "#008800" ' Заполняем таблицу Mosaic1.SetContents(Data1) ' Применяем изменения Mosaic1.Apply(strErrs) 'Убираем за собой -- удаляем только что созданную таблицу Doc.AllTables.Delete(Doc.AllTables.ItemCount-1) End Sub
В приведённом выше примере функции и каждому элементу назначается свой текст и свой цвет. Чтобы создалась мозаика именно такого типа, в функцию CreateNewItem создания новой таблицы ввода передается массив параметров. Первый параметр - это название мозаики, "Element text mosaic". Второй параметр - это тип содержимого таблицы, число 11 обозначает, что таблица будет заполнена для каждого элемента числом и сопутствующим комментарием. Третий параметр 1 включает в таблице столбец с цветами. Поддерживаются следующие типы содержимого таблицы для построения мозаик:
Тут следует отметить, что вместо мозаики по расчётным сечениям стержней можно построить эпюру по расчетным сечениям, тип 3. А вместо мозаики на пластинах можно построить изополя, тип 4.
Всю информацию и примеры, которые были приведены выше в этом разделе, можно было воспроизвести на любом языке программирования, в том числе на интерпретируемых языках сценариев наподобие VBScript или JScript. В нижеследующих подразделах мы коснемся возможностей, которые недоступны из интерпретируемых языков.
Для начала мы опишем, как регистрировать функции расширения и управлять видом кнопок не при помощи параметров реестра Windows, как уже было описано в подразделах выше, а при помощи функций LIRA-FEM API. Далее мы коснемся более продвинутых возможностей, таких как реакция на смену номера текущего загружения или на запуск произвольной команды из меню или ленты инструментов LIRA-FEM, хранение исходных данных расширения внутри файла расчетной схемы и документирование исходных данных и результатов расчета расширения в системе "Книга отчетов". Чтобы продолжить чтение этого раздела далее, вам понадобятся дополнительные сведения по программированию, которые невозможно привести в этой статье, а именно, знания, как создавать динамические библиотеки классов DLL и как реализовывать предопределенные программные интерфейсы.
На следующей диаграмме желтым цветом изображены объекты LIRA-FEM API, которые предназначены для работы с расширениями. Белым цветом на диаграмме изображены интерфейсы, которые реализуются объектами на стороне расширения.
LIRA-FEM Расширение LIRA-FEM Объект приложения LiraApplication ¦ ¦ Лента инструментов ¦--LiraRibbon ¦ ¦ Расширения ¦--LiraExtensions ¦ ¦ Объект расширения ¦ '--------------------------------------------<<--ILiraExtension ¦ ¦ Документ, или расчетная схема ¦--LiraDocument ¦ ¦ ¦ ¦ Все группы и таблицы ввода ¦ '--LiraTables ¦ ILiraExtensionTables ¦ ¦ ¦ ¦ Группа таблиц ввода документа ¦ ¦--LiraTableGroup ¦ ¦ ILiraExtensionTableGroup ¦ ¦ ¦ ¦ Объект для управления ¦ ¦ ¦ ¦ группой таблиц ввода расширения ¦ ¦ ¦ '------------------------------<<--ILiraExtensionTableGroupHelper ¦ ¦ ¦ ¦ ¦ ¦ Таблица ввода документа ¦ ¦----'--LiraTable ¦ ¦ ¦ ¦ ¦ ¦ Таблица ввода расширения ¦ ¦----'--LiraExtensionTable ¦ ¦ ¦ Объект для управления ¦ ¦ ¦ таблицей ввода расширения ¦ ¦ '------------------------------<<--ILiraExtensionTableHelper ¦ ¦ ¦ ¦ Настройки единиц измерения '------------LiraMeasurementUnits '--ILiraExtensionMeasurementUnits
Объекты и программные интерфейсы для работы с расширениями повторяют, хотя и с большей свободой, те же варианты использования, что и параметры разделов реестра Windows, которые были описаны выше, а именно:
С помощью программных интерфейсов становятся доступными и дополнительные варианты использования расширений:
Правда, есть единственный вариант использования, который нельзя реализовать при помощи методов программных интерфейсов, и который реализуется только с помощью настройки параметров разделов реестра Windows. Это - первоначальная загрузка расширения в адресное пространство приложения LIRA-FEM. Чтобы расширение загрузилось, необходимо "прописать" его загрузку, как было описано выше в подразделе "Регистрация функций расширения для запуска из LIRA-FEM", хотя бы загрузку расширения на старте работы приложения CallAfter = AppStartup. Когда у расширения вызвана функция, то есть когда оно получило управление, расширение может настраивать ленту инструментов, регистрировать другие свои функции и многое другое, но "заставить" приложение передать управление расширению можно только через реестр.
Со стороны LIRA-FEM API для работы расширений предназначены объекты LiraRibbon, LiraExtensions, LiraTables, LiraTableGroup, LiraExtensionTable, LiraExtensionMeasurementUnits. Рассмотрим методы этих объектов.
| Объект и его методы | Описание, параметры |
|---|---|
| LiraRibbon | Объект для управления лентой инструментов |
| AddExtensionTab() | Добавляет новую вкладку с именем TabName. TabKey — это ее сокращение из латинских букв или цифр. PathImagesSmall и PathImagesLarge — пути к файлам с изображениями. Возвращает номер добавленной вкладки, начиная с 0 |
| AddExtensionTabImage() | Добавляет новое изображение на вкладку с именем TabName. ToLargeImages указывает, куда добавить изображение: для маленьких или больших изображений вкладки. ImagePath — путь к файлу изображения. Возвращает номер добавленного изображения от 0 или -1 в случае неудачи |
| GetExtensionTabCount() | Возвращает количество вкладок, добавленных на ленту с помощью метода AddExtensionTab() |
| GetExtensionTabData() | Возвращает данные i-й вкладки: ее имя, ее ярлык, количество изображений 16x16, 32x32 |
| RemoveExtensionTab() | Удаляет вкладку с именем TabName |
| AddPanel() | На вкладке с именем TabName добавляется новая панель с именем PanelName. PanelKey — это ее сокращение из латинских букв или цифр. ImageSmall — индекс изображения вкладки. Возвращает номер добавленной панели, начиная с 0 |
| GetPanelCount() | Возвращает количество панелей на вкладке с именем TabName |
| GetPanelData() | Возвращает данные i-й панели на вкладке с именем TabName: ее имя, ее сочетание клавиш, флаги |
| RemovePanel() | Удаляет панель с именем PanelName на вкладке с именем TabName |
| AddButton() | На вкладке TabName и панели PanelName добавляется новая кнопка ButtonName. При нажатии кнопки вызывается функция из ExtensionID. Если ParentButton не равен -1, новая кнопка является частью ее всплывающего меню. Возвращает номер новой кнопки или -1 в случае сбоя |
| AddButtonSeparator() | На вкладке TabName и панели PanelName добавляет новый разделитель. Возвращает его номер или -1 в случае сбоя |
| GetButtonCount() | Возвращает количество кнопок или разделителей на вкладке с именем TabName и панели с именем PanelName. Если ParentButton не равен -1, возвращает данные его всплывающего меню |
| GetButtonData() | Возвращает данные i-й кнопки или разделителя на вкладке с именем TabName и панели с именем PanelName: ее имя, ID расширения, функция, родительская кнопка, всплывающая подсказка, описание, сочетание клавиш, изображения и флаги |
| SetButtonData() | Устанавливает данные i-й кнопки на вкладке TabName и панели PanelName: ее имя, идентификатор расширения, функция, родительская кнопка, всплывающая подсказка, описание, сочетание клавиш, изображения и флаги. pImageSmall и pImageLarge — количество изображений вкладок |
| RemoveButton() | Удаляет i-ю кнопку на вкладке TabName и панели PanelName |
| Update() | Обновляет ленту |
Как видно из вышеприведенной таблицы, все методы объекта LiraRibbon создают, изменяют или удаляют элементы ленты инструментов: вкладки Tab, панели Panel, кнопки Button или разделители между кнопками ButtonSeparator. Здесь следует заметить, что расширения не могут изменять вкладки, которые не относятся к расширениям. Преимуществом создания кнопок ленты через объект LiraRibbon по сравнению с созданием тех же кнопок из реестра является, во-первых, динамичность, то есть расширение может изменять кнопки во время выполнения и во-вторых, языко-зависимость, так как текст элементов ленты может быть настроен в зависимости от текущего языка интерфейса. Еще функция AddButton может создавать кнопки в выпадающих списках.
Следующий объект предназначен исключительно для регистрации расширений и их методов. При помощи его методов, например, одно расширения LIRA-FEM может загрузить другое расширение, и зарегистрировать команды расширения.
| Объект и его методы | Описание, параметры |
|---|---|
| LiraExtensions | Объект для управления расширениями и их функциями |
| AddExtension() | Добавляет расширение. ExtensionID должен состоять из 3 латинских букв. Имя видно пользователю. Если Register не равно 0, регистрирует расширение в системном реестре. Возвращает номер добавленного расширения, начиная с 0 |
| GetExtensionCount() | Возвращает количество добавленных расширений |
| GetExtensionData() | Возвращает данные i-го расширения. i — это индекс расширения в списке расширений, начинающийся с нуля |
| RemoveExtension() | Удаляет расширение с ExtensionID. Если UnRegister не равно 0, отменяет регистрацию расширения и всех его функций в системном реестре |
| AddExtensionFunction() | Добавляет функцию для вызова из файла по пути с расширением ExtensionID. Если функция является методом, она будет выглядеть как 'MyNamespace.MyClass.MyMethod'. Имя и описание видны пользователю |
| GetExtensionFunctionCount() | Возвращает количество добавленных функций расширения |
| GetExtensionFunctionData() | Возвращает данные по функции номер i. См. AddExtensionFunction() для описания возвращаемых параметров |
| RemoveExtensionFunction() | Удаляет функцию расширения с ExtensionID. Также можно отменить ее регистрацию в реестре Windows, если параметр UnRegister не равен 0 |
Следующими объектами, предназначенными для работы с расширениями, являются объекты LiraTables, LiraTableGroup и LiraExtensionTable. Обратите внимание, что на диаграмме объектов LIRA-FEM выше объекты LiraTables и LiraTableGroup, кроме своего интерфейса по умолчанию, поддерживают специализированный интерфейс для работы с расширениями. Это интерфейс ILiraExtensionTables и ILiraExtensionTableGroup соответственно. Интерфейсы таблиц ввода ILiraExtensionTables и ILiraExtensionTableGroup вместе с объектом LiraExtensionTable позволяют расширениям создавать свои собственные группы таблиц ввода и таблицы ввода - и таким образом интегрировать свои данные в данные документа с расчетной схемой LIRA-FEM. Поскольку большинство методов интерфейсов ILiraExtensionTables, ILiraExtensionTableGroup, LiraExtensionTable повторяют методы объектов LiraTables, LiraTableGroup, LiraTable - рассмотрим только те из свойств и методов, которые предназначены для работы непосредственно с расширениями.
| Объект и его методы | Описание, параметры |
|---|---|
| ILiraExtensionTables, ILiraExtensionTableGroup | Все таблицы ввода, в том числе таблицы, управляемые расширениями Группа таблиц ввода, в том числе группа, управляемая расширением |
| AddTable() | Добавляет новую таблицу, реализованную с помощью вспомогательного объекта расширения LIRA-FEM, который поддерживает интерфейс ILiraExtensionTableHelper (он описан в подразделе ниже). Параметр ExtensionID должен содержать идентификатор расширения LIRA-FEM (3 латинские буквы). Возвращает новую таблицу. |
| AddTableGroup() | Добавляет новую группу таблиц, реализованную с помощью вспомогательного объекта расширения LIRA-FEM, который поддерживает интерфейс ILiraExtensionTableGroupHelper (он описан в подразделе ниже). Параметр ExtensionID должен содержать идентификатор расширения LIRA-FEM (3 латинские буквы). Возвращает новую группу таблиц. |
| FindTable() | Возвращает таблицу, ранее добавленную методом AddTable и управляемую вспомогательным объектом расширения с ID=HelperID. Параметр ExtensionID должен содержать идентификатор расширения LIRA-FEM (3 латинские буквы). Возвращает null, если таблица не была добавлена. |
| FindTableGroup() | Возвращает группу таблиц, ранее добавленную методом AddTableGroup и управляемую вспомогательным объектом расширения с ID=HelperID. Параметр ExtensionID должен содержать идентификатор расширения LIRA-FEM (3 латинские буквы). Возвращает null, если группа таблиц не была добавлена. |
| GetGroupHelper() | Возвращает вспомогательный объект расширения, который фактически реализует эту таблицу. |
| ILiraExtensionTable | Таблица ввода, управляемая расширением. |
| GetTableHelper() | Возвращает вспомогательный объект, который фактически реализует эту таблицу. |
Расширение не обязано реализовывать все интерфейсы, которые изображены с прозрачным фоном на диаграмме в предыдущем подразделе. В следующей таблице показано, в каких случаях требуется реализовать те или другие интерфейсы со стороны расширения.
| Интерфейс | Следует реализовывать, когда требуется |
|---|---|
| ILiraExtension | Управлять своими кнопками ленты инструментов, в том числе доступностью команд, принадлежащих расширению Получать уведомления о смене текущего загружения, варианта конструирования и т.п. Получать уведомления о вызове команд меню / ленты инструментов Обновлять копии экрана для документирования с помощью "Книги отчетов" Создавать экземпляры объектов, реализующих интерфейсы ILiraExtensionTableGroupHelper и ILiraExtensionTableHelper |
| ILiraExtensionTableGroupHelper | Настраивать параметры группы таблиц ввода, принадлежащих расширению |
| ILiraExtensionTableHelper | Редактировать данные расширения как таблицу ввода Сохранять данные расширения вместе с данными документа в составе LIR-файла Создавать таблицы результатов для документирования с помощью "Книги отчетов" |
Далее мы рассмотрим методы упомянутых в вышеприведенной таблице интерфейсов, акцентируя внимание на наиболее важных из них.
Итак, вы пришли к выводу, что вашему расширению требуется более тесная интеграция с пользовательским интерфейсом приложения. Тогда ваши действия должны быть следующими:
Как и когда создается экземпляр объекта, который реализует этот программный интерфейс?
Как уже было сказано, для того чтобы расширение могло быть загружено в адресное пространство приложения LIRA-FEM, необходимо зарегистрировать его в реестре. Рекомендуется это делать при помощи параметра реестра Windows "CallAfter"="AppStartup", как было показано в подразделе "Регистрация функций расширения для запуска из LIRA-FEM". После того, как мы внесли в реестр Windows необходимые разделы и их параметры, при загрузке приложения LIRA-FEM будет вызвана функция, приведенная в разделе реестра. Именно эта функция и должна создать экземпляр объекта расширения и добавить его в соответствующий контейнер объектов LIRA-FEM под названием LiraExtensions.
Например, расширение Дерево могло бы загрузиться в адресное пространство LIRA-FEM следующим образом. Во время своей установки оно регистрирует в реестре Windows динамическую библиотеку Wood.dll и ее метод Startup:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\Wud] @="Dll:Net4" [HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\Wud\Wood.WoodExtension.Startup] @="c:\\Users\\Public\\Documents\\WoodExtension\\Wood.dll" CallAfter="AppStartup"
И реализует метод Startup в динамической библиотеке на платформе .NET Framework 4 и языке C#:
using LiraFEM;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Wood
{
public class WoodExtension : ILiraExtension
{
// Конструктор должен быть публичным и без параметров
public WoodExtension() { }
// Полное имя этого метода с учетом пространства имен и имени класса зарегистрировано в реестре
public void Startup()
{
//Главная наша задача - подключить объект расширения. Делаем это
string strThisDllPath = System.Reflection.Assembly.GetExecutingAssembly().Location; //Путь к DLL расширения
LiraApplication LiraApp = new LiraApplication(); // Получаем ссылку на приложение
LiraExtensions LiraExts = LiraApp.Extensions; // Получаем ссылку на контейнер расширений
LiraExts.AddExtension( // Добавляем расширение в контейнер
"Wud", // ID расширения из 3-х латинских букв
LiraExtensionLangEnum.kLiraExtensionLang_Dll_Net4, // Технология, на которой написано расширение
"Timber structures design and analysis", // Имя расширения (можно не указывать)
LiraCompatibleVersionEnum.kLiraCompatibleVersion_Any, // Минимальная совместимая с расширением версия приложения
LiraCompatibleVersionEnum.kLiraCompatibleVersion_Any, // Максимальная совместимая с расширением версия приложения
this); // Указатель на расширение
Так расширение должно загружать себя в контейнер расширений. Создание кнопок на ленте, команды которых обрабатываются расширением, можно выполнить с помощью реестра Windows. Однако добавление кнопок можно выполнить и программно, как показано в примере ниже. В этом примере мы добавим функцию, которая эмулирует расчет, и кнопку на ленту инструментов, которая вызывает эту функцию расчета.
// Продолжение метода Startup() double fFunctionsOrder = 0; // Формальный параметр LiraExts.AddExtensionFunction( // Указатель на расширение "Wud", // ID расширения из 3-х латинских букв "Wood.WoodExtension.DoAnalysis", // Полное имя метода с учетом пространства имен и имени класса strThisDllPath, // Полный путь к Wood.dll LiraCallAfterEnum.kLiraCallAfter_Button, // Метод вызывается по нажатию кнопки на ленте ref fFunctionsOrder, // Порядок вызова метода (для кнопок на ленте не имеет значения) "Timber analysis", // Имя метода (можно не указывать) "Performs timber analysis", // Описание функции (можно не указывать) "wud"); // Расширение файлов результатов // Далее программно добавим на ленту инструментов вкладку и панель для кнопки, которая будет вызывать эту функцию. LiraRibbon Ribbon = LiraApp.Ribbon; // Получаем ссылку на ленту Ribbon.AddExtensionTab("Wood"); // Добавим на ленту новую вкладку с именем Wood Ribbon.AddPanel("Wood", "Analysis"); // Добавим на новую вкладку новую панель для кнопок с именем Analysis int iImgSmall = Ribbon.AddExtensionTabImage( // Добавим пиктограмму для кнопки "Wood", // Для какой закладки добавляется пиктограмма false, // Это пиктограмма для крупной кнопки? strThisDllPath + ".ICO"); // Путь к пиктограмме. Она лежит рядом с Wood.dll в файле Wood.dll.ico int iImgLarge = Ribbon.AddExtensionTabImage("Wood",true,strThisDllPath + ".ICO"); // то же, для крупной кнопки // Добавляем и саму кнопку на ленту LiraCmdIdEnum eCmd = Ribbon.AddButton( "Wood", // Имя новой вкладки ленты "Analysis", // Имя новой панели ленты -1, // Номер "родительской" кнопки. Для обычных кнопок -1 "Wud", // ID расширения из 3-х латинских букв "Wood.WoodExtension.DoAnalysis", // Полное имя метода с учетом пространства имен и имени класса "Timber analysis", // Надпись на кнопке "Performs Timber Analysis", // Подсказка для кнопки "More description comes here", // Описание кнопки "", // Быстрые клавиши iImgSmall, // Номер изображения для маленькой кнопки iImgLarge); // Номер изображения для большой кнопки m_CmdId2Func[eCmd] = "Wood.WoodExtension.DoAnalysis"; } Dictionary<LiraCmdIdEnum, string> m_CmdId2Func = new Dictionary<LiraCmdIdEnum, string>(); public void DoAnalysis() { System.Windows.Forms.MessageBox.Show("Timber analysis performed!"); }
Для полноты добавим в класс WoodExtension еще и методы, которые реализуют интерфейс ILiraExtension, правда без их реализации. Эти методы будут описаны в следующем подразделе.
string ILiraExtension.GetExtensionId() {return "Wud";}
string ILiraExtension.GetExtensionName() {return "Timber design and analysis";}
ILiraExtensionTableGroupItemHelper ILiraExtension.CreateTableHelper(ILiraExtensionTables Tables, int ExtensionHelperID) { return null;}
void ILiraExtension.SetApplication(LiraApplication App){}
void ILiraExtension.StateChanged(LiraDocument Doc, LiraCmdIdEnum Cmd, LiraViewCtlEnum Ctl){}
int ILiraExtension.GetExtensionCmdState(LiraCmdIdEnum Cmd, out bool pEnabled){pEnabled = true;return 0;}
bool ILiraExtension.CanExtensionDoAnalysis(){return false;}
bool ILiraExtension.UpdateScreenshotScreen(string Src, string Dat, LiraTable DstTable){return false;}
void ILiraExtension.DocumentClosing(LiraDocument Doc){}
void ILiraExtension.HelpContext(string TabName, string PanelName, string Function, int HtmlHelpCommand, long hParentWnd){}
void ILiraExtension.ApplicationClosing(){}
}
}
Методы интерфейса ILiraExtension описаны в таблице ниже.
| Интерфейс и его методы | Описание |
|---|---|
| ILiraExtension | Основной интерфейс расширения для работы в среде LIRA-FEM |
| CreateTableHelper() | По запросу LIRA-FEM API создает и возвращает объект, управляющий таблицей ввода расширения ILiraExtensionTable или группой таблиц ввода расширения ILiraExtensionTableGroup |
| GetExtensionId() | Возвращает трехбуквенный идентификатор расширения |
| GetExtensionName() | Возвращает имя расширения |
| SetApplication() | Передает расширению ссылку на объект LiraApplication |
| StateChanged() | Передает расширению информацию о нажатии любой кнопки на ленте или любому выбранному пункту меню, а также смене текущего номера загружения, варианта конструирования и т.д. |
| GetExtensionCmdState() | По запросу LIRA-FEM API возвращает приложению, доступна ли кнопка на ленте, принадлежащая расширению |
| CanExtensionDoAnalysis() | По запросу LIRA-FEM API возвращает приложению, может ли расширение выполнить расчет. Это нужно, например, в сквозном расчете или при настройке параметров расчета |
| UpdateScreenshotScreen() | Вызывается при обновлении копии экрана, созданной с изображением данных расширения. |
| DocumentClosing() | Вызывается при закрытии документа LIRA-FEM. Реализация этого метода должна освободить все ссылки на все объекты документа, которые могут удерживаться объектом расширения |
| HelpContext() | Вызывается, когда пользователь вызывает справку по команде расширения. Реализация этого метода должна открыть соответствующий раздел справки расширения. |
| ApplicationClosing() | Вызывается при закрытии приложения LIRA-FEM. Реализация этого метода должна освободить все ссылки на все объекты приложения, которые могут удерживаться объектом расширения |
Большинство из 11 вышеприведенных в таблице методов интерфейса ILiraExtension имеют тривиальную реализацию, то есть в большинстве случаев эти методы могут ничего не делать. Это касается, например, методов-уведомлений SetApplication(), StateChanged(), DocumentClosing(), ApplicationClosing(). Если расширение не отслеживает нажатие на кнопки ленты, не созданные самим расширением, если расширению не интересна смена текущего загружения или варианта конструирования, эти методы действительно можно оставить пустыми. Еще 3 метода GetExtensionId(), GetExtensionName(), HelpContext() также имеют чрезвычайно простую реализацию. Методы GetExtensionId() и GetExtensionName() - должны просто вернуть две предопределенные строки, а метод HelpContext() - просто вызвать раздел справки, соответствующий имени переданной команды. Немного сложнее будет реализация метода CanExtensionDoAnalysis(). Этот метод должен проверить, достаточно ли у расширения данных, чтобы выполнять расчет. Например, расширение "Дерево" для реализации этого метода убеждается, что заданы его таблицы ввода исходных данных.
Реализация этого метода в "Дереве" могла бы выглядеть так:
bool ILiraExtension.CanExtensionDoAnalysis() // Можно ли выполнять расчет расширению { // с идентификатором "Wud"? LiraApplication App = new LiraApplication(); // Получаем ссылку на приложение LIRA-FEM LiraDocument Doc = App.ActiveDocument; // Получаем ссылку на активный документ LiraTables Ts = Doc.AllTables; // Получаем ссылку на таблицы ввода ILiraExtensionTables ETs = Ts as ILiraExtensionTables; // Приводим ее к интерфейсу для работы с расширениями ILiraExtensionTable ET0 = ETs.FindTable(1, "Wud"); // Ищем таблицу с идентификатором 1 расширения "Wud" ILiraExtensionTable ET1 = ETs.FindTable(2, "Wud"); // Ищем таблицу с идентификатором 2 расширения "Wud" return ET0 != null && ET1 != null; // Если обе таблицы найдены, значит можно выполнять расчет }
В первых трех строках этой функции расширение получает ссылку на контейнер всех таблиц ввода. Этот контейнер содержит также и таблицы, содержащие исходные данные таблиц ввода расширений (тому, как сохраняются исходные данные расширений, в составе LIR-файла посвящен отдельный подраздел ниже). Далее ссылка на контейнер всех таблиц ввода приводится к ссылке на интерфейс ILiraExtensionTables. Мы вполне могли бы обойтись и методами объекта LiraTables по умолчанию, но его интерфейс ILiraExtensionTables содержит удобный метод FindTable(), которым мы и воспользуемся в данном случае. Мы приводим ссылку на контейнер всех таблиц ввода к интерфейсу ILiraExtensionTables и далее вызываем его метод FindTable(), чтобы поискать таблицы ввода, принадлежащие расширению с идентификатором "Wud". Если найдены таблицы ввода с идентификаторами 1 и 2 этого расширения, то функция считает, что данных для расчета достаточно.
Подобным образом должен быть реализован и метод расширения GetExtensionCmdState(), который отвечает приложению на вопрос, доступна ли кнопка на ленте, которая принадлежит расширению. Предположим, что на ленте есть кнопка, которая должна показывать мозаику исходных данных расширения, раскрашивая в разные цвета элементы расчетной схемы. Тогда реализация метода GetExtensionCmdState() должна проверить, заданы ли уже эти исходные данные, и если нет, сделать кнопку недоступной для нажатия. У расширения "Дерево" такая реализация могла бы выглядеть так:
int ILiraExtension.GetExtensionCmdState(LiraCmdIdEnum eCmd, out bool pEnabled)
{
pEnabled = false;
string strFunctionName;
if(m_CmdId2Func.TryGetValue(eCmd, out strFunctionName))
{
if(strFunctionName == "WudTblElsMosaic")
{
LiraApplication App = new LiraApplication(); // Получаем ссылку на приложение LIRA-FEM
LiraDocument Doc = App.ActiveDocument; // Получаем ссылку на активный документ
ILiraTables Ts = Doc.AllTables; // Получаем ссылку на таблицы ввода
ILiraExtensionTables ETs = Ts as ILiraExtensionTables; // Приводим ее к интерфейсу для работы с расширениями
ILiraExtensionTable ET0 = ETs.FindTable(0, "Wud"); // Ищем таблицу с идентификатором 0 расширения "Wud"
pEnabled = (ET0 != null); // Если обе таблицы найдены, значит можно выполнять расчет
}
else //if (strFunctionName == "...")
{
// другие проверки
}
}
return 0;
}
Приведенный выше код метода GetExtensionCmdState() во многом походит на реализацию метода CanExtensionDoAnalysis() с той разницей, что вначале по идентификатору команды eCmd получается имя функции, связанной с этой командой, а потом для этого имени производится поиск соответствующей таблицы ввода. Пока оставим в стороне значение, которое эта функция возвращает, и вернемся к нему в подразделе "Создание обновляемых снимков экрана". Также оставим пока в стороне и реализацию методов UpdateScreenshotScreen(), и CreateTableHelper(), к ним мы вернемся в следующих подразделах. Из-за того, что два метода интерфейса мы оставили без пояснений, итог по интерфейсу ILiraExtension будет только частичным. Из того частичного описания, которое уже получил интерфейс ILiraExtension, можно сделать вывод, что этот интерфейс предназначен для того, чтобы получать уведомления о событиях, происходящих в приложении LIRA-FEM, таких как закрытие документа, закрытие приложения, вызов команды меню или ленты, обновление копии экрана для Книги отчетов. Также этот интерфейс может отвечать на запрос приложения о доступности кнопок на ленте, принадлежащих расширению.
Неописанный в подразделе выше метод интерфейса ILiraExtension.CreateTableHelper() как раз и предназначен для того, чтобы создать на стороне расширения объект, реализующий интерфейс ILiraExtensionTableHelper, который способен сохранять данные расширения вместе с другими данными расчетной схемы внутри файла с расширением .LIR. Всегда ли нужно реализовывать такой объект? Разумеется, нет. Во-первых, расширение может не иметь никаких своих данных и пользоваться только данными документа LIRA-FEM. Если данных нет, то и интерфейс для их сохранения не нужен. Во-вторых, расширение может хранить свои данные в каком-то отдельном файле, поручив пользователю самостоятельно копировать их вместе с LIR-файлом, если требуется переносить задачу с одного компьютера на другой. Но если вы не попали ни в 1, ни во 2 случай, то скорее всего вы захотите реализовать интерфейс ILiraExtensionTableHelper, чтобы хранить данные расширения внутри LIR-файла.
Особенностью данных, которые сохраняются в LIR-файле с помощью интерфейса ILiraExtensionTableHelper, является их прозрачность. Все данные расширения, которые подключаются к документу LIRA-FEM с расчетной схемой при помощи интерфейса ILiraExtensionTableHelper являются либо таблицами ввода, либо их параметрами, и поэтому любой пользователь LIRA-FEM может свободно их просматривать. Методы интерфейса ILiraExtensionTableHelper и его родительского интерфейса ILiraExtensionTableGroupItemHelper приведены в нижеследующей таблице.
| Интерфейс и его методы | Описание |
|---|---|
| ILiraExtensionTableGroupItemHelper, | Предназначен для показа и редактирования параметров группы таблиц ввода, принадлежащих расширению. |
| ILiraExtensionTableHelper |
Предназначен для показа и редактирования таблицы ввода, принадлежащей расширению, а также ее параметров. Общие для двух интерфейсов методы: |
| GetName() | Возвращает имя таблицы ввода или группы таблиц ввода для показа его как элемента дерева в окне "Таблицы ввода". |
| GetExtensionHelperID() | Возвращает уникальный идентификатор таблицы ввода или группы таблиц ввода, принадлежащих расширению. Это должно быть число от 0 до 255. |
| GetParameterCount() | Возвращает количество параметров. Просмотреть параметры можно в окне "Параметры" таблиц ввода |
| GetParameter() | Возвращает данные i-го параметра. Просмотреть параметры можно в окне "Параметры" таблиц ввода |
| SetParameter() | Устанавливает значение i-го параметра таблицы ввода или группы таблиц ввода. Просмотреть параметры можно в окне "Параметры" таблиц ввода. |
| EditParameter() | Предлагает расширению открыть всплывающее окна для редактирования i-го параметра. Возвращает true, если расширение подтвердило редактирование, или false в противном случае. |
| GetParameterAllowedValues() | Возвращает массив вариантов, каждый из которых представляет собой допустимое значение i-го параметра. |
| ILiraExtensionTableHelper | Методы ниже есть только в интерфейсе ILiraExtensionTableHelper: |
| GetColumnCount() | Возвращает количество столбцов в подконтрольной таблице. |
| GetColumn() | Возвращает данные i-го столбца, а именно: его имя, всплывающую подсказку, ширину в процентах от ширины таблицы, тип данных, единицы измерения и количество знаков после запятой для чисел с плавающей запятой и чисел двойной точности. pData — это комбинация флагов LiraTableColumnEnum. |
| EditCell() | Предлагает расширению отредактировать содержимое ячейки подконтрольной таблицы во всплывающем окне. Col и Row — это номера столбца и строки, начинающиеся с нуля. Параметр pCell содержит содержимое ячейки, параметр pRow — содержимое строки с ячейкой в виде массива строк. Расширение может изменять параметры pCell или pRow. |
| GetCellAllowedValues() | Возвращает варианты содержимого ячейки (Row, Col) подконтрольной таблицы в виде массива текстовых строк или вариантов. pDivider — это символ, разделяющий независимую от языка часть текста ячейки от зависимой от языка части. |
| IsDataFromOutside | Это свойство имеет значение true, если данные подконтрольной таблицы не хранятся ни в самой таблице, ни в документе LIRA-FEM. В этом случае для ее пополнения вызывается метод RefillFromOutsideData, а при применении данных вызывается метод ApplyToOutsideData. |
| IsResult | Является ли подконтрольная таблица ввода таблицей результатов. У таблицы результатов нельзя вызывать метод Apply(). |
| RefillFromOutsideData() | Вызывается только в том случае, если свойство IsDataFromOutside имеет значение true. Отменяет все изменения, внесенные в таблицу, и заполняет ее содержимое данными из внешнего источника данных, определенного расширением Lira. |
| CanApply() | Вызывается только в том случае, если свойство IsDataFromOutside имеет значение false. Проверяет наличие ошибок в принадлежащей таблице. Возвращает ненулевое значение, если ошибок не обнаружено, или 0 в противном случае. pErrs получает информацию об ошибках, если таковые имеются. Формат ошибок такой же, как в методе LiraTable.Apply. |
| ApplyToOutsideData() | Вызывается только в том случае, если свойство IsDataFromOutside имеет значение true. Проверяет ошибки и применяет содержимое таблицы. Сбрасывает флаг IsModified таблицы. Возвращает ненулевое значение в случае успеха или 0 в противном случае. Формат pErrs такой же, как в методе LiraTable.Apply. |
| FindInModel() | Возвращает pElementNumbers или pSelectedNodes (оба значения начинаются с 1), соответствующие строкам (с нулевой индексацией) таблицы. Каждый параметр, кроме Table, представляет собой массив вариантов, каждый вариант содержит значение типа long. |
| FindInTable() | Возвращает pRowNumbers (начиная с 0) элементов таблицы, соответствующих ElementNumbers или NodeNumbers (оба параметра начинаются с 1). Каждый параметр, кроме Table, представляет собой массив вариантов, каждый вариант содержит значение типа long. |
| CopyToAdaptCellValue() | Вызывается методом CopyTo, если 1 конечный элемент (КЭ) в целевом документе (ЦД) соответствует 2 или больше КЭ в исходном документе (ИД). Параметр SrcCells представляет собой массив вариантов, по одному для каждого КЭ в ИД. Необходимо вернуть значение КЭ в ЦД. Все значения находятся в столбце Col. |
| DocumentClosing() | Вызывается перед закрытием документа, содержащего подконтрольную таблицу. |
Методы интерфейсов ILiraExtensionTableGroupItemHelper и ILiraExtensionTableHelper позволяют полностью контролировать соответствующую группу таблиц ввода или таблицу ввода. Чтобы создать собственную группу таблиц ввода или таблицу ввода, расширение должно воспользоваться соответствующим методом интерфейса ILiraExtensionTableGroup. Например, в ответ на нажатую на ленте кнопку "Создать таблицу исходных данных" расширение может выполнить следующий блок кода:
LiraApplication LiraApp = new LiraApplication(); // Получаем ссылку на приложение LIRA-FEM LiraDocument LiraDoc = LiraApp.ActiveDocument; // Получаем ссылку на активный документ LiraTables Tables = LiraDoc.AllTables; // Получаем ссылку на контейнер всех таблиц ILiraExtensionTableGroup ExtTables = Tables as ILiraExtensionTableGroup; // Преобразовываем ссылку // Создаем объект, управляющий группой таблиц ввода из нашего расширения Wood ILiraExtensionTableGroupItemHelper GrpHelper = new WoodLiraExtensionTableGroupHelper(); // Создаем группу таблиц ввода, подконтрольную объекту GrpHelper ILiraExtensionTableGroup WoodTableGroup = ExtTables.AddTableGroup(GrpHelper, "Wud"); // Создаем объект, управляющий таблицей ввода исходных данных нашего расширения Wood ILiraExtensionTableHelper TblHelper = new WoodLiraExtensionTableHelper(); // Создаем таблицу ввода, подконтрольную объекту TblHelper, в подконтрольной группе ILiraExtensionTable WoodTable = WoodTableGroup.AddTable(TblHelper, "Wud");
После того, как была создана группа таблиц ввода или таблица ввода, она становится видной в окне "Таблицы ввода" и начинает сохраняться вместе с расчетной схемой в LIR-файле. Во время настройки параметров группы таблиц ввода или таблицы ввода, подконтрольной расширению, вызываются методы интерфейса ILiraExtensionTableGroupItemHelper, а во время редактирования таблицы ввода, подконтрольной расширению, вызываются методы интерфейса ILiraExtensionTableHelper. Таким образом с точки зрения пользователя редактирование данных расширения ничем не отличается от редактирования данных расчетной схемы при помощи таблиц ввода.
Данные расширения, сохраненные внутри LIR-файла вместе с подконтрольной расширению таблицей ввода или группой таблиц ввода при загрузке необходимо вновь связать с расширением. Для этого в интерфейсе ILiraExtension и предусмотрен метод CreateTableHelper(). Метод ILiraExtension.CreateTableHelper() должен вернуть ссылку на объект-хелпер для таблицы или группы таблиц, подконтрольной расширению по ее идентификатору.
ILiraExtensionTableGroupItemHelper ILiraExtension.CreateTableHelper(ILiraExtensionTables ExtTables, long ExtensionHelperID)
Возвращенная ссылка связывается с таблицей или с группой таблиц ввода и так делает эту таблицу или группу таблиц снова подконтрольной расширению после загрузки LIR-файла.
Разумеется, расширение может создавать файлы с абсолютно любыми именами. Однако если имя файла результатов будет совершенно произвольное, пользователю придется хранить у себя в голове, какой файл следует забирать с собой, когда ему придется передавать задачу с результатами на другой компьютер. С другой стороны, в LIRA-FEM есть встроенная возможность создать ZIP-архив с исходными данными задачи и результатами. Этот подраздел содержит очень простые требования, в какой папке и под каким именем следует сохранять файл с результатами расчета расширения с тем, чтобы они попали в ZIP-архив с прочими результатами расчета расчетной схемы.
Расширение файлов может иметь больше, чем три символа, однако окна наподобие "Открыть файл" не различают расширения файлов, у которых первые три символа одинаковые, поэтому ограничение длины расширения файла тремя символами будет разумным решением. Идентификатор расширения, которое породило такой файл в пределах LIRA-FEM уникальный, поэтому использовать его для дифференциации файлов результатов тоже выглядит разумным.
Если результатом расчета расширения является прямоугольная таблица, ее можно включить в систему документирования LIRA-FEM под названием Книга отчетов. Книга отчетов позволяет накапливать скриншоты - снимки экрана, таблицы и текстовые документы, обновлять их после пересчетов и верстать из них единый отчет в формате .DOCX. Чтобы ваша таблица результатов могла быть включена в Книгу отчетов, необходимо сперва сделать из нее таблицу ввода, подконтрольную расширению. Другими словами, необходимо предусмотреть для таблицы результатов отдельный объект, который реализует интерфейс ILiraExtensionTableHelper и после расчета добавить эту таблицу к остальным таблицам ввода.
LiraApplication LiraApp = new LiraApplication(); LiraDocument LiraDoc = LiraApp.ActiveDocument; LiraTables Tables = LiraDoc.AllTables; ILiraExtensionTableGroup ExtTables = Tables as ILiraExtensionTableGroup; // Находим ранее созданную группу таблиц ввода, подконтрольную нашему расширению (пусть ее ID = 0) ILiraExtensionTableGroup WoodTableGroup = ExtTables.FindTableGroup(0, "Wud"); // Создаем объект, управляющий таблицей ввода результатов ILiraExtensionTableHelper ResultTblHelper = new WoodLiraExtensionResultTableHelper(); // Создаем таблицу ввода, подконтрольную объекту ResultTblHelper, в подконтрольной группе ILiraExtensionTable WoodResultTable = WoodTableGroup.AddTable(ResultTblHelper, "Wud");
Таблица ввода результатов по сути не будет являться таблицей ввода, потому что изменять результаты нельзя. Кнопка "Применить" в такой таблице не будет делать ничего. Свойство ILiraExtensionTableHelper.IsDataFromOutside должно возвращать значение true. Все, что можно сделать с такой таблицей -- это заново перезаполнить ее при помощи метода ILiraExtensionTableHelper.RefillFromOutsideData(), чтобы обновить ее данные. Любую таблицу ввода, в том числе и содержащую результаты можно добавить в Книгу отчетов. Программно это можно сделать при помощи метода LiraTable.AddToReportBook(). Таким образом и таблицы ввода исходных данных, и таблицы ввода результатов, подконтрольные расширению, можно легко включить в Книгу отчетов и сверстать в единый с остальными результатами DOCХ-файл.
В подразделе "Визуализация данных расширения при помощи мозаик" мы показали, как можно программно построить произвольную мозаику, раскрасив элементы расчетной схемы в разные цвета. Построенную таким образом мозаику, изополе или эпюры можно добавить в Книгу отчетов, чтобы включить в общий отчет по задаче. Ни для построения мозаик, ни для включения их в Книгу отчетов не требовалось разрабатывать какие-либо объекты, которые реализуют предопределенные интерфейсы. Но все же у мозаик, добавленных в Книгу отчетов есть проблема - они не обновляемы, и если при очередном пересчете задачи результаты расчета вашего расширения изменились, то соответствующие мозаики в Книге отчетов придется переснимать вручную.
Однако если вы и реализовываете интерфейс ILiraExtension в своем объекте, вы можете реализовать и его метод ILiraExtension.UpdateScreenshotScreen(). Этот метод как раз и предназначен для перегенерации снимков экрана, уже добавленных в Книгу отчетов. Правда, для этого надо знать один секрет: надо подписать свою мозаику, чтобы потом "узнать" свою подпись и обновить мозаику уже согласно новым данным.
Итак, подписываем свою мозаику. Для разнообразия сделаем это не на языке VBScript, как это было сделано в разделе "Визуализация данных расширения при помощи мозаик", а на языке C#.
void CreateMosaic(string strTableContentPostfix)
{
// Подключаемся к объекту LiraApplication и получаем активный документ с расчетной схемой
LiraApplication LiraApp = new LiraApplication();
LiraDocument LiraDoc = LiraApp.ActiveDocument;
// Создаём таблицу мозаики
object Params1 = new object[] { "Element text mosaic", "11" + strTableContentPostfix, 1 };
LiraTable Mosaic1 = LiraDoc.AllTables.CreateNewItem(LiraTableEnum.kLiraTable_UserMosaicData, Params1) as LiraTable;
// Данные для мозаики (массив 2D)
object Data1 = new object[2,5]{{ "", 1, "", "1.1 Красный цвет", "#ff4444" },
{ "", 2, "", "2.2 Зеленый цвет", "#008800" }};
// Заполняем таблицу
Mosaic1.SetContents(Data1);
// Применяем изменения
string strErrs = "";
Mosaic1.Apply(out strErrs);
//Убираем за собой -- удаляем только что созданную таблицу
//LiraDoc.AllTables.Delete(LiraDoc.AllTables.ItemCount - 1);
}
Если сравнить эту функцию на C# с ее предшественницей, написанной на VBScript, можно заметить, что у новой функции появился параметр strTableContentPostfix, который добавляется как постфикс ко второму по счету параметру в массиве, передаваемом в функцию AllTables.CreateNewItem()
Если присмотреться еще внимательней, то этот самый параметр в массиве стал из типа int типом string, что нормально, иначе мы бы не смогли добавить в к нему суффикс. И, наконец, последняя строка функции, которая удаляла только что созданную таблицу ввода с исходными данными мозаики, закомментирована. Кстати, оставлять таблицу с исходными данными мозаики среди таблиц ввода, принадлежащих расширению - не такая уж и плохая идея. Это позволяет пользователю впоследствии открыть эту таблицу ввода и настроить ее изображение на расчетной схеме. Именно так поступает расширение Дерево - оставляет таблицу ввода с мозаикой, чтобы пользователь мог ее при желании настроить.
Вызовем эту функцию в уже зарегистрированной функции расчета, передав в нее "правильный" постфикс strTableContentSuffix.
public void DoAnalysis()
{
System.Windows.Forms.MessageBox.Show("Timber analysis performed!");
CreateMosaic(". Src=Wud:MyMosaicSign");
}
Далее нажмем на кнопку "Timber Analysis", откроем окно Таблиц ввода с новосозданной таблицей и посмотрим на ее параметры. Окна приложения будут выглядеть примерно как на следующем рисунке.
Как видно, во второй по счету параметр таблицы ввода попал наш "правильный" постфикс "Src=Wud:MyMosaicSign"
В описании этого параметра сказано, что постфикс этого параметра как раз и должен содержать подпись расширения, которое его создало. Причем формат постфикса должен быть следующим:
. Src=Имя:Параметры
здесь
. Src= - это идентификатор, показывающий, что за ним идут данные расширения,
Имя: - это трехбуквенный идентификатор расширения, за которым следует символ двоеточия - разделитель между идентификатором расширения и параметрами мозаики
Параметры - это, собственно, и есть подпись, которую должна распознать функция ILiraExtension.UpdateScreenshotScreen().
Во время обновления снимка экрана приложение LIRA-FEM распознает снимок экрана, выполненный по таблице ввода, содержащей данные пользовательской мозаики, ищет ее "подпись" и вызывает у расширения с соответствующим идентификатором метод ILiraExtension.UpdateScreenshotScreen(), передав в этот метод подпись, то есть данные после идентификатора ". Src=". В нашем случае в функцию ILiraExtension.UpdateScreenshotScreen() попадет параметр "Wud:MyMosaicSign". В ответ расширение должно распознать свою подпись, и если она распознана - вновь построить такую же мозаику по свои текущим данным в окне расчетной модели, использовав при этом, разумеется все ту же таблицу ввода для построения пользовательской мозаики. Давайте реализуем такую функцию, заменив красный цвет мозаики на синий, чтобы убедится, что обновление действительно произошло.
bool ILiraExtension.UpdateScreenshotScreen(string strSrc, string strDat, LiraTable DstTable)
{
if(strSrc != "Wud:MyMosaicSign")
{
return false; // Эта подпись нам не известна
}
if(DstTable == null) // Если таблица ввода для этой мозаики была удалена --
{ // пересоздаем ее заново
LiraApplication LiraApp = new LiraApplication(); // Подключаемся к объекту LiraApplication
LiraDocument LiraDoc = LiraApp.ActiveDocument; // получаем активный документ с расчетной схемой
object Params1 = new object[] { "Element text mosaic", "11. Src=" + strSrc, 1 }; // Параметры создания таблицы
DstTable = LiraDoc.AllTables.CreateNewItem(LiraTableEnum.kLiraTable_UserMosaicData, Params1) as LiraTable;
}
object Data1 = new object[2, 5] {{ "", 1, "", "1.1 Синий цвет", "#0000ff" }, // Данные для мозаики (массив 2D)
{ "", 2, "", "2.2 Зеленый цвет", "#008800" }};
DstTable.SetContents(Data1); // Заполняем таблицу
DstTable.Apply(out string strErrs); // Применяем изменения.
// Удалять таблицу не будем, чтобы пользователь мог впоследствии изменить ее представление в окне расчетной схемы по своему вкусу
return true; //обновление прошло успешно
}
Чтобы проверить, как эта функция сработала, добавим в Книгу отчетов снимок экрана, на котором изображена мозаика, построенная из функции DoAnalysis() выше. Затем щелкнем на снимке правой кнопкой мыши и выберем команду "Обновить выделенные элементы". Метод ILiraExtension.UpdateScreenshotScreen() отработает и зеленый цвет на мозаике и на снимке в Книге отчетов изменится на синий:
Из диаграммы в подразделе "Объекты и интерфейсы LIRA-FEM API для расширений" было видно, что для работы с расширениями LIRA появились объекты LiraExtensions и LiraRibbon, которые обеспечивают подключение расширений, а другие объекты получили дополнительные программные интерфейсы. Но и в основных объектах появились новые функции, предназначенные для работы с расширениями. В этом подразделе мы прокомментируем важнейшие из них.
| Объект и его методы | Описание |
|---|---|
| LiraDocument | Документ, содержащий расчетную схему |
| CurrentLoadCase | Номер загружения в режиме задания исходных данных. Устанавливает или возвращает число, от 1, для текущего загружения исходных данных (или стадии монтажа, если применимо) |
| CurrentDesignOption | Номер варианта конструирования. Устанавливает или возвращает число, от 1, обозначающее текущий вариант конструирования |
| LiraApplication | Приложение |
| Extensions | Возвращает ссылку на объект LiraExtensions (см. раздел "Объекты и интерфейсы LIRA-FEM API для расширений") |
| Ribbon | Возвращает ссылку на объект LiraRibbon (см. раздел "Объекты и интерфейсы LIRA-FEM API для расширений") |
| GetFilePath() | Позволяет получить пути к папкам, которые настраиваются в окне "Каталоги" LIRA-FEM |
| GetInterfaceLanguage() | Возвращает язык графического пользовательского интерфейса LIRA-FEM |
| GetCmdState() | Возвращает состояние элемента меню/панели инструментов/ленты (кнопки), соответствующего команде, заданной в параметре Cmd. Параметр pEnabled возвращает значение, указывающее, включен ли элемент (кнопка). Параметр pSel возвращает состояние элемента: 0 — не выбран (не отмечен, не нажат), 1 — выбран (отмечен, нажат). |
| SetCmdState() | Запускает команду с идентификатором, заданным в параметре Cmd. В отличие от метода LiraApplication.StartCmd, этот метод не возвращает управление до завершения выполнения команды. |
| GetViewState() | Предназначен для определения текущего загружения, варианта конструирования и прочих текущих настроек, которые отображаются в строке статуса окна LIRA-FEM. Возвращает состояние выпадающего списка, переданного в параметре Ctrl. Параметр pEnabled возвращает значение, указывающее, включен ли список. Параметр pSel возвращает номер выбранного элемента в списке (от 0 до -1 означает, что ничего не выбрано). Необязательный параметр pItems возвращает текст всех элементов списка в виде массива строк. |
| SetViewState() | Предназначен для изменения текущего загружения, варианта конструирования и прочих текущих настроек, которые отображаются в строке статуса окна LIRA-FEM. Устанавливает новый выбранный элемент Sel выпадающего списка, переданного в параметре Ctrl |
| GetViewStateTimePoints() | Получает массив точек интегрирования для просмотра результатов расчета задачи динамики во времени. Возвращает массив значений типа long (шагов интегрирования, начиная с 1) . Параметр TimeHistory указывает номер динамики во времени, начиная с 1, параметр pStep возвращает шаг в секундах, pPointCount — общее количество доступных временных точек. |
| SetViewStateTimePoints() | Задает временные точки (шаги интеграции) для просмотра результатов расчета задачи динамики во времени. Параметр lTimeHistory указывает номер динамики во времени, начиная с 1, TimePoints — это массив, содержащий шаги интегрирования (начиная с 1), необходимые для просмотра. |
Среди вышеприведенных методов хотелось бы отметить несколько из них, которые могут оказаться наиболее полезными.
Во-первых, LiraApplication.SetCmdState() позволяет запускать команды или переключать режимы работы приложения, при чем этот новый метод ожидает завершения команды, а не сразу же возвращает управление, в отличие от метода LiraApplication.StartCmd(), после вызова которого необходимо было ожидать неопределенное время, пока метод LiraApplication.StartCmd() выполнится.
Во-вторых, в метод LiraApplication.GetViewState() можно передать параметр Ctrl=kLiraViewCtl_MainWindow (kLiraViewCtl_MainWindow=2000), и узнать HANDLE этого окна - он попадает в параметр pItems этого метода. Еще, передав в этот метод параметр Ctrl=kLiraViewCtl_Plot (kLiraViewCtl_Plot=1000), можно узнать, включена ли сейчас какая-то мозаика или эпюры. Если в настоящий момент включена мозаика, построенная при помощи таблицы ввода пользовательской мозаики, то в параметре pItems этого метода можно получить ее подпись. Можно также отключить показ мозаики, вызвав метод LiraApplication.SetViewState() с параметром Ctrl=kLiraViewCtl_Plot и параметром Sel=0.
Обладая этими сведениями, мы, наконец, можем дописать метод ILiraExtension.GetExtensionCmdState(), в котором возвращаемое значение всегда оставалось нулевым. Теперь мы можем определить, что активна наша мозаика и вернуть ненулевое значение, чтобы ее кнопка оказалась "нажатой" на ленте инструментов.
public void Startup()
{
...
//Добавим еще одну функцию и кнопку для построения мозаики
LiraExts.AddExtensionFunction("Wud", "Wood.WoodExtension.DrawPlot", strThisDllPath, LiraCallAfterEnum.kLiraCallAfter_Button, ref fFunctionsOrder);
eCmd = Ribbon.AddButton("Wood","Analysis",-1,"Wud","Wood.WoodExtension.DrawPlot","Mosaic");
m_CmdId2Func[eCmd] = "Wood.WoodExtension.DrawPlot";
}
static Dictionary<LiraCmdIdEnum, string> m_CmdId2Func = new Dictionary<LiraCmdIdEnum, string>();
public void DoAnalysis() { System.Windows.Forms.MessageBox.Show("Timber analysis performed!"); }
public void DrawPlot() { CreateMosaic(". Src=Wud:MyMosaicSign"); }
//Обновленная реализация метода ILiraExtension.GetExtensionCmdState()
int ILiraExtension.GetExtensionCmdState(LiraCmdIdEnum eCmd, out bool pEnabled)
{
pEnabled = false;
string strFunctionName;
if(m_CmdId2Func.TryGetValue(eCmd, out strFunctionName))
{
LiraApplication App = new LiraApplication(); // Получаем ссылку на приложение LIRA-FEM
LiraDocument Doc = App.ActiveDocument; // Получаем ссылку на активный документ
if(strFunctionName == "Wood.WoodExtension.DoAnalysis")
{
ILiraTables Ts = Doc.AllTables; // Получаем ссылку на таблицы ввода
ILiraExtensionTables ETs = Ts as ILiraExtensionTables; // Приводим ее к интерфейсу для работы с расширениями
ILiraExtensionTable ET0 = ETs.FindTable(0, "Wud"); // Ищем таблицу с идентификатором 0 расширения "Wud"
pEnabled = (ET0 != null); // Если обе таблицы найдены, значит можно выполнять расчет
}
else if(strFunctionName == "Wood.WoodExtension.DrawPlot")
{
pEnabled = true; // Пусть кнопка мозаики будет всегда доступна
bool bPlotEnabled = false;
object pItems = null;
if(App.GetViewState(LiraViewCtlEnum.kLiraViewCtl_Plot, out bPlotEnabled, ref pItems) != 0 && bPlotEnabled)
{ // Какая-то мозаика включена. Это наша?
object[] Items = pItems as object[];
if(Items != null && Items.Length > 0)
{
string strPlot = Items[0] as string;
if(strPlot != null && strPlot.Contains(". Src=Wud:MyMosaicSign"))
{// Да, эта мозаика наша. Зажимаем кнопку:
return 1;
}
}
}
}
else //if (strFunctionName == "...")
{
// другие проверки
}
}
return 0;
}
По разным причинам удобно бывает сосредоточить внимание пользователя на одном или нескольких элементах расчетной схемы. Для этого в LIRA-FEM встроены так называемые локальные режимы конструирования железобетонных конструкций ЛАРМ и металлических конструкций СТК. В локальном режиме расчета металлических конструкций СТК, например, доступна трассировка расчета, то есть разворачивание чисел конечного результат в формулы, вплоть до исходных усилий и геометрических характеристик металлических профилей, тогда как в металлическом расчете LIRA-FEM такая трассировка недоступна. Локальный режим позволяет вынести из LIRA-FEM некоторые функции, например, требующие существенного дополнительного вычислительного времени.
LIRA-FEM API предоставляет разработчикам расширений возможность создавать подобные режимы работы своего расширения, причем автоматически переносит почти все возможности редактирования исходных данных и создания результатов из приложения LIRA-FEM в локальный режим. Не переносятся разве что возможности построения мозаик на расчетной схеме, потому что полной расчетной схемы в локальном режиме нет. Примером локального режима является приложение Wood.exe - локальный режим расширения Дерево.
Если мы откроем Wood.exe, мы увидим интерфейс, очень похожий на интерфейс окна Таблицы ввода.
В нем такие же таблицы ввода расширения Дерево, как и в LIRA-FEM, и при нажатии на троеточие в ячейке открываются все те же окна для редактирования содержимого ячейки. Все эти возможности автоматически предоставляются LIRA-FEM API, а именно специализированным элементом управления LiraExtensionTablesControl class. Пользователь этого элемента управления найдет в нем реализацию уже знакомых интерфейсов LIRA-FEM API. Диаграмма взаимодействия объектов и интерфейсов локального режима работы расширения показана ниже.
LIRA-FEM API Расширение LIRA-FEM
Элемент управления
LiraExtensionTablesControl
¦
¦ Все группы и таблицы ввода
'--LiraExtensionTables
ILiraExtensionTables
¦ ¦ Объект для управления
¦ ¦ таблицами ввода расширения
¦ '------------------------------<<--ILiraExtensionTableGroupHelper
¦
¦ Группа таблиц ввода документа
¦--LiraExtensionTableGroup
¦ ILiraExtensionTableGroup
¦ ¦ ¦ Объект для управления
¦ ¦ ¦ группой таблиц ввода расширения
¦ ¦ '------------------------------<<--ILiraExtensionTableGroupHelper
¦ ¦
¦ ¦ Таблица ввода документа
¦----'--LiraExtensionTable
¦ ¦
¦ ¦ Таблица ввода расширения
¦----'--LiraExtensionTable
¦ ¦ Объект для управления
¦ ¦ таблицей ввода расширения
¦ '------------------------------<<--ILiraExtensionTableHelper
¦
¦ Настройки единиц измерения
'--LiraExtensionMeasurementUnits
ILiraExtensionMeasurementUnits
Проанализируем различия локального режима работы и режима работы в составе LIRA-FEM. В локальном режиме работы нет объектов LiraApplication и LiraDocument, место последнего занимает элемент управления LiraExtensionTablesControl class. В нем содержится параллельная реализация таблиц ввода, в том числе контейнера всех таблиц ввода ILiraExtensionTables. Внутри этого контейнера можно создавать таблицы ввода и их группы. Правда, объекты таблиц ввода и их групп в этой реализации не поддерживают интерфейсы [I]LiraTable и [I]LiraTableGroup, но расширение может пользоваться их версиями ILiraExtensionTable и ILiraExtensionTableGroup. Эти интерфейсы поддерживаются и в режиме работы в LIRA-FEM, так что в большинстве случаев расширение может пользоваться версиями программных интерфейсов *LiraExtensionTable* вместо *LiraTable*. Только когда речь идет о взаимодействии с расчетной схемой расширение может запрашивать интерфейсы *LiraTable*, а через них и объекты типа LiraDocument или LiraApplication.
В остальных же случаях возможностей интерфейсов *LiraExtensionTable* будет вполне достаточно. Единицы измерения доступны только в виде интерфейса ILiraExtensionMeasurementUnits, но опять-таки это не проблема, так как он поддерживает все методы интерфейса [I]LiraMeasurementUnits, а раз так, то расширение может использовать ILiraExtensionMeasurementUnits всегда - как в режиме работы в LIRA-FEM, так и в локальном режиме работы.
| Интерфейс и его методы | Описание |
|---|---|
| LiraExtensionTablesControl | Основной интерфейс расширения для работы в среде LIRA-FEM |
| AllowEditTree | Позволяет пользователю удалять или перемещать элементы в древовидном представлении этого элемента управления. |
| Tables | Все таблицы ввода одного документа локального режима работы расширения |
Коренным отличием локального режима работы расширения от режима работы в LIRA-FEM является отсутствие в локальном режиме объекта ILiraExtension. Этот объект никогда не создается, а взамен его приложение должно поддерживать объект, который реализует интерфейс ILiraExtensionTablesHelper. Его единственное назначение по сути - создавать объекты ILiraExtensionTableGroupHelper и ILiraExtensionTableHelper при загрузке документа локального режима. Интерфейс ILiraExtensionTablesHelper невелик:
| Интерфейс и его методы | Описание |
|---|---|
| ILiraExtensionTablesHelper | Служебный интерфейс, замена ILiraExtension, который позволяет загружать таблицы ввода из файлов, хранящихся на жестком диске |
| CreateTableHelper() | По запросу LIRA-FEM API создает и возвращает объект, управляющий таблицей ввода расширения ILiraExtensionTable или группой таблиц ввода расширения ILiraExtensionTableGroup |
| GetExtensionId() | Возвращает трехбуквенный идентификатор расширения |
| GetExtensionName() | Возвращает имя расширения |
| ExtensionDocumentClosing() | Вызывается при закрытии автономного документа в автономном приложении расширения. Требует освобождения ссылок на объекты в автономном документе. |
Чтобы создать локальный режим работы расширения LIRA-FEM, необходимо создать приложение .EXE и разместить на его форме или диалоговой панели элемент управления LiraExtensionTablesControl class. В Microsoft Visual Studio для этого следует щелкнуть правой кнопкой мыши в окне Toolbox, выбрать пункт контекстного меню Choose Items, затем включить на закладке COM элемент управления LiraExtensionTablesControl class и нажать OK.
После размещения элемента управления на форме он будет выглядеть так:
Если вам не удалось с первого раза разместить этот элемент управления на форме, выполните следующие действия:
Как видно после размещения элемента управления на форме, он инкапсулирует редактирование таблиц ввода. Вашему приложению надо просто инстанциировать нужные из них, как это делал объект ILiraExtension. Язык элемента управления соответствует языку LIRA-FEM.
Сохранение и загрузка данных осуществляется при помощи методов ILiraExtensionTables.SaveToFile() и ILiraExtensionTables.LoadFromFile(). Благодаря тому, что метод ILiraExtensionTables.LoadFromFile() может читать данные, записанные методом LiraTables.ExportToFile(), очень легко выполнить передачу данных из режима работы в LIRA-FEM в локальный режим работы расширения. В расширении Дерево для этого предусмотрена специальная команда "Локальный режим расчета элемента". При вызове этой команды создается несколько временных таблиц, в которых расширение собирает данные исключительно выделенных на расчетной схеме элементов, затем выполняет их экспорт при помощи метода LiraTables.ExportToFile() и далее открывает этот файл приложением Wood.exe.
По умолчанию в локальном режиме работы расширения операции с таблицами ввода, такие как переименование, перемещение или копирование таблиц в дереве при помощи перетаскивания мышкой или буфера обмена отключены. Включить их можно в свойстве AllowEditTree элемента управления LiraExtensionTablesControl class, размещенного на форме. Все экспортированные из режима LIRA-FEM в локальный режим таблицы, которые не имеют своей реализации интерфейса ILiraExtensionTableHelper, будут изображаться в локальном режиме просто как текст и без возможности редактирования ячеек в соответствующих диалоговых панелях. В локальном режиме недоступно построение мозаик на расчетной схеме и документирование при помощи Книги отчетов.
Элемент управления LiraExtensionTablesControl class устанавливается и удаляется вместе с LIRA-FEM, однако для своей работы не требует лицензии LIRA-FEM.
| Раздел | Параметр | Допустимые значения | Комментарии | Соответствующий метод API |
|---|---|---|---|---|
HKEY_LOCAL_MACHINE\Software\LIRA EXTENSIONS\ |
Раздел для регистрации всех расширений | |||
| Abc | Только латиница и цифры | Трехбуквенный идентификатор расширения | LiraExtension.AddExtension() | |
| (По умолчанию) | Script:VBS | Расширение написано на языке VBScript | то же | |
| Script:JS | Расширение написано на языке JScript | |||
| Script:V8 | Расширение написано на языке V8 Java Script | |||
| Dll:Net4 | Расширение - это DLL на .NET Framework 4 (язык С# и т.п.) | |||
| Dll:stdcall | Расширение - это native DLL с соглашением о вызовах _stdcall | |||
| Dll:cdecl | Расширение - это native DLL с соглашением о вызовах _cdecl | |||
| Exe:App | Расширение - это отдельное приложение EXE | |||
| Version | 20AB - 20CD | С какими версиями LIRA-FEM совместимо расширение, например: "2026 - 2027". Если это значение не указано, приложение совместимо со всеми версиями LIRA-FEM, начиная от 2026. | то же | |
| Name | Произвольный текст | Имя расширения | то же | |
| RibbonTab | Произвольный текст | Имя вкладки на ленте инструментов, на которой будут располагаться кнопки для расширения | LiraRibbon.AddExtensionTab() | |
| RibbonTabImageListSmall | Ограничены файловой системой ОС | Путь к горизонтальному спрайту с изображениями 16x16 или 24x24 (в зависимости от настройки "Крупные значки на ленте") для кнопок расширения на ленте инструментов | то же | |
| RibbonTabImageListLarge | Ограничены файловой системой ОС | Путь к горизонтальному спрайту с изображениями 32x32 или 48x48 (в зависимости от настройки "Крупные значки на ленте") для кнопок расширения на ленте инструментов | то же | |
| Function | Ограничены языком программирования | Имя функции или метода расширения с учетом пространства имен и имени класса, если они есть | LiraExtension.AddExtensionFunction() | |
| (По умолчанию) | Ограничены файловой системой ОС | Путь к файлу VBS/JS или DLL/EXE, содержащего функцию | то же | |
| CallAfter | Button | Функция должна быть вызвана по нажатию кнопки на ленте | то же | |
| AppStartup | Функция должна быть вызвана непосредственно после загрузки приложения* | |||
| Analysis000 | Функция должна быть вызвана перед конечно-элементным (КЭ) расчетом* | |||
| AnalysisFEA | Функция должна быть вызвана непосредственно после КЭ расчета* | |||
| AnalysisCLA | То же, после расчета сочетаний нагрузок и воздействий СНВ* | |||
| AnalysisDCF | То же, после расчета расчетных сочетаний усилий РСУ* | |||
| AnalysisUCF | То же, после расчета унифицированных усилий РСУ* | |||
| AnalysisDCL | То же, после расчета расчетных сочетаний нагрузок РСН* | |||
| AnalysisLoF | То же, после расчета нагрузок на фрагмент* | |||
| AnalysisPES | То же, после расчета главных и эквивалентных напряжений* | |||
| AnalysisCRK | То же, после расчета ширины раскрытия трещин после нелинейного расчета* | |||
| AnalysisDOs | То же, после расчета вариантов конструирования (ж/б, металл, кирпич)* | |||
| AnalysisCSV | То же, после создания CSV файлов результатов (если заказано)* | |||
| Name | Произвольный текст | Подпись кнопки на ленте** | LiraRibbon.AddButton() | |
| ToolTip | Произвольный текст | Подсказка кнопки на ленте** | то же | |
| Description | Произвольный текст | Описание кнопки на ленте** | то же | |
| RibbonImageSmall | Ограничены файловой системой ОС | Номер от 0 в спрайте или путь к изображению 16x16 или 24x24 (в зависимости от настройки "Крупные значки на ленте")** | то же | |
| RibbonImageLarge | Ограничены файловой системой ОС | Номер от 0 в спрайте или путь к изображению 32x32 или 48x48 (в зависимости от настройки "Крупные значки на ленте")** | то же | |
| RibbonPanel | Произвольный текст | Имя панели на вкладке ленты инструментов, на которой располагается кнопка | LiraRibbon.AddPanel() | |
| RibbonAlwaysLarge | 1 или 0 | Кнопка всегда большая** | LiraRibbon.AddButton() | |
| HelpCommand | Ограничены файловой системой ОС | Вызов справки для этой функции расширения**, например: C:\Program Files (x86)\LIRALAND\LIRA-FEM 2026\bin\x64\help\ru\LiraFEM.chm |
ILiraExtension.HelpContext() | |
| * Можно указать порядок вызова в виде числа double после знака плюс "+", например, Analysis000 + 123.456 | ||||
| ** Только для функций с "CallAfter"="Button" | ||||
В этом подразделе перечисляются, на каких языках можно писать и отлаживать расширения LIRA-FEM.
Поддерживаемые языки программирования in-proc:
Поддерживаемые языки программирования out-proc:
Отладка in-proc:
Отладка out-proc:
Заметили ошибку? Выделите ее и нажмите Ctrl+Enter, чтобы сообщить нам.
Комментарии