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

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

Первая библиотека содержит модель, создающую и обслуживающую пустую панель (во второй библиотеке будет добавлено формирование на этой панели трехмерного изображения с помощью OpenGL).

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

  // Глобальная переменная для значения ошибки
  double ;

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

      }
    return 1;
  }
  //========= Конец главной функции =========


  //=================================================
  // Личная область данных блока
  //=================================================
  class TOpenGLInstr
  { private:
       RefreshTimer; // Таймер обновления

    public:
       Panel;        // Объект-панель

      // Сохранение параметров блока
      void SaveText(void);
      // Загрузка параметров блока
      void LoadText(char *text);

      // Создание таймера обновления
      void CreateRefreshTimer( parent);

      // Конструктор класса
      TOpenGLInstr(void);
      // Деструктор класса
      ~TOpenGLInstr();
  };
  //=================================================

  // Конструктор класса личной области данных
  // 
  // 
  // 
  TOpenGLInstr::TOpenGLInstr(void)
  { // Создаем панель в окне подсистемы
    Panel=(0,0,0,300,300,
                       ||
                       ||
                       ||
                       ,
                       "Прибор");
    // Инициализируем идентификатор еще не созданного таймера
    RefreshTimer=NULL;
  }
  //=================================================

  // Деструктор класса личной области данных
  TOpenGLInstr::~TOpenGLInstr()
  { // Удаление панели
    if(Panel)
      (Panel);
    // Удаление таймера
    if(RefreshTimer)
      (RefreshTimer);
  }
  //=================================================

  // Создание таймера обновления панели
  void TOpenGLInstr::CreateRefreshTimer(RDS_BHANDLE parent)
  { // Структура для получения переметров окна подсистемы
     WinParams;
    // Определение интервала обновления окна подсистемы
    WinParams.servSize=sizeof();
    (parent,&WinParams);
    // Интервал - в WinParams.RefreshDelay

    // Создание таймера
    RefreshTimer=(RefreshTimer, // Идентификатор
                   WinParams.RefreshDelay,      // Интервал
                    |  |
                   ,          // Режим и флаги
                   TRUE);                       // Запустить таймер
  }
  //=================================================

  // Функция сохранения параметров блока
  void TOpenGLInstr::SaveText(void)
  {  ini; // Идентификатор вспомогательного объекта

    // При сохранении блока в отдельный файл на диске параметры
    // панели записывать не нужно
    if(()==)
      return;

    // Создание вспомогательного объекта для работы с данными
    ini=(TRUE);

    // Параметры записываются в секцию "[Window]"
    (ini,,0,"Window");

    // Получение параметров панели и запись их в объект
    (ini,"Left",(Panel,,0));
    (ini,"Top",(Panel,,0));
    (ini,"Width",(Panel,,0));
    (ini,"Height",(Panel,,0));
    (ini,"Visible",(Panel,,0));

    // Сохранение получившегося текста в файл, в который в данный
    // момент идет запись
    (ini,);

    // Удаление вспомогательного объекта
    (ini);
  }
  //=================================================

  // Функция загрузки параметров блока
  void TOpenGLInstr::LoadText(char *text)
  {  ini; // Идентификатор вспомогательного объекта

    // Создание вспомогательного объекта для работы с данными
    ini=(TRUE);

    // Запись в объект полученного от RDS текста с параметрами блока
    (ini,,0,text);

    // Установка "[Window]" в качестве текущей секции и чтение
    // из нее пяти целых параметров
    if(rdsINIOpenSection(ini,"Window"))
      { (Panel,,0,
                        (ini,"Left",0));
        (Panel,,0,
                        (ini,"Top",0));
        (Panel,,0,
                        (ini,"Width",0));
        (Panel,,0,
                        (ini,"Height",0));
        (Panel,,0,
                        (ini,"Visible",0));
      }
    // Удаление вспомогательного объекта
    (ini);
  }
  //=================================================

  // Модель блока с панелью
  extern "C" __declspec(dllexport) int  OpenGLInstr(
        int CallMode,
         BlockData,
         ExtParam)
  { // Указатель на личную область, приведенный к нужному типу
    TOpenGLInstr *data=(TOpenGLInstr*)(BlockData->BlockData);
    // Вспомогательная – указатель на структуру параметров при
    // действиях с панелью (будет использована в реакциях)
     param;

    switch(CallMode)
      { // Инициализация блока
        case :
          // Создание личной области данных
          // (при этом в конструкторе будет создана панель)
          BlockData->BlockData=data=new TOpenGLInstr();
          break;

        // Очистка данных блока
        case :
          // В деструкторе класса панель будет уничтожена
          delete data;
          break;

        // Запуск расчета
        case :
          // Создание таймера обновления
          data->CreateRefreshTimer(BlockData->Parent);
          break;

        // Вызов функции настройки или двойной щелчок
        // левой кнопки мыши
        case :
        case :
          // Показать панель
          (data->Panel,,0,1);
          break;

        // Сохранение параметров блока
        case :
          data->SaveText();
          break;

        // Загрузка параметров блока
        case :
          data->LoadText((char*)ExtParam);
          break;

        // Действия с панелью
        case :
          // Приведение указателя на структуру, переданного в
          // ExtParam, к нужному типу
          param=()ExtParam;
          // Разные действия в зависимости от операции с панелью
          switch(param->Operation)
            { // Создание оконного объекта для панели
              case :
                // Здесь будет инициализация рисования на панели
                break;
              // Уничтожение оконного объекта панели
              case :
                // Здесь будет очистка инициализированного
                break;
              // Размер панели изменен
              case :
                // Здесь будет реакция на изменение размера
                // и перерисовка панели
                break;
              // Необходимо перерисовать изображение
              case :
                // Здесь будет перерисовка панели
                break;
            }
          break;

       // Необходимо обновить окна блока (вызывается таймером)
       case :
          // Здесь будет перерисовка панели
          break;
      }
    return ;
  }
  //=================================================

