Навигация:
<< >> Оглавление Указатель
Текст С++

Полный исходный текст на языке C++ для библиотеки (DLL) с моделью блока-генератора синусоиды, косинусоиды или прямоугольных импульсов, сохраняющего свои параметры в текстовом формате при помощи вспомогательного объекта RDS. Изменения относительно примера из §2.8.3 выделены цветом.

  // Сохранение параметров в текстовом формате с использованием вспомогательного объекта
  #include <windows.h>
  #include <math.h>
  #include <RdsDef.h>
  // Подготовка описаний сервисных функций
  
  #include <RdsFunc.h>

  //==========  ==========
  int WINAPI ( /*hinst*/,
                           unsigned long reason,
                           void* /*lpReserved*/)
  { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL
      { // Получение доступа к функциям RDS
        if(!GetInterfaceFunctions())
           // Сообщение: старая версия RDS
      }
    return 1;
  }
  //========= Конец главной функции =========

  //=========================================
  //=             Генератор                 =
  //=========================================

  //====== Класс личной области данных ======
  class TTestGenData
  { public:
      int Type;        // Тип (0-sin,1-cos,2-прямоугольные)
      double Period;   // Период
      double Impulse;  // Длительность импульса

       Time; // Связь с динамической
                            // переменной времени

      int Setup(void);      // Функция настройки
      void SaveText(void);  // Сохранение параметров
      void LoadText(char *text);// Загрузка параметров
      TTestGenData(void)    // Конструктор класса
        { Type=0; Period=1.0; Impulse=0.5;
          // Подписка на динамическую переменную времени
          Time=(,
                                        "DynTime",
                                        "D",
                                        TRUE);
        };
      ~TTestGenData(void) // Деструктор класса
        { // Прекращение подписки
          (Time);
        };
  };

  //==== Прототип функции обратного вызова окна настроек ====
  void  TestGenDataCheckFunc2( win,
                                      data);

  //====== Функция редактирования параметров ======
  // 
  // 
  // 
  int TTestGenData::Setup(void)
  {  window; // Идентификатор вспомогательного объекта
     ok;            // Пользователь нажал "OK"
    // Создание окна
    window=(FALSE,-1,-1,"Простой генератор");
    // Добавление полей ввода
    (window,0,1,,
                   "Вид:",210);
    (window,0,2,,
                   "Период:",80);
    (window,0,3,,
                   "Длительность:",80);
    // Установка списка вариантов
    (window,1,,
                    "Синус\nКосинус\nПрямоугольные импульсы");
    // Занесение исходных значений в поля ввода
    (window,1,,Type);
    (window,2,,Period);
    (window,3,,Impulse);
    // Включение дополнительной панели слева от полей ввода
    (window,1,-1);
    // Добавление области для рисования графика
    (window,1,4,,NULL,100);
    // Автоматическое вычисление высоты этой области
    (window,4,,-1);
    // Открытие окна с другой функцией обратного вызова
    ok=(window,TestGenDataCheckFunc2);

    if(ok)
      { // Нажата кнопка OK - запись параметров обратно в блок
        Type=(window,1,);
        Period=(window,2,);
        Impulse=(window,3,);
      }
    // Уничтожение окна
    (window);
    // Возвращаемое значение
    return ok?:;
  }

  //====== Функция обратного вызова для окна настроек ======
  void  TestGenDataCheckFunc2( win,
                                      data)
  { // Считать номер пункта выпадающего списка
    int type=(win,1,);
    // Вспомогательные переменные для рисования графика
    int y0,y_ampl,x0,x1;
    double pix_period;

    switch(data->Event)
      { // Изменение поля ввода
        case :
          // Запретить ввод длительность импульса для sin и cos
          (win,3,,type==2);
          // Перерисовать график
          (win,);
          break;

        // Рисование
        case :
          // Заливка фона белым цветом
          (0,,0xffffff);
          (data->Left,
                        data->Top,
                        data->Left+data->Width,
                        data->Top+data->Height);
          // Координаты рисования
          x0=data->Left+10;               // Начало графика
          x1=data->Left+data->Width-10;// Конец графика
          y0=data->Top+data->Height/2; // Центр по вертикали
          y_ampl=(data->Height-20)/2;     // Амплитуда
          pix_period=0.5*(x1-x0);            // Период на рисунке
          // Координатные оси
          (0,,1,0,);
          (data->Left+5,y0);
          (data->Left+data->Width-5,y0);
          (x0,data->Top+5);
          (x0,data->Top+data->Height-5);
          // График
          (,0,3,0,0);
          if(type==2) // Прямоугольные импульсы
            { double period,impulse,pix_impulse;
              // Чтение введенных пользователем значений
              period=(win,2,);
              impulse=(win,3,);
              if(period==0.0) // Нельзя вычислить частоту
                return;
              // Длительность импульса на рисунке
              pix_impulse=impulse*pix_period/period;
              // Первый период
              (x0,y0+y_ampl);
              (x0,y0-y_ampl);
              (x0+pix_impulse,y0-y_ampl);
              (x0+pix_impulse,y0+y_ampl);
              (x0+pix_period,y0+y_ampl);
              // Второй период
              (x0+pix_period,y0-y_ampl);
              (x0+pix_period+pix_impulse,y0-y_ampl);
              (x0+pix_period+pix_impulse,y0+y_ampl);
              (x1,y0+y_ampl);
            }
          else // Синус или косинус
            { double t,y;
              // Цикл по горизонтали с шагом в 3 точки
              for(int x=x0;x<=x1;x+=3)
                { t=2*M_PI*(x-x0)/pix_period;
                  y=y_ampl*((type==0)?sin(t):cos(t));
                  if(x==x0) // Первая точка – установить позицию
                    (x,y0-y);
                  else // Рисовать линию от предыдущей точки
                    (x,y0-y);
                } // for(int x=x0...)
            }
          break;
      } // switch
  }
  //=========================================

  //============= Модель блока ==============
  extern "C" __declspec(dllexport)
    int  TestGen(int CallMode,
                         BlockData,
                         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 :
          data=(TTestGenData*)(BlockData->BlockData);
          delete data;
          break;

        // Проверка типа переменных
        case :
          if(strcmp((char*)ExtParam,"{SSD}")==0)
            return ;
          return ;

        // Запись параметров в текстовом формате
        case :
          data=(TTestGenData*)(BlockData->BlockData);
          data->SaveText();
          break;

        // Загрузка параметров в текстовом формате
        case :
          data=(TTestGenData*)(BlockData->BlockData);
          data->LoadText((char*)ExtParam);
          break;

        // Функция настройки
        case :
          data=(TTestGenData*)(BlockData->BlockData);
          return data->Setup();

        // Изменение динамической переменной или запуск расчета
        case :
        case :
          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 ;
  // Отмена макроопределений
  #undef y
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================

// Глобальный массив ключевых слов // Индексы 0 1 2 const char *TestGen_Keywords[]={"type","period","impulse",NULL}; // define-константы для индексов #define TESTGEN_KW_TYPE 0 #define TESTGEN_KW_PERIOD 1 #define TESTGEN_KW_IMPULSE 2 //========================================= // Функция сохранения параметров void TTestGenData::SaveText(void) { // Запись "type" и целого значения (TestGen_Keywords[TESTGEN_KW_TYPE],Type); // Запись "period" и вещественного значения (TestGen_Keywords[TESTGEN_KW_PERIOD], Period); // Запись "impulse" и вещественного значения if(Type==2) (TestGen_Keywords[TESTGEN_KW_IMPULSE], Impulse); } //========================================= // Функция загрузки параметров void TTestGenData::LoadText(char *text) { Parser; // Вспомогательный объект work=TRUE; // Флаг цикла // Создание объекта для разбора текста Parser=(TRUE); // Передача объекту массива ключевых слов (Parser,TestGen_Keywords,-1,0); // Передача объекту разбираемого текста (Parser,,0,text); // Цикл до тех пор, пока в тексте не кончатся слова while(work) { int id; // Уникальный идентификатор слова // Извлечь из текста и опознать слово id=(Parser,NULL,NULL,NULL,TRUE); // Действия в зависимости от слова switch(id) { // Нет слова – конец текста case : work=FALSE; // Выйти из цикла break; // Перевод строки – пропускаем case : break; // Слово "type" case TESTGEN_KW_TYPE: // Извлекаем следующее слово и переводим в целое Type=(Parser,,TRUE); break; // Слово "period" case TESTGEN_KW_PERIOD: // Извлекаем следующее слово и переводим в double Period=(Parser,,TRUE); break; // Слово "impulse" case TESTGEN_KW_IMPULSE: // Извлекаем следующее слово и переводим в double Impulse=(Parser,,TRUE); break; default: // Слово не опознано – ошибка work=FALSE; // Выйти из цикла } // Конец switch(...) } // Конец while(work) // Удаление вспомогательного объекта (Parser); } //=========================================


<< >> Оглавление Указатель