Полный исходный текст на языке C++ для библиотеки (DLL) с моделью блока, вычисляющего значение выхода «y» по формуле «y=K×x+C» и хранящего настроечные параметры в значениях по умолчанию входов «K» и «C»
// Хранение настроек в значениях входов по умолчанию #include <windows.h> #include <math.h> #include <RdsDef.h> // Подготовка описаний сервисных функций #define RDS_SERV_FUNC_BODY GetInterfaceFunctions #include <RdsFunc.h> //========== Главная функция DLL ========== int WINAPI DllMain(HINSTANCE /*hinst*/, unsigned long reason, void* /*lpReserved*/) { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL { // Получение доступа к функциям RDS if(!GetInterfaceFunctions()) RDS_SERV_ERROR_MSGW // Сообщение: старая версия RDS } return 1; } //========= Конец главной функции ========= // Проверка наличия связи у входа блока BOOL CheckBlockInputConnection( RDS_BHANDLE Block, // Идентификатор блока int num, // Номер входа RDS_PVARDESCRIPTION pVarDescr) // Указатель на структуру // описания переменной { RDS_CHANDLE c; // Идентификатор связи RDS_POINTDESCRIPTION PtDescr; // Структура описания точки связи // Заполнение служебных полей структур их размерами PtDescr.servSize=sizeof(PtDescr); pVarDescr->servSize=sizeof(RDS_VARDESCRIPTION); // Получение описания переменной блока по номеру if(rdsGetBlockVar(Block,num,pVarDescr)==NULL) return FALSE; // Нет такой переменной // Перебор всех связей, подключенных к этому блоку c=NULL; for(;;) { // Найти связь, следующую за c, и заполнить структуру // описания точки соединения PtDescr c=rdsGetBlockLink(Block,c,TRUE,FALSE,&PtDescr); if(c==NULL) // Больше нет связей break; // Найдена очередная связь – сравнение имени заданной // переменной с именем переменной точки этой связи if(strcmp(PtDescr.VarName,pVarDescr->Name)==0) return TRUE; // Имена совпали – есть связь, соединенная // с переменной блока } // Все подключенные связи перебраны, а связь, подключенная // к заданной переменной так и не была найдена return FALSE; } //========================================= // Добавление поля для ввода или индикации вещественного параметра // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" BOOL AddWinEditOrDisplayDouble( RDS_HOBJECT window, // Идентификатор объекта-окна RDS_BHANDLE Block, // Блок int varnum, // Номер переменной в блоке int ctrlnum, // Идентификатор поля ввода в окне char *title) // Заголовок поля или NULL { // Структура описания переменной блока RDS_VARDESCRIPTION VarDescr; // Проверка наличия связи у переменной varnum в блоке Block // и заполнение структуры VarDescr описанием переменной BOOL conn=CheckBlockInputConnection(Block,varnum,&VarDescr); if(conn) // К переменной подключена связь { // Вспомогательные переменные char *caption; // Заголовок поля double *cur; // Указатель на данные переменной // Заголовок поля формируется из имени переменной и // текста "подключена связь" caption=rdsDynStrCat(title?title:VarDescr.Name, " (подключена связь)", FALSE); // Добавление поля для индикации текущего значения rdsFORMAddEdit(window,0,ctrlnum,RDS_FORMCTRL_DISPLAY, caption,80); // Освобождение динамически сформированной строки // заголовка поля rdsFree(caption); // Получение указателя на данные переменной cur=(double*)rdsGetBlockVarBase(Block,varnum,NULL); // Проверка – переменная должна существовать и иметь тип double if(cur!=NULL && VarDescr.Type=='D') // Занесение текущего значения переменной в поле rdsSetObjectDouble(window,ctrlnum,RDS_FORMVAL_VALUE,*cur); } else // К переменной не подключена связь { // Вспомогательная переменная для значения по умолчанию char *defval; // Получение строки со значением переменной по умолчанию // (необходимо потом освободить при помощи rdsFree) defval=rdsGetBlockVarDefValueStr(Block,varnum,NULL); // Добавление поля для ввода параметра rdsFORMAddEdit(window,0,ctrlnum,RDS_FORMCTRL_EDIT, title?title:VarDescr.Name,80); // Занесение в поле ввода значения перменной по умолчанию rdsSetObjectStr(window,ctrlnum,RDS_FORMVAL_VALUE,defval); // Освобождение динамически сформированной строки rdsFree(defval); } // Возврат: TRUE – есть связь, FALSE – нет связи return conn; } //========================================= // Функция настройки K и C для модели блока y=Kx+C // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" BOOL TestKxCSetup( RDS_BHANDLE Block, // Идентификатор блока int numK, // Номер переменной K в блоке int numC) // Номер переменной C в блоке { RDS_HOBJECT window; // Идентификатор вспомогательного объекта BOOL ok; // Пользователь нажал "OK" BOOL K_conn,C_conn; // Флаги наличия связей у K и C // Создание окна window=rdsFORMCreate(FALSE,-1,-1,"Kx+C"); // Добавление полей для ввода или индикации K и C // (в зависимости от наличия связей) K_conn=AddWinEditOrDisplayDouble(window,Block,numK,1,NULL); C_conn=AddWinEditOrDisplayDouble(window,Block,numC,2,NULL); // Открытие окна ok=rdsFORMShowModalEx(window,NULL); if(ok) { // Нажата кнопка OK – запись параметров в блок if(!K_conn) // У K нет связи { // Получение строки из поля ввода char *str=rdsGetObjectStr(window,1,RDS_FORMVAL_VALUE); // Установка значения переменной K по умолчанию rdsSetBlockVarDefValueStr(Block,numK,str); } if(!C_conn) // У С нет связи { // Получение строки из поля ввода char *str=rdsGetObjectStr(window,2,RDS_FORMVAL_VALUE); // Установка значения переменной C по умолчанию rdsSetBlockVarDefValueStr(Block,numC,str); } } // Уничтожение окна rdsDeleteObject(window); // Возвращаемое значение – истина, если нажата "OK" return ok; } //========================================= // Функция модели блока extern "C" __declspec(dllexport) int RDSCALL TestKxC(int CallMode, RDS_PBLOCKDATA BlockData, LPVOID ExtParam) { // Макроопределения для статических переменных #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define x (*((double *)(pStart+2*RDS_VSZ_S))) #define K (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D))) #define C (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D))) #define y (*((double *)(pStart+2*RDS_VSZ_S+3*RDS_VSZ_D))) switch(CallMode) { // Проверка типа переменных case RDS_BFM_VARCHECK: if(strcmp((char*)ExtParam,"{SSDDDD}")==0) return RDS_BFR_DONE; return RDS_BFR_BADVARSMSG; // Запуск расчета case RDS_BFM_STARTCALC: // Если это запуск с начала, взвести Start if(((RDS_PSTARTSTOPDATA)ExtParam)->FirstStart) Start=1; // Модель запустится в первом же такте break; // Такт расчета case RDS_BFM_MODEL: y=K*x+C; break; // Функция настройки case RDS_BFM_SETUP: if(TestKxCSetup(BlockData->Block,3,4)) { // Нажата “OK" Start=1; // Запустить модель в следующем такте return RDS_BFR_MODIFIED; } } return RDS_BFR_DONE; // Отмена макроопределений #undef y #undef C #undef K #undef x #undef Ready #undef Start #undef pStart } //=========================================