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 "Ну, привет, 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. Если во время выполнения действий выше программа уже была запущена, её нужно перезапустить. После запуска можно убедиться, что на ленте появилась новая вкладка «Инструменты» («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 по созданию кнопок на ленте ничем не уступают возможностям самой программы, и подтверждением этому служит вкладка «Дерево» («Timber»), полностью построенная одноимённым расширением.
Новые вкладки, панели и пиктограммы команд — всё это можно добавить на ленту 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 без дополнительного маршалинга параметров. Если вызов метода API из исполняемого модуля *.EXE может занять миллисекунды, то вызов того же метода из библиотеки *.DLL занимает наносекунды, то есть в миллионы раз быстрее. Для регистрации расширений в исполняемых модулях *.EXE предусмотрен параметр реестра @="Exe:App". Динамические библиотеки *.DLL могут быть скомпилированы в код .NET CLR (например, C# или VB.NET) либо в нативный код (например, C, C++). Параметры реестра для регистрации зависят от выбранного языка. Для библиотеки классов на .NET CLR предусмотрен параметр @="Dll:Net4", а для нативного кода — @="Dll:stdcall" или @="Dll:cdecl", в зависимости от соглашения о вызовах функций. Соглашение stdcall наиболее распространено, но в C/C++ требует ключевого слова __stdcall. Если оно отсутствует, то следует использовать @="Dll:cdecl".
В подразделе «Быстрый старт» для идентификации нашего расширения мы добавили в реестр Windows HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS параметр hli. Этот параметр состоит из трёх латинских букв. Ограничение связано с расширениями файлов и будет подробно объяснено в подразделе «Требования к именованию файлов результатов».
Идентификатор расширения — трёхбуквенный параметр, который может состоять только из латинских букв и цифр.
Для регистрации расширения LIRA-FEM необходимо в разделе реестра Windows HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS создать новый подраздел с именем — идентификатором расширения.
В качестве параметра по умолчанию следует указать инструкцию загрузки расширения, одно из следующих значений:
.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, тем позже будет запускаться функция расширения.
Регистрацию функций расширения можно выполнять не только с помощью ключей реестра, но и методами LIRA-FEM API, причём последний предоставляет больше возможностей. Однако в реестре Windows в любом случае должна быть зарегистрирована хотя бы одна функция расширения, чтобы передать ей управление и дать расширению возможность вызывать методы LIRA-FEM API. Как правило, это функция с параметром "CallAfter"="AppStartup".
В примере в подразделе «Быстрый старт» мы создали кнопку, которая получила имя по умолчанию, разместилась на вкладке ленты LIRA-FEM по умолчанию и вовсе не имела пиктограммы. Всё это легко настроить с помощью соответствующих параметров раздела реестра Windows с именем — идентификатором расширения и именем вызываемой функции расширения; в нашем примере это разделы HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli и HKEY_LOCAL_MACHINE\SOFTWARE\LIRA EXTENSIONS\hli\HelloLira.
В разделе реестра с именем — идентификатором расширения — допускаются строковые параметры со следующими именами:
В разделе реестра с именем — именем функции расширения — допускаются строковые параметры со следующими именами:
Значения параметров RibbonTabImageListSmall, RibbonTabImageListLarge, RibbonImageSmall, RibbonImageLarge могут содержать путь к изображению .PNG, .BMP или .ICO для одной или нескольких кнопок. Можно указать полный путь к файлу изображения на диске либо путь к изображению, находящемуся в ресурсах нативного приложения или динамической библиотеки .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‑файлом, если нужно перенести задачу с одного компьютера на другой. Но если вы не попадаете ни в первый, ни во второй случай, то скорее всего захотите реализовать интерфейс 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(). Таким образом, и таблицы ввода исходных данных, и таблицы ввода результатов, подконтрольные расширению, можно легко включить в Книгу отчётов и сверстать в единый вместе с остальными результатами DOCX‑файл.
В подразделе «Визуализация данных расширения с помощью мозаик» мы показали, как можно программно построить произвольную мозаику, раскрасив элементы расчётной схемы в разные цвета. Построенную таким образом мозаику, изополе или эпюры можно добавить в Книгу отчётов, чтобы включить их в общий отчёт по задаче. Ни для построения мозаик, ни для включения их в Книгу отчётов не требовалось разрабатывать какие‑либо объекты, реализующие заранее определённые интерфейсы. Но у мозаик, добавленных в Книгу отчётов, есть проблема — они не обновляемые, и если при очередном пересчёте задачи результаты расчёта вашего расширения изменились, то соответствующие мозаики в Книге отчётов придётся переделывать вручную.
Однако если вы реализуете интерфейс 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 (язык C# и др.) | |||
| 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, чтобы сообщить нам.
Комментарии