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

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

  // Добавление пунктов в контекстное меню блока
  #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;
// Флаги фиксации одной из координат LockX,LockY; // Идентификаторы добавленных пунктов меню MenuLockX,MenuLockY;
public: // Настроечные параметры блока BorderColor; // Цвет рамки блока FieldColor; // Цвет прямоугольника HandleColor; // Цвет круга в покое MovingHandleColor; // Цвет круга при таскании
GrayedColor; // Цвет недоступной области
int HandleSize; // Диаметр круга // Реакция на нажатие кнопки мыши int MouseDown( mouse,double x,double y, *pFlags); // Реакция на перемещение курсора мыши void MouseMove( mouse,double *px,double *py); // Рисование изображения блока void Draw( draw,double x,double y,BOOL moving);
// Реакция на выбор добавленного пункта меню void MenuFunction( MenuData);
// Конструктор класса TSimpleJoystick(void) { BorderColor=0; // Черная рамка FieldColor=0xffffff; // Белое поле HandleColor=0xff0000; // Синий круг MovingHandleColor=0xff; // Красный при таскании HandleSize=20; // Диаметр круга };
// Деструктор класса ~TSimpleJoystick() { // Уничтожение пунктов меню (MenuLockX); (MenuLockY); };
}; //========================================= // Рисование изображения блока void TSimpleJoystick::Draw( draw, double x,double y, moving) { int hx,hy,cx,cy; RECT 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);
// Рисование ограничений if(LockX||LockY) // Фиксируется одна из координат { // Установка серого цвета заливки (0,,GrayedColor); if(LockX) // Фиксируется X { (r.left,r.top,hx-hR,r.bottom); // Слева (hx+hR,r.top,r.right,r.bottom); // Справа } else // Фиксируется Y { (r.left,r.top,r.right,hy-hR); // Сверху (r.left,hy+hR,r.right,r.bottom);// Снизу } }
// Линии перекрестия (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, *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] if(!LockX) { *px=2.0*(hx-cx)/mouse->Width; if(*px>1.0) *px=1.0; else if(*px<-1.0) *px=-1.0; } if(!LockY) { *py=-2.0*(hy-cy)/mouse->Height; if(*py>1.0) *py=1.0; else if(*py<-1.0) *py=-1.0; } } //=========================================
// Функция реакции на выбор одного из пунктов меню void TSimpleJoystick::MenuFunction( MenuData) { switch(MenuData->Function) { case 1: // Выбран пункт "Фиксировать X" LockX=!LockX; // Переключаем флаг фиксации X LockY=FALSE; // Отключаем фиксацию Y break; case 2: // Выбран пункт "Фиксировать Y" LockY=!LockY; // Переключаем флаг фиксации Y LockX=FALSE; // Отключаем фиксацию X break; } // Установка галочек у пунктов меню в зависимости от // флагов фиксации координат (MenuLockX,LockX?:0); (MenuLockY,LockY?: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;
// Выбор пользователем добавленного пункта меню case : data->MenuFunction(()ExtParam); break;
} return ; // Отмена макроопределений #undef y #undef x #undef Ready #undef Start #undef pStart } //========================================= //============================================================================ // Блок с "окном" //============================================================================ extern "C" __declspec(dllexport) int EditControlFrame(int CallMode, BlockData, ExtParam) { // #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define x_ext (*((double *)(pStart+2*RDS_VSZ_S))) #define x_int (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D))) #define out (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D))) #define bypass (*((char *)(pStart+2*RDS_VSZ_S+3*RDS_VSZ_D))) const int fr=20; // Толщина рамки // Вспомогательные переменные mouse; draw; int frz,x1,y1,x2,y2,xi1,yi1,xi2,yi2; switch(CallMode) { // Проверка типов статических переменных case : return strcmp((char*)ExtParam,"{SSDDDL}")? :; // Реакция на нажатие кнопки мыши case : mouse=()ExtParam; // Толщина рамки с учетом масштаба frz=fr*mouse->DoubleZoom; // В открытом состоянии при попадании курсора внутрь // прозрачного окна на щелчок реагировать не нужно if(bypass==0 && mouse->x>mouse->Left+frz && mouse->y>mouse->Top+frz && mouse->x<mouse->Left+mouse->Width-frz && mouse->y<mouse->Top+mouse->Height-frz) return ; // Если не левая кнопка - не обрабатываем щелчок // и разрешаем вывести контекстное меню, если нужно if(mouse->Button!=) return ; // Нажата левая кнопка мыши, причем курсор попал // в рамку или блок в закрытом состоянии bypass=!bypass; // Переключаем состояние Ready=1; // Взводим сигнал готовности // Здесь намеренно не поставлен оператор break: необходимо // выполнить действия в следующем case (такт расчета) // Один такт расчета case : // В зависимости от состояния, подаем на выход // один из входов out=bypass?x_ext:x_int; break; // Рисование внешнего вида блока case : draw=()ExtParam; // Координаты описывающего прямоугольника блока x1=draw->Left; x2=draw->Left+draw->Width; y1=draw->Top; y2=draw->Top+draw->Height; // Толщина рамки с учетом масштаба frz=fr*draw->DoubleZoom; // Координаты окна внутри блока xi1=x1+frz; xi2=x2-frz; yi1=y1+frz; yi2=y2-frz; if(bypass) { // Закрытое состояние int w; char *text; // Рисуем красный прямоугольник с черной рамкой (0,,1,0,); (0,,0xff); rdsXGRectangle(x1,y1,x2,y2); // Устанавливаем шрифт выстой в окно внутри блока (0,"Arial",yi2-yi1,0, ,0,FALSE,FALSE,FALSE,FALSE); // Преобразуем значение выхода в динамическую строку text=(out,-1,NULL); // Определяем ширину получившейся строки на экране (text,&w,NULL); // Выводим значение выхода туда, где в открытом // состоянии находится прозрачное окно (xi2-w,yi1,text); // Освобождаем динамическую строку (text); } else { // Открытое состояние (0,,0xff00); // Рисуем рамку вокруг прозрачного окна из четырех // зеленых прямоугольников (x1,y1,x2,yi1); (x1,yi2,x2,y2); (x1,yi1,xi1,yi2); (xi2,yi1,x2,yi2); // Обрамляем черными линиями (0,,1,0,); (0,,0); (x1,y1,x2,y2); (xi1,yi1,xi2,yi2); } break; // Проверка возможности выбора блока мышью case : mouse=()ExtParam; frz=fr*mouse->DoubleZoom; // Толщина рамки // Проверка попадания в прозрачное окно if(bypass==0 && mouse->x>mouse->Left+frz && mouse->y>mouse->Top+frz && mouse->x<mouse->Left+mouse->Width-frz && mouse->y<mouse->Top+mouse->Height-frz) return ; // В окно не попали - функция вернет break;
// Выбор пункта меню пользователем case : bypass=!bypass; // Переключить режим out=bypass?x_ext:x_int; // Подать на выход один из входов Ready=1; // Взвести флаг готовности break;
} return ; // Отмена макроопределений #undef bypass #undef out #undef x_int #undef x_ext #undef Ready #undef Start #undef pStart } //=========================================


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