Полный исходный текст на языке C++ для библиотеки (DLL) с моделями блоков, открывающих модальные окна для настройки параметров с помощью вспомогательных объектов RDS. Библиотека содержит две модели:
- Test1 – абстрактная модель с параметрами в личной области данных (изменения, внесенные в предыдущую версию этой модели, выделены цветом);
- TestGen – блок-генератор синусоиды, косинусоиды или прямоугольных импульсов, у которого разрешенность одного из полей окна настройки зависит от значения в другом поле.
// Функция настройки через вспомогательные объекты RDS #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; } //========= Конец главной функции ========= //========================================= //= Пример блока с личной областью данных = //========================================= //====== Класс личной области данных ====== class TTest1Data { public: int IParam; // Целый параметр double DParam; // Вещественный параметр int Setup(void); // Функция настройки параметров TTest1Data(void) // Конструктор класса { IParam=0; DParam=0.0; rdsMessageBoxW(L"Область создана",L"TTest1Data",MB_OK); }; ~TTest1Data() // Деструктор класса { rdsMessageBoxW(L"Область удалена",L"TTest1Data",MB_OK);}; }; //========================================= //============= Модель блока ============== extern "C" __declspec(dllexport) int RDSCALL Test1(int CallMode, // Режим вызова (событие в RDS) RDS_PBLOCKDATA BlockData, // Структура данных блока LPVOID /*ExtParam*/) // Доп.параметр (здесь не используется) { TTest1Data *data; switch(CallMode) { case RDS_BFM_INIT: // Инициализация BlockData->BlockData=new TTest1Data(); break; case RDS_BFM_CLEANUP: // Очистка data=(TTest1Data*)(BlockData->BlockData); delete data; break; case RDS_BFM_SETUP: // Функция настройки data=(TTest1Data*)(BlockData->BlockData); return data->Setup(); } return RDS_BFR_DONE; } //========================================= // Функция настройки параметров // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" int TTest1Data::Setup(void) { RDS_HOBJECT window; // Идентификатор вспомогательного объекта BOOL ok; // Пользователь нажал "OK" // Создание окна window=rdsFORMCreate(FALSE,-1,-1,"Ввод параметров"); // Добавление полей ввода rdsFORMAddEdit(window,0,1,RDS_FORMCTRL_EDIT, "Целый параметр:",80); rdsFORMAddEdit(window,0,2,RDS_FORMCTRL_EDIT, "Вещественный параметр:",80); // Занесение исходных значений в поля ввода rdsSetObjectInt(window,1,RDS_FORMVAL_VALUE,IParam); rdsSetObjectDouble(window,2,RDS_FORMVAL_VALUE,DParam); // Открытие окна ok=rdsFORMShowModalEx(window,NULL); if(ok) { // Нажата кнопка OK - запись параметров обратно в блок IParam=rdsGetObjectInt(window,1,RDS_FORMVAL_VALUE); DParam=rdsGetObjectDouble(window,2,RDS_FORMVAL_VALUE); } // Уничтожение окна rdsDeleteObject(window); // Возвращаемое значение return ok?RDS_BFR_MODIFIED:RDS_BFR_DONE; } //========================================= //========================================= //= Генератор = //========================================= //====== Класс личной области данных ====== class TTestGenData { public: int Type; // Тип (0-sin,1-cos,2-прямоугольные) double Period; // Период double Impulse; // Длительность импульса RDS_PDYNVARLINK Time; // Связь с динамической // переменной времени int Setup(void); // Функция настройки TTestGenData(void) // Конструктор класса { Type=0; Period=1.0; Impulse=0.5; // Подписка на динамическую переменную времени Time=rdsSubscribeToDynamicVar(RDS_DVPARENT, "DynTime", "D", TRUE); }; ~TTestGenData(void) // Деструктор класса { // Прекращение подписки rdsUnsubscribeFromDynamicVar(Time); }; }; //========================================= //==== Прототип функции обратного вызова окна настроек ==== void RDSCALL TestGenDataCheckFunc(RDS_HOBJECT); //====== Функция редактирования параметров ====== // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" int TTestGenData::Setup(void) { RDS_HOBJECT window; // Идентификатор вспомогательного объекта BOOL ok; // Пользователь нажал "OK" // Создание окна window=rdsFORMCreate(FALSE,-1,-1,"Простой генератор"); // Добавление полей ввода rdsFORMAddEdit(window,0,1,RDS_FORMCTRL_COMBOLIST, "Вид:",210); rdsFORMAddEdit(window,0,2,RDS_FORMCTRL_EDIT, "Период:",80); rdsFORMAddEdit(window,0,3,RDS_FORMCTRL_EDIT, "Длительность:",80); // Установка списка вариантов rdsSetObjectStr(window,1,RDS_FORMVAL_LIST, "Синус\nКосинус\nПрямоугольные импульсы"); // Занесение исходных значений в поля ввода rdsSetObjectInt(window,1,RDS_FORMVAL_VALUE,Type); rdsSetObjectDouble(window,2,RDS_FORMVAL_VALUE,Period); rdsSetObjectDouble(window,3,RDS_FORMVAL_VALUE,Impulse); // Открытие окна с указанием функции обратного вызова ok=rdsFORMShowModalEx(window,TestGenDataCheckFunc); if(ok) { // Нажата кнопка OK - запись параметров обратно в блок Type=rdsGetObjectInt(window,1,RDS_FORMVAL_VALUE); Period=rdsGetObjectDouble(window,2,RDS_FORMVAL_VALUE); Impulse=rdsGetObjectDouble(window,3,RDS_FORMVAL_VALUE); } // Уничтожение окна rdsDeleteObject(window); // Возвращаемое значение return ok?RDS_BFR_MODIFIED:RDS_BFR_DONE; } //====== Функция обратного вызова для окна настроек ====== void RDSCALL TestGenDataCheckFunc(RDS_HOBJECT win) { // Считать номер пункта выпадающего списка int type=rdsGetObjectInt(win,1,RDS_FORMVAL_VALUE); // Разрешить ввод длительности, если выбран пункт 2 rdsSetObjectInt(win,3,RDS_FORMVAL_ENABLED,type==2); } //========================================= //============= Модель блока ============== extern "C" __declspec(dllexport) int RDSCALL TestGen(int CallMode, RDS_PBLOCKDATA BlockData, LPVOID ExtParam) { // Макроопределения для статических переменных #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define y (*((double *)(pStart+2*RDS_VSZ_S))) // Вспомогательная переменная – указатель на личную область // данных блока, приведенный к правильному типу TTestGenData *data; switch(CallMode) { // Инициализация case RDS_BFM_INIT: BlockData->BlockData=new TTestGenData(); break; // Очистка case RDS_BFM_CLEANUP: data=(TTestGenData*)(BlockData->BlockData); delete data; break; // Проверка типа переменных case RDS_BFM_VARCHECK: if(strcmp((char*)ExtParam,"{SSD}")==0) return RDS_BFR_DONE; return RDS_BFR_BADVARSMSG; // Функция настройки case RDS_BFM_SETUP: data=(TTestGenData*)(BlockData->BlockData); return data->Setup(); // Изменение динамической переменной или запуск расчета case RDS_BFM_STARTCALC: case RDS_BFM_DYNVARCHANGE: data=(TTestGenData*)(BlockData->BlockData); if(data->Period==0.0) // Нельзя вычислить частоту return 0; // Проверка наличия переменной “DynTime" if(data->Time!=NULL && data->Time->Data!=NULL) { // Динамическая переменная найдена – чтение значения double t=*((double*)data->Time->Data); switch(data->Type) { case 0: // Синус y=sin(2*M_PI*t/data->Period); break; case 1: // Косинус y=cos(2*M_PI*t/data->Period); break; case 2: // Прямоугольные импульсы t=fmod(t,data->Period); y=(t>data->Impulse)?-1.0:1.0; break; } // Взвести Ready для передачи выхода по связям Ready=1; } break; } return RDS_BFR_DONE; // Отмена макроопределений #undef y #undef Ready #undef Start #undef pStart } //=========================================