Текущий раздел:

Описания RDS

Руководство программиста

Глава 2. Создание моделей блоков

§2.7. Настройка параметров блока

§2.7.2. Использование объектов-окон RDS

Полный исходный текст на языке 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
      }
      //=========================================