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

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

  // Реакция на перемещение курсора мыши (п.2.12.2)
  #include <windows.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 TSimpleJoystick
  { private:
      // Центр круга (рукоятки) до начала перетаскивания
      int OldHandleX,OldHandleY;
      // Координаты курсора на момент начала перетаскивания
      int OldMouseX,OldMouseY;
    public:
      // Настроечные параметры блока
       BorderColor;       // Цвет рамки блока
       FieldColor;        // Цвет прямоугольника
       HandleColor;       // Цвет круга в покое
       MovingHandleColor; // Цвет круга при таскании
      int HandleSize;             // Диаметр круга

      // Реакция на нажатие кнопки мыши
      int MouseDown( mouse,double x,double y,DWORD *pFlags);
      // Реакция на перемещение курсора мыши
      void MouseMove( mouse,double *px,double *py);
      // Рисование изображения блока
      void Draw( draw,double x,double y,BOOL moving);

      // Конструктор класса
      TSimpleJoystick(void)
        { BorderColor=0;          // Черная рамка
          FieldColor=0xffffff;    // Белое поле
          HandleColor=0xff0000;   // Синий круг
          MovingHandleColor=0xff; // Красный при таскании
          HandleSize=20;          // Диаметр круга
        };
  };
  //=========================================

  // Рисование изображения блока
  void TSimpleJoystick::Draw( draw,
                             double x,double y,BOOL moving)
  { int hx,hy,cx,cy;
     r;
    int hR=HandleSize*draw->DoubleZoom/2; // Радиус круга-рукоятки

    // Если размер блока - нулевой, рисовать негде
    if(draw->Height==0 || draw->Width==0)
      return;

    // Рисование поля блока
    (0,,1,BorderColor,);
    (0,,FieldColor);
    (draw->Left,draw->Top,
                   draw->Left+draw->Width,draw->Top+draw->Height);

    // Вычисление центра прямоугольника блока
    cx=draw->Left+draw->Width/2;
    cy=draw->Top+draw->Height/2;

    // Вычисление координат центра круга-рукоятки
    hx=cx+x*draw->Width/2;
    hy=cy-y*draw->Height/2;

    // Установка области отсечения
    r.left=draw->Left+1;
    r.top=draw->Top+1;
    r.right=draw->Left+draw->Width-1;
    r.bottom=draw->Top+draw->Height-1;
    (&r);

    // Линии перекрестия
    (cx,draw->Top);
    (cx,draw->Top+draw->Height);
    (draw->Left,cy);
    (draw->Left+draw->Width,cy);

    // Рисование круга (цвет зависит от параметра moving)
    (,,0,0,0);
    (0,,
                       moving?MovingHandleColor:HandleColor);
    (hx-hR,hy-hR,hx+hR+1,hy+hR+1);

    // Отмена отсечения
    (NULL);
  }
  //=========================================

  // Реакция на нажатие кнопки мыши
  int TSimpleJoystick::MouseDown( mouse,
                                 double x,double y,DWORD *pFlags)
  { int hx,hy,cx,cy,
        hR=HandleSize*mouse->DoubleZoom/2; // Радиус круга

    // Если размер - нулевой, реакция не имеет смысла
    if(mouse->Height==0 || mouse->Width==0)
      return ;
    // Если нажата не левая кнопка, перетаскивать не надо
    // Разрешаем в этом случае вызов контекстного меню блока
    if(mouse->Button!=)
      return ;

    // Координаты цента блока
    cx=mouse->Left+mouse->Width/2;
    cy=mouse->Top+mouse->Height/2;
    // Координаты центра круга-рукоятки
    hx=cx+x*mouse->Width/2;
    hy=cy-y*mouse->Height/2;

    // Проверка попадания курсора в круг
    if(abs(mouse->x-hx)<=hR && abs(mouse->y-hy)<=hR)
      { // Курсор попал в круг
        // Запоминаем координаты центр круга на момент
        // начала перетаскивания
        OldHandleX=hx;
        OldHandleY=hy;
        // Координаты курсора на начало перетаскивания
        OldMouseX=mouse->x;
        OldMouseY=mouse->y;
        // Взводим флаг захвата мыши
        *pFlags|=;
      }
    // Курсор не попал в рукоятку - захватывать мышь
    // и подготавливать перетаскивание не нужно
    return ;
  }
  //=========================================

  // Реакция на перемещение курсора мыши
  void TSimpleJoystick::MouseMove( mouse,
                                  double *px,double *py)
  { int hx,hy,cx,cy;

    // Если размер - нулевой, реакция не имеет смысла
    if(mouse->Height==0 || mouse->Width==0)
      { *px=*py=0.0;
        return;
      }

    // Новые координаты центра рукоятки
    hx=OldHandleX+(mouse->x-OldMouseX);
    hy=OldHandleY+(mouse->y-OldMouseY);

    // Координаты центра блока
    cx=mouse->Left+mouse->Width/2;
    cy=mouse->Top+mouse->Height/2;

    // По новым координатам центра рукоятки вычисляем соответствующие
    // им вещественные значения выходов, ограничивая их
    // диапазоном [-1...1]
    *px=2.0*(hx-cx)/mouse->Width;
    if(*px>1.0) *px=1.0;
    else if(*px<-1.0) *px=-1.0;
    *py=-2.0*(hy-cy)/mouse->Height;
    if(*py>1.0) *py=1.0;
    else if(*py<-1.0) *py=-1.0;
  }
  //=========================================

  // Функция модели блока
  extern "C" __declspec(dllexport)
    int  SimpleJoystick(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)))
  #define y (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D)))
    // Вспомогательная переменная - указатель на личную область,
    //приведенный к правильному типу
    TSimpleJoystick *data=(TSimpleJoystick*)(BlockData->BlockData);
    switch(CallMode)
      { // Инициализация
       case :
          BlockData->BlockData=new TSimpleJoystick();
          break;
        // Очистка
        case :
          delete data;
          break;
        // Проверка допустимости типов переменных
        case :
          return strcmp((char*)ExtParam,"{SSDD}")?
            :;
        // Нажатие кнопки мыши
        case :
          return data->MouseDown(()ExtParam,x,y,
            &(BlockData->Flags));
        // Отпускание кнопки мыши
        case :
          // Снятие захвата мыши
          (BlockData->Flags,,FALSE);
          break;
        // Перемещение курсора мыши
        case :
          // Проверка: включен ли захват мыши
          if(BlockData->Flags & )	// Включен
            { // Вызываем функцию реакции
              data->MouseMove(()ExtParam,&x,&y);
              Ready=1; // Взводим сигнал готовности
            }
          break;
        // Рисование
        case :
          data->Draw(()ExtParam,x,y,
          BlockData->Flags & );
          break;
      }
    return ;
  // Отмена макроопределений
  #undef y
  #undef x
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================


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