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

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

  // Рисование в окне настроек
  #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);      // Функция настройки
      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; // Идентификатор вспомогательного объекта
    BOOL 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+1)))
  #define y      (*((double *)(pStart+2)))
    // Вспомогательная переменная – указатель на личную область
    // данных блока, приведенный к правильному типу
    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);
          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
  }
  //=========================================


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