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

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

  // Сохранение параметров в текстовом формате
  #include <windows.h>
  #include <math.h>
  #include <stdio.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,RDS_GFS_SOLID,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 :
          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 } //=========================================
// Функция сохранения параметров void TTestGenData::SaveText(void) { char buffer[100]; // Буфер для формирования текста // Формирование текста в буфере при помощи функции sprintf sprintf(buffer, "type %d period %lf impulse %lf", Type,Period,Impulse); // Передача сформированного текста в RDS (buffer,FALSE); } //=========================================
/* // Функция сохранения параметров – вариант с условием void TTestGenData::SaveText(void) { char buffer[100]; // Буфер для формирования текста // Формирование текста для Type и Period sprintf(buffer, "type %d period %lf", Type,Period); // Передача сформированного текста в RDS (buffer,FALSE); // Запись Impulse если Type равно 2 if(Type==2) { // Формирование текста sprintf(buffer,"impulse %lf",Impulse); // Передача текста в RDS (buffer,FALSE); } } //========================================= */
// Функция загрузки параметров void TTestGenData::LoadText(char *text) { char *word,*ptr,c; // Установка указателя ptr на начало переданного текста ptr=text; // Цикл по словам в тексте for(;;) { // Получить из текста очередное слово word=(ptr,&ptr,&c,TRUE); if(c==0) // Текст закончился – выход из цикла break; if(c=='\n') // Перевод строки – пропускаем и продолжаем continue; if(strcmp(word,"type")==0) // Тип сигнала { // Следующее слово – целое число word=(ptr,&ptr,NULL,FALSE); Type=atoi(word); } else if(strcmp(word,"period")==0) // Период { // Следующее слово - число double word=(ptr,&ptr,NULL,FALSE); Period=atof(word); } else if(strcmp(word,"impulse")==0) // Длительность импульса { // Следующее слово - число double word=(ptr,&ptr,NULL,FALSE); Impulse=atof(word); } else // Неопознанное ключевое слово break; // Ошибка – прекращаем обработку } // Конец цикла for(;;) } //=========================================


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