Эта же библиотека с добавленными функциями формирования трехмерного изображения (добавки выделены цветом).

  // Панели блоков в окне подсистемы - OpenGL
  #include <windows.h>
#include <math.h> #include <gl/gl.h> #include <gl/glu.h>
#include <RdsDef.h> // Подготовка описаний сервисных функций #include <RdsFunc.h> // Глобальная переменная для значения ошибки double ; //========== ========== int WINAPI ( /*hinst*/, unsigned long reason, void* /*lpReserved*/) { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL { // Получение доступа к функциям RDS if(!GetInterfaceFunctions()) // Сообщение: старая версия RDS else (&); } return 1; } //========= Конец главной функции ========= //================================================= // Личная область данных блока //================================================= class TOpenGLInstr { private:
HGLRC Hrc; // Контекст OpenGL
RefreshTimer; // Таймер обновления public: Panel; // Объект-панель
// Настройка вывода изображения на панель void ( window); // Отключение OpenGL void (void); // Рисование трехмерной сцены void (double Dir,double List,double Pitch);
// Сохранение параметров блока void SaveText(void); // Загрузка параметров блока void LoadText(char *text); // Создание таймера обновления void CreateRefreshTimer( parent); // Конструктор класса TOpenGLInstr(void); // Деструктор класса ~TOpenGLInstr(); }; //=================================================
// Вычисление нормали к треугольнику // p1,p2,p3 – массивы координат вершин {x,y,z} // norm – массив, в котором возвращаются вычисленные // координаты нормали void NormalToTriangle(GLfloat *p1,GLfloat *p2, GLfloat *p3,GLfloat *norm) { double m[3],a[3],b[3],R; // Вспомогательные переменные // Символические имена для координат векторов #define x 0 #define y 1 #define z 2 // Вычисляем векторное произведение векторов // a (p1->p2) и b (p1->p3) for(int i=0;i<3;i++) { a[i]=p2[i]-p1[i]; b[i]=p3[i]-p1[i]; } m[x]=a[y]*b[z]-a[z]*b[y]; m[y]=a[z]*b[x]-a[x]*b[z]; m[z]=a[x]*b[y]-a[y]*b[x]; // Длина получившегося вектора R=sqrt(m[x]*m[x]+m[y]*m[y]+m[z]*m[z]); // Приводим вектор к единичной длине for(int i=0;i<3;i++) norm[i]=(GLfloat)(m[i]/R); // Отмена макроопределений символических имен координат #undef x #undef y #undef z } //=================================================
// Построение треугольника p1-p2-p3 void DrawTriangleGL(GLfloat *p1,GLfloat *p2,GLfloat *p3) { GLfloat norm[3]; // Массив для вычисления нормали // Вычислить нормаль (p1,p2,p3,norm); // Установить нормаль в OpenGL glNormal3fv(norm); // Задать три точки треугольника glVertex3fv(p1); glVertex3fv(p2); glVertex3fv(p3); } //=================================================
// Рисование окружности в OpenGL void DrawCircleGL(GLfloat R,int N,GLfloat cR,GLfloat cG,GLfloat cB) { double aStep=(2.0*M_PI)/N; // Шаг ломаной по углу, радиан // Массивы для задания материала GLfloat MaterialAmbDiff[4], MaterialSpecular[4]={1.0,1.0,1.0,1.0}; // Запись цвета материала в массив MaterialAmbDiff[0]=cR; MaterialAmbDiff[1]=cG; MaterialAmbDiff[2]=cB; MaterialAmbDiff[3]=1.0; // Непрозрачный // Установка отражающих свойств (материала) фигуры glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, MaterialAmbDiff); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS, 50.0); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,MaterialSpecular); // Нормаль – по оси Z (окружность в плоскости XY) glNormal3f(0.0,0.0,1.0); // Рисуем замкнутую ломаную линию glBegin(GL_LINE_LOOP); for(int j=0;j<N;j++) // Цикл по углу { double a=aStep*j; // Угол double x=R*cos(a),y=R*sin(a); // Координаты точки glVertex3f((GLfloat)x,(GLfloat)y,0); } glEnd(); } //=================================================
// Рисование центрального объекта блока void DrawArrowGL(double R,double l,double w,double h,double b) { // Массивы для координат точек фигуры GLfloat p1[3],p2[3],p3[3],p4[3]; // Материал – дно и корма (белый цвет) GLfloat MaterialBack[] = {1.0, 1.0, 1.0, 1.0}; // Материал – левый борт (красный цвет) GLfloat MaterialLeft[] = {1.0, 0.5, 0.5, 1.0}; // Материал – правый борт (зеленый цвет) GLfloat MaterialRight[] = {0.5, 1.0, 0.5, 1.0}; // Символические имена для координат точек #define x 0 #define y 1 #define z 2 // Вычисление координат точек фигуры p1[x]=0; p1[y]=R; p1[z]=0; p2[x]=-w; p2[y]=R-l; p2[z]=0; p3[x]=w; p3[y]=p2[y]; p3[z]=0; p4[x]=0; p4[y]=p2[y]+b; p4[z]=h; // Построение граней glBegin(GL_TRIANGLES); // Свойства материала – общие для всех glMaterialf(GL_FRONT,GL_SHININESS,20.0); // Свойства материала – корма и дно glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,MaterialBack); glMaterialfv(GL_FRONT,GL_SPECULAR,MaterialBack); // Нижний треугольник (дно) (p1,p3,p2); // Задний треугольник (корма) (p2,p3,p4); // Свойства материала – левый борт glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,MaterialLeft); glMaterialfv(GL_FRONT,GL_SPECULAR,MaterialLeft); // Левый передний треугольник (p2,p4,p1); // Свойства материала – правый борт glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,MaterialRight); glMaterialfv(GL_FRONT,GL_SPECULAR,MaterialRight); // Правый передний треугольник (p4,p3,p1); glEnd(); // Отмена макроопределений символических имен координат #undef x #undef y #undef z } //=================================================
// Конструктор класса личной области данных // // // TOpenGLInstr::TOpenGLInstr(void) { // Создаем панель в окне подсистемы Panel=(0,0,0,300,300, || || || , "Прибор"); // Инициализируем идентификатор еще не созданного таймера RefreshTimer=NULL; } //================================================= // Деструктор класса личной области данных TOpenGLInstr::~TOpenGLInstr() { // Удаление панели if(Panel) (Panel); // Удаление таймера if(RefreshTimer) (RefreshTimer); } //================================================= // Создание таймера обновления панели void TOpenGLInstr::CreateRefreshTimer(RDS_BHANDLE parent) { // Структура для получения переметров окна подсистемы WinParams; // Определение интервала обновления окна подсистемы WinParams.servSize=sizeof(); (parent,&WinParams); // Интервал - в WinParams.RefreshDelay // Создание таймера RefreshTimer=(RefreshTimer, // Идентификатор WinParams.RefreshDelay, // Интервал | | , // Режим и флаги TRUE); // Запустить таймер } //================================================= // Функция сохранения параметров блока void TOpenGLInstr::SaveText(void) { ini; // Идентификатор вспомогательного объекта // При сохранении блока в отдельный файл на диске параметры // панели записывать не нужно if(()==) return; // Создание вспомогательного объекта для работы с данными ini=(TRUE); // Параметры записываются в секцию "[Window]" (ini,,0,"Window"); // Получение параметров панели и запись их в объект (ini,"Left",(Panel,,0)); (ini,"Top",(Panel,,0)); (ini,"Width",(Panel,,0)); (ini,"Height",(Panel,,0)); (ini,"Visible",(Panel,,0)); // Сохранение получившегося текста в файл, в который в данный // момент идет запись (ini,); // Удаление вспомогательного объекта (ini); } //================================================= // Функция загрузки параметров блока void TOpenGLInstr::LoadText(char *text) { ini; // Идентификатор вспомогательного объекта // Создание вспомогательного объекта для работы с данными ini=(TRUE); // Запись в объект полученного от RDS текста с параметрами блока (ini,,0,text); // Установка "[Window]" в качестве текущей секции и чтение // из нее пяти целых параметров if(rdsINIOpenSection(ini,"Window")) { (Panel,,0, (ini,"Left",0)); (Panel,,0, (ini,"Top",0)); (Panel,,0, (ini,"Width",0)); (Panel,,0, (ini,"Height",0)); (Panel,,0, (ini,"Visible",0)); } // Удаление вспомогательного объекта (ini); } //=================================================
// Настройка вывода изображения на панель void TOpenGLInstr::InitWindow( window) { Hdc; // Контекст устройства Windows // Структура для установки формата изображения PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Размер структуры 1, // Номер версии PFD_DRAW_TO_WINDOW | // Вывод в окно PFD_SUPPORT_OPENGL | // Поддержка OpenGL PFD_DOUBLEBUFFER, // Двойная буферизация PFD_TYPE_RGBA, // Формат цвета – RGBA 24, // Глубина цвета – 24 бита 0,0,0,0,0,0, // (здесь не используется) 0,0,0,0,0,0,0, // (здесь не используется) 32, // Z-буфер - 32 бита 0,0, // (здесь не используется) PFD_MAIN_PLANE, // Главный слой 0, // Зарезервировано 0,0, // Маски слоев (не исп.) }; int PixelFormat; // Получение контекста оконного объекта Hdc=GetDC(window); // Установка формата изображения по структуре pfd PixelFormat=ChoosePixelFormat(Hdc,&pfd); SetPixelFormat(Hdc,PixelFormat,&pfd); // Создание контекста OpenGL Hrc=wglCreateContext(Hdc); // Установка этого контекста в качестве текущего wglMakeCurrent(Hdc,Hrc); } //=================================================
// Отключение OpenGL void TOpenGLInstr::Clear() { // Отключение текущего контекста OpenGL wglMakeCurrent(NULL,NULL); // Уничтожение созданного контекста wglDeleteContext(Hrc); } //=================================================
// Служебная функция – настройка параметров OpenGL TOpenGLInstr::SetupGLParams( *pHdc) { // Параметры перспективной проекции const GLfloat zNear=0.1; // Ближняя плоскость отсечения const GLfloat zFar=1000.0; // Дальняя плоскость отсечения const GLfloat vAngle=30.0; // Угол зрения Hdc; // Контекст устройства (окна) Windows // Расположение источника освещения const double lightDistance=500.0; // Расстояние до объекта const double lightRotation=-55.0; // Азимут в градусах const double lightPitch=45.0; // Угол места в градусах // Вспомогательные переменные descr; int width,height; GLfloat array[4]; double l_r,l_p; // Получение описания панели и дескриптора ее окна descr.servSize=sizeof(); if(!RDS(Panel,&descr)) // Не удалось return FALSE; if(descr.Handle==NULL) // Нет оконного объекта return FALSE; // Проверка высоты и ширины панели if(descr.Height==0 || descr.Width==0) return FALSE; // Негде рисовать // Получение контекста окна и передача в вызвавшую функцию // его через параметр-указатель Hdc=GetDC(descr.Handle); if(pHdc) *pHdc=Hdc; // Установка контекста Hrc, созданного при инициализации, // в качестве текущего if(!wglMakeCurrent(Hdc,Hrc)) return FALSE; // Не удалось // Уcтановка различных параметров, влияющих на качество рисования // и способ закраски многоугольников glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glHint(GL_POLYGON_SMOOTH_HINT,GL_FASTEST); glEnable(GL_POINT_SMOOTH); glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.0f,0.0f,0.0f,1.0f); // Цвет фона - черный glClearDepth(1.0); // Значение для очистки Z-буфера //----------- Установка освещения ---------- // Общее рассеянное освещение array[0]=array[1]=array[2]=0.5; // Белый, интенсивность 0.5 array[3]=1.0; glLightModelfv(GL_LIGHT_MODEL_AMBIENT,array); // Вычисление координат источника света l_r=(lightRotation*M_PI)/180.0; l_p=(lightPitch*M_PI)/180.0; array[0]=(GLfloat)(lightDistance*cos(l_p)*sin(l_r)); // X array[1]=(GLfloat)(lightDistance*sin(l_p)); // Y array[2]=(GLfloat)(lightDistance*cos(l_p)*cos(l_r)); // Z array[3]=0.0; glLightfv(GL_LIGHT0,GL_POSITION,array); // Рассеянное освещение от источника отсутствует array[0]=array[1]=array[2]=0.0; // Отсутствует - интенсивность 0 array[3]=1.0; glLightfv(GL_LIGHT0,GL_AMBIENT,array); // Другие виды освещения – белый цвет array[0]=array[1]=array[2]=0.5; // Белый, интенсивность 0.5 glLightfv(GL_LIGHT0,GL_DIFFUSE,array); glLightfv(GL_LIGHT0,GL_SPECULAR,array); // Включение источника света glEnable(GL_LIGHT0); // Разрешение расчета освещения glEnable(GL_LIGHTING); // Режим расчета “затенения" glShadeModel(GL_SMOOTH); // Способ расчета освещения glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); //------------------------------------------ // Установка области окна для рисования glViewport(0,0,descr.Width,descr.Height); // Настройка перспективной проекции на эту область glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(vAngle, (GLfloat)descr.Width/(GLfloat)descr.Height, zNear,zFar); // Переключение на матрицу моделей (для рисования объектов) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return TRUE; // Установка параметров успешно завершена } //=================================================
// Рисование трехмерной сцены void TOpenGLInstr::RenderScene(double Dir,double List,double Pitch) { Hdc; // Контекст устройства Windows // Угол места камеры в градусах const GLfloat Camera_Pitch=-50.0; // Расстояние до камеры const GLfloat Camera_Distance=300.0; // Настройка параметров OpenGL и получение контекста окна if(!(&Hdc)) return; // Очистка буфера изображения и Z-буфера glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Записать матрицу трансформаций в стек glPushMatrix(); // Трансформации камеры glTranslatef(0.0,0.0,-Camera_Distance); // Отодвигаем от камеры glRotatef(Camera_Pitch,1,0,0); // Поворачиваем // Рисование неподвижной зеленой (0,1,0) окружности (60,100,0.0,1.0,0.0); if(Dir!= && List!= && Pitch!=) // Можно рисовать { // Поворот на угол курса if(Dir!=0.0) glRotatef(Dir,0,0,1); // Поворот на угол дифферента if(Pitch!=0.0) glRotatef(Pitch,1,0,0); // Поворот на угол крена if(List!=0.0) glRotatef(-List,0,1,0); // Рисование подвижной белой (1,1,1) окружности (55,100,1.0,1.0,1.0); // Рисование центрального объекта (50,80,30,10,10); } // Восстановить матрицу трансформаций из стека glPopMatrix(); // Завершить незавершенное рисование, если нужно glFlush(); // Поменять местами видимый и рабочий буферы SwapBuffers(Hdc); } //=================================================
// Модель блока с панелью extern "C" __declspec(dllexport) int OpenGLInstr( int CallMode, BlockData, ExtParam) {
// #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define Dir (*((double *)(pStart+2*RDS_VSZ_S))) #define List (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D))) #define Pitch (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D)))
// Указатель на личную область, приведенный к нужному типу TOpenGLInstr *data=(TOpenGLInstr*)(BlockData->BlockData); // Вспомогательная – указатель на структуру параметров при // действиях с панелью (будет использована в реакциях) param; switch(CallMode) { // Инициализация блока case : // Создание личной области данных // (при этом в конструкторе будет создана панель) BlockData->BlockData=data=new TOpenGLInstr(); break; // Очистка данных блока case : // В деструкторе класса панель будет уничтожена delete data; break;
// Проверка типа переменных case : if(strcmp((char*)ExtParam,"{SSDDD}")) return ; return ;
// Запуск расчета case : // Создание таймера обновления data->CreateRefreshTimer(BlockData->Parent); break; // Вызов функции настройки или двойной щелчок // левой кнопки мыши case : case : // Показать панель (data->Panel,,0,1); break; // Сохранение параметров блока case : data->SaveText(); break; // Загрузка параметров блока case : data->LoadText((char*)ExtParam); break; // Действия с панелью case : // Приведение указателя на структуру, переданного в // ExtParam, к нужному типу param=()ExtParam; // Разные действия в зависимости от операции с панелью switch(param->Operation) { // Создание оконного объекта для панели case : // Настройка вывода изображения на панель data->(param->Panel->Handle); break; // Уничтожение оконного объекта панели case : // Отключение OpenGL data->(); break; // Размер панели изменен case : // При изменении размера – просто перерисовка data->(Dir,List,Pitch); break; // Необходимо перерисовать изображение case : data->(Dir,List,Pitch); break; } break; // Необходимо обновить окна блока (вызывается таймером) case : // Перерисовка изображения data->(Dir,List,Pitch); break; } return ;
// Отмена макроопределений #undef Pitch #undef List #undef Dir #undef Ready #undef Start #undef pStart
} //=================================================


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