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

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

  // Программное рисование - дополнительное рисование на графике
  #include <windows.h>
  #include <stdio.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 TSimplePlotData
  { private:
      // Запомненные координаты поля графика
      int Gr_x1,Gr_x2,Gr_y1,Gr_y2;
      // Масштаб окна на момент последнего рисования
      double OldZoom;
      // Индекс последнего нарисованного отсчета
      int LastDrawnIndex;

      // Настроечные параметры графика (цвета, шаг и т.п.)
      double TimeStep;         // Шаг записи отсчетов
       Font; // Шрифт чисел на осях
       BorderColor;    // Цвет рамки вокруг блока
       FillColor;      // Цвет фона блока
       PlotBorderColor;// Цвет рамки поля графика
       PlotFillColor;  // Цвет фона поля графика
       LineColor;      // Цвет лини графика
      int LineWidth;           // Толщина линии графика

      // Ось X
      double Xmin,Xmax;        // Диапазон
      double XGridStep;        // Шаг чисел на осях
      int XNumDecimal;         // Дробная часть чисел на осях

      // Ось Y
      double Ymin,Ymax;        // Диапазон
      double YGridStep;        // Шаг чисел на осях
      int YNumDecimal;         // Дробная часть чисел на осях

      // Массивы для хранения отсчетов графика
      double *Times;           // Массив отсчетов времени
      double *Values;          // Массив значений
      int Count;               // Размер массивов
      int NextIndex;           // Индекс для записи следующего значения
      double NextTime;         // Время записи следующего значения

       Time;    // Связь с динамической переменной
                               // времени ("DynTime")
    public:
      // Функция сброса запомненного масштаба последнего рисования
      void ResetCoords(void){OldZoom=-1.0;};

      // Функция отведения массивов отсчетов
      void AllocateArrays(void);
      // Функция освобождения массивов отсчетов
      void ClearArrays(void);
      // Добавление очередной точки в массив отсчетов графика
      void AddPoint(double v);

      int Setup(void);            // Функция настройки параметров
      void SaveText(void);        // Функция сохранения параметров
      void LoadText(char *text);  // Функция загрузки параметров
      void Draw( DrawData); // Функция рисования
      void DrawFast( DrawData); // Функция быстрого рисования
// Рисование иконки при отсутствии доступа к DynTime void DrawAdditional( DrawData);
TSimplePlotData(void); // Конструктор класса ~TSimplePlotData(); // Деструктор класса }; //========================================= // Модель блока extern "C" __declspec(dllexport) int SimplePlot( int CallMode, BlockData, ExtParam) { // #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define x (*((double *)(pStart+2*RDS_VSZ_S))) // Указатель на личную область, приведенный к правильному типу TSimplePlotData *data=(TSimplePlotData*)(BlockData->BlockData); switch(CallMode) { // Инициализация блока case : BlockData->BlockData=new TSimplePlotData(); break; // Очистка данных блока case : delete data; break; // Проверка типов статических переменных case : if(strcmp((char*)ExtParam,"{SSD}")==0) return ; return ; // Функция настройки параметров case : data->ResetCoords(); // Сброс запомненных значений return data->Setup(); // Загрузка параметров в текстовом формате case : data->LoadText((char*)ExtParam); data->ResetCoords(); // Сброс запомненных значений break; // Созранение параметров в текстовом формате case : data->SaveText(); break; // Изменение размеров блока case : data->ResetCoords(); // Сброс запомненных значений break; // Рисование внешнего вида блока case : //data->Draw(()ExtParam); data->DrawFast(()ExtParam); break;
// Дополнительное рисование case : data->DrawAdditional(()ExtParam); break;
// Запуск расчета case : if((()ExtParam)->FirstStart) data->AllocateArrays(); // Первый запуск break; // Сброс расчета case : data->ClearArrays(); break; // Реакция на изменение динамической переменной case : data->AddPoint(x); break; } return ; // Отмена макроопределений для переменных #undef x #undef Ready #undef Start #undef pStart } //========================================= // Конструктор класса личной области данных графика TSimplePlotData::TSimplePlotData(void) { // Инициализация OldZoom: значение -1 приведет к принудительному // вычислению Gr_x1,Gr_x2,Gr_y1 и Gr_y2 в ближайшем вызове // функции Draw OldZoom=-1.0; // Инициализация LastDrawnIndex LastDrawnIndex=-1; // Присвоение начальных значений параметрам TimeStep=0.1; // Шаг записи BorderColor=0; // Цвет рамки вокруг блока FillColor=0xffffff; // Цвет фона блока PlotBorderColor=0; // Цвет рамки окна графика и сетки PlotFillColor=0xffffff; // Цвет окна графика LineColor=0; // Цвет линии графика LineWidth=1; // Толщина линии графика // Параметры шрифта Font.servSize=sizeof(Font); strcpy(Font.Name,"Arial"); Font.SizePriority=FALSE; Font.Height=15; Font.Color=0; Font.Bold=Font.Italic=Font.Underline=Font.StrikeOut=FALSE; Font.CharSet=; // Диапазоны осей, шаг сетки, число десятичных знаков // в числах на осях Xmin=0.0; Xmax=10.0; XGridStep=5.0; XNumDecimal=0; Ymin=-1.0; Ymax=1.0; YGridStep=0.5; YNumDecimal=1; // Обнуление указателей на массивы и их размера // (массивы еще не отведены) Times=Values=NULL; Count=NextIndex=0; NextTime=Xmin; // Подписка на динамическую переменную времени Time=( , // В родительской подсистеме "DynTime", // Имя переменной "D", // Тип переменной (double) TRUE); // Искать по иерархии } //========================================= // Деструктор класса TSimplePlotData::~TSimplePlotData() { (Time); // Прекратить подписку ClearArrays(); // Освободить массивы } //========================================= // Рисование внешнего вида блока void TSimplePlotData::Draw( DrawData) { // Вспомогательные переменные // int Gr_x1,Gr_x2,Gr_y1,Gr_y2; - эти переменные стали полями класса int x1,y1,x2,y2,textheight,w1,w2; char buf[80]; // Рамка графика (0,,1,BorderColor,); (0,,FillColor); (DrawData->Left,DrawData->Top, DrawData->Left+DrawData->Width, DrawData->Top+DrawData->Height); // Необходимо вычислить координаты поля графика относительно // верхнего левого угла блока // Установка параметров шрифта с учетом масштаба (&Font,DrawData->DoubleZoom); ("0",NULL,&textheight); if(DrawData->DoubleZoom!=OldZoom) // Масштаб изменен { // Зазор сверху – половина высоты цифры + 1 точка Gr_y1=textheight/2+1; // Зазор снизу – полная высота цифры + 1 точка Gr_y2=DrawData->Height-textheight-1; // Зазор слева – ширина самого длинного числа вертикальной // оси или половина ширины Xmin sprintf(buf," %.*lf ",YNumDecimal,Ymin); (buf,&w1,NULL); // Ширина Ymin sprintf(buf," %.*lf ",YNumDecimal,Ymax); (buf,&w2,NULL); // Ширина Ymax if(w2>w1) w1=w2; sprintf(buf," %.*lf ",XNumDecimal,Xmin); (buf,&w2,NULL); // Ширина Xmin w2/=2; if(w2>w1) w1=w2; Gr_x1=w1; // Зазор справа – половина ширины Xmax sprintf(buf," %.*lf ",XNumDecimal,Xmax); (buf,&w2,NULL); // Ширина Xmax w2/=2; Gr_x2=DrawData->Width-w2; // Запоминание нового масштаба OldZoom=DrawData->DoubleZoom; } // if(DrawData->DoubleZoom!=OldZoom) // Абсолютные (на рабочем поле) координаты поля графика x1=DrawData->Left+Gr_x1; x2=DrawData->Left+Gr_x2; y1=DrawData->Top+Gr_y1; y2=DrawData->Top+Gr_y2; if(x1>=x2 || y1>=y2) // Негде рисовать return; // Прямоугольник поля графика (0,,1,PlotBorderColor,); (0,,PlotFillColor); (x1,y1,x2,y2); // Установка пунктирного стиля линии (0,,1,PlotBorderColor,); (0,,0); // Без заливки // Горизонтальная ось с сеткой for(double x=Xmin;x<=Xmax+XGridStep*0.5;x+=XGridStep) { // ix - координата линии на рабочем поле int ix=x1+(x-Xmin)*(x2-x1)/(Xmax-Xmin); if(ix>x1 && ix<x2) // Чертим вертикальную линию { (ix,y1); (ix,y2); } // Вывод числа на оси под полем sprintf(buf,"%.*lf",XNumDecimal,x); (buf,&w1,NULL); (ix-w1/2,y2,buf); } // Вертикальная ось с сеткой for(double y=Ymin;y<=Ymax+YGridStep*0.5;y+=YGridStep) { // iy - координата линии на рабочем поле int iy=y2-(y-Ymin)*(y2-y1)/(Ymax-Ymin); if(iy>y1 && iy<y2) // Чертим горизонтальную линию { (x1,iy); (x2,iy); } // Вывод числа на оси слева от поля sprintf(buf,"%.*lf ",YNumDecimal,y); (buf,&w1,&textheight); (x1-w1-2,iy-textheight/2,buf); } // Если массивы не пустые – рисовать график if(Count) { r; // Установить область отсечения рисования по полю графика r.left=x1+1; r.top=y1+1; r.right=x2-1; r.bottom=y2-1; (&r); // Установить сплошной стиль линии, заданный для // графика цвет и толщину линии с учетом масштаба (0,, LineWidth*DrawData->DoubleZoom, LineColor,); // Строим ломанную линию по отсчетам из массивов for(int i=0;i<NextIndex;i++) { // Преобразуем вещественные отсчеты в целочисленные // координаты на рабочем поле int ix=x1+(Times[i]-Xmin)*(x2-x1)/(Xmax-Xmin), iy=y2-(Values[i]-Ymin)*(y2-y1)/(Ymax-Ymin); if(i) // Не первая точка – строим линию от предыдущей (ix,iy); else // Первая точка графика – делаем ее текущей (ix,iy); } // Запоминаем последний нарисованный отсчет LastDrawnIndex=NextIndex-1; // Отмена отсечения (NULL); } } //========================================= // Рисование изменений void TSimplePlotData::DrawFast( DrawData) { int x1,y1,x2,y2; // Если RDS требует полного рисования, или полное рисование // еще не проводилось, вызывается старая функция Draw if(DrawData->FullDraw || DrawData->DoubleZoom!=OldZoom) { Draw(DrawData); return; } // Вычисление абсолютных координат поля графика x1=DrawData->Left+Gr_x1; x2=DrawData->Left+Gr_x2; y1=DrawData->Top+Gr_y1; y2=DrawData->Top+Gr_y2; if(x1>=x2 || y1>=y2) // Негде рисовать return; // Если массивы не пустые – рисовать график, начиная // с последней уже нарисованной точки if(Count) { r; // Установить область отсечения рисования по полю графика r.left=x1+1; r.top=y1+1; r.right=x2-1; r.bottom=y2-1; (&r); // Установить сплошной стиль линии, заданный для // графика цвет и толщину линии с учетом масштаба (0,, LineWidth*DrawData->DoubleZoom, LineColor,); // Проверка допустимости LastDrawnIndex – на всякий случай if(LastDrawnIndex<0) LastDrawnIndex=0; // Строим ломанную линию по отсчетам из массивов, // начиная с LastDrawIndex for(int i=LastDrawnIndex;i<NextIndex;i++) { int ix=x1+(Times[i]-Xmin)*(x2-x1)/(Xmax-Xmin), iy=y2-(Values[i]-Ymin)*(y2-y1)/(Ymax-Ymin); if(i!=LastDrawnIndex) (ix,iy); else (ix,iy); } // Запоминаем последний нарисованный отсчет LastDrawnIndex=NextIndex-1; // Отмена отсечения (NULL); } } //=========================================
// Дополнительное рисование void TSimplePlotData::DrawAdditional( DrawData) { // Проверка доступа к переменной времени if(Time==NULL || Time->Data==NULL) // Доступа нет { int w,h; // Константа, указывающая на стандартную иконку RDS DWORD icon=; // Определяем размер иконки и выводим ее в центре блока if((icon,&w,&h)) (DrawData->Left+(DrawData->Width-w)/2, DrawData->Top+(DrawData->Height-h)/2, icon); } } //=========================================
// Отведение памяти под массивы void TSimplePlotData::AllocateArrays(void) { // Сначала нужно очистить массивы, если они были отведены ранее ClearArrays(); // При нулевом или отрицательном шаге записи отсчетов // работа блока невозможна if(TimeStep<=0.0) return; // Вычисление требуемого числа отсчетов по диапазону оси // времени и шагу записи Count=(Xmax-Xmin)/TimeStep+1; // Число отсчетов должно быть положительным if(Count<=0) {Count=0; return; } // Отведение памяти – по Count чисел double Times=new double[Count]; Values=new double[Count]; // Первый свободный индкс массива - 0 NextIndex=0; // Момент записи отсчета – начало диапазона оси времени NextTime=Xmin; } //========================================= // Освобождение массивов void TSimplePlotData::ClearArrays(void) { if(Count) // Массивы были отведены { delete[] Times; delete[] Values; } // Обнуление указателей и Count Times=Values=NULL; Count=NextIndex=0; } //========================================= // Добавление отсчета в массив void TSimplePlotData::AddPoint(double v) { double t; if(NextIndex>=Count) // Весь массив заполнен return; if(Time==NULL || Time->Data==NULL) // Нет доступа к “DynTime" return; // Получение значения времени из “DynTime" t=*((double*)Time->Data); if(t<NextTime) // Еще не пришло время писать отсчет return; // Достигнуто время записи Values[NextIndex]=v; Times[NextIndex]=t; NextIndex++; // Следующий отсчет – в следующий индекс NextTime+=TimeStep; // Время записи следующего отсчета } //========================================= // Сохранение параметров в текстовом виде void TSimplePlotData::SaveText(void) { ini; char *str; // Создание объекта для работы с текстом ini=(TRUE); // Создание в тексте секции "[General]" (ini,,0,"General"); // Запись в секцию различных параметров (ini,"TimeStep",TimeStep); (ini,"Xmin",Xmin); (ini,"Xmax",Xmax); (ini,"XGridStep",XGridStep); (ini,"XNumDecimal",XNumDecimal); (ini,"Ymin",Ymin); (ini,"Ymax",Ymax); (ini,"YGridStep",YGridStep); (ini,"YNumDecimal",YNumDecimal); // Создание в тексте секции "[Visuals]" (ini,,0,"Visuals"); // Запись в секцию различных параметров (ini,"BorderColor",(int)BorderColor); (ini,"FillColor",(int)FillColor); (ini,"PlotBorderColor",(int)PlotBorderColor); (ini,"PlotFillColor",(int)PlotFillColor); (ini,"LineColor",(int)LineColor); (ini,"LineWidth",LineWidth); // Преобразование описания шрифта в строку для сохранения str=(&Font,NULL); // Запись строки с описанием шрифта (ini,"Font",str); (str); // Освобождение памяти, занятой строкой // Запись сформированного текста в файл схемы или буфер обмена (ini,); // Уничтожение вспомогательного объекта (ini); } //========================================= // Загрузка параметров в текстовом виде из строки text void TSimplePlotData::LoadText(char *text) { ini; char *str; // Создание объекта для работы с текстом ini=(TRUE); // Загрузка текста в объект (ini,,0,text); // Если в тексте есть секция "General", загрузить из нее данные if((ini,"General")) { TimeStep=(ini,"TimeStep",TimeStep); Xmin=(ini,"Xmin",Xmin); Xmax=(ini,"Xmax",Xmax); XGridStep=(ini,"XGridStep",XGridStep); XNumDecimal=(ini,"XNumDecimal",XNumDecimal); Ymin=(ini,"Ymin",Ymin); Ymax=(ini,"Ymax",Ymax); YGridStep=(ini,"YGridStep",YGridStep); YNumDecimal=(ini,"YNumDecimal",YNumDecimal); } // Если в тексте есть секция "Visuals", загрузить из нее данные if((ini,"Visuals")) { BorderColor=()(ini,"BorderColor", (int)BorderColor); FillColor=()(ini,"FillColor", (int)FillColor); PlotBorderColor=()(ini, "PlotBorderColor",(int)PlotBorderColor); PlotFillColor=()(ini,"PlotFillColor", (int)PlotFillColor); LineColor=()(ini,"LineColor", (int)LineColor); LineWidth=()(ini,"LineWidth",LineWidth); str=(ini,"Font","",NULL); if(str) (str,NULL,&Font); } // Уничтожение вспомогательного объекта (ini); } //========================================= // Функция настройки параметров блока // // // int TSimplePlotData::Setup(void) { window; ok; char *str; // Создание окна window=(TRUE,-1,-1,"Простой график"); // Вкладка "Оси" (window,1,"Оси"); (window,1,100, | ,"Шаг записи",50); (window,100,,TimeStep); // Текстовая метка без возможности ввода (window,1,1,,"Ось X:",0); // Диапазон (два поля ввода в одной строке) (window,1,2,,"Диапазон",90); (window,2,,Xmin); (window,2,,Xmax); (window,1,3,,"Шаг сетки",50); (window,3,,XGridStep); // Поле ввода со стрелками увеличения/уменьшения (window,1,4, | , "Дробная часть чисел",50); (window,4,,XNumDecimal); (window,4,,0); (window,4,,5); (window,4,,1); // Текстовая метка без возможности ввода (window,1,5,,"Ось Y:",0); (window,1,6,,"Диапазон",90); (window,6,,Ymin); (window,6,,Ymax); (window,1,7,,"Шаг сетки",50); (window,7,,YGridStep); (window,1,8,, "Дробная часть чисел",50); (window,8,,YNumDecimal); (window,8,,0); (window,8,,5); (window,8,,1); // Вкладка "Внешний вид" (window,2,"Внешний вид"); (window,2,9,,"Цвет рамки блока",50); (window,9,,(int)BorderColor); (window,2,10, | ,"Цвет фона блока",50); (window,10,,(int)FillColor); (window,2,11,,"Цвет рамки графика и сетки",50); (window,11,,(int)PlotBorderColor); (window,2,12,,"Цвет фона графика",50); (window,12,,(int)PlotFillColor); (window,2,13,,"Цвет линии графика",50); (window,13,,(int)LineColor); (window,2,14, | , "Толщина линии графика",50); (window,14,,LineWidth); (window,14,,0); (window,14,,5); (window,14,,1); // Кнопка открытия диалога выбора шрифта (window,2,15,,"Шрифт чисел",0); // Преобразование шрифта в строку и занесение в поле ввода str=(&Font,NULL); (window,15,,str); (str); // Открытие окна ok=(window,NULL); if(ok) { // Нажата кнопка OK - запись параметров обратно в блок Xmin=(window,2,); Xmax=(window,2,); XGridStep=(window,3,); XNumDecimal=(window,4,); TimeStep=(window,100,); Ymin=(window,6,); Ymax=(window,6,); YGridStep=(window,7,); YNumDecimal=(window,8,); BorderColor=()(window,9,); FillColor=()(window,10,); PlotBorderColor=()(window,11,); PlotFillColor=()(window,12,); LineColor=()(window,13,); LineWidth=(window,14,); // Получение параметров шрифта из строки str=(window,15,); (str,NULL,&Font); } // Уничтожение окна (window); // Возвращаемое значение return ok?:; } //=========================================


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