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

Описания RDS

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

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

§2.9. Использование таймеров

§2.9.4. Несколько таймеров в одной модели

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

      // Мигающий и вращающийся блок
      #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;
      }
      //========= Конец главной функции =========

      //=== Структура личной области данных =====
      struct TRotateFlashData
      { RDS_TIMERID FlashTimer; // Таймер мигания
        RDS_TIMERID RotTimer;   // Таймер вращения
      };
      //============= Модель блока ==============
      extern "C" __declspec(dllexport) int RDSCALL RotateFlash(
              int CallMode,
              RDS_PBLOCKDATA BlockData,
              LPVOID ExtParam)
      {
      // Макроопределения для статических переменных
      #define pStart ((char *)(BlockData->VarTreeData))
      #define Start (*((char *)(pStart)))
      #define Ready (*((char *)(pStart+RDS_VSZ_S)))
      #define Flash (*((char *)(pStart+2*RDS_VSZ_S)))
      #define Rotate (*((char *)(pStart+2*RDS_VSZ_S+RDS_VSZ_L)))
      #define State (*((char *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_L)))
      #define Angle (*((double *)(pStart+2*RDS_VSZ_S+3*RDS_VSZ_L)))
        // Вспомогательная переменная – указатель на личную область
        TRotateFlashData *data=(TRotateFlashData*)(BlockData->BlockData);
        // Структура для получения параметров таймера
        RDS_TIMERDESCRIPTION descr;

        switch(CallMode)
          { // Инициализация блока
            case RDS_BFM_INIT:
              // Отведение памяти под личную область
              BlockData->BlockData=data=new TRotateFlashData;
              // Создание двух одинаковых таймеров
              data->FlashTimer=rdsSetBlockTimer(NULL,0,
                RDS_TIMERM_LOOP|RDS_TIMERS_TIMER,FALSE);
              data->RotTimer=rdsSetBlockTimer(NULL,0,
                RDS_TIMERM_LOOP|RDS_TIMERS_TIMER,FALSE);
              break;

            // Очистка данных блока
            case RDS_BFM_CLEANUP:
              // Уничтожение таймеров
              rdsDeleteBlockTimer(data->FlashTimer);
              rdsDeleteBlockTimer(data->RotTimer);
              // Освобождение памяти, занятой под личную область
              delete data;
              break;

            // Проверка типа статических переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSLLLD}"))
                return RDS_BFR_BADVARSMSG;
              return RDS_BFR_DONE;

            // Такт расчета
            case RDS_BFM_MODEL:
              // Подготовка структуры descr к чтению данных таймера
              descr.servSize=sizeof(descr);
              // Управление миганием
              rdsGetBlockTimerDescr(data->FlashTimer,&descr);
              if(Flash) // Включить мигание
                { if(!descr.On) // Таймер остановлен
                    { // Запускаем таймер и “зажигаем" индикатор
                      rdsRestartBlockTimer(data->FlashTimer,1000);
                      State=1;
                    }
                }
              else // Выключить мигание
                { if(descr.On) // Таймер работает
                    { // Останавливаем и “гасим" индикатор
                      rdsStopBlockTimer(data->FlashTimer);
                      State=0;
                    }
                }
              // Управление вращением
              rdsGetBlockTimerDescr(data->RotTimer,&descr);
              if(Rotate) // Включить врашение
                { if(!descr.On) // Таймер остановлен – запускаем
                    rdsRestartBlockTimer(data->RotTimer,100);
                }
              else // Выключить вращение
                { if(descr.On) // Таймер работает – останавливаем
                    rdsStopBlockTimer(data->RotTimer);
                }
              break;

            // Срабатывание таймера
            case RDS_BFM_TIMER:
              // Сравниваем с имеющимися таймерами
              if(ExtParam==((LPVOID)data->FlashTimer))
                // Это – таймер мигания
                State=!State;
              else // Если не таймер мигания, значит, вращения
                Angle=fmod(Angle+0.4,2*M_PI);
              break;
          }
        return RDS_BFR_DONE;

      // Отмена макроопределений для переменных
      #undef Angle
      #undef State
      #undef Rotate
      #undef Flash
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=================================================