Полный исходный текст на языке C++ для библиотеки (DLL) с моделями блоков, имеющих прозрачные для щелчков мыши «окна». Библиотека содержит две модели:
- EditControlFrame_1 – прозрачное «окно» в блоке будет работать только в режимах моделирования и расчета;
- EditControlFrame – «окно» будет работать и в режиме редактирования (изменения в модели выделены цветом).
// Реакция на мышь в блоках с "окнами" #include <windows.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; } //========= Конец главной функции ========= // Блок с "окном" - первый вариант // (в режиме редактирования "окно" не работает) extern "C" __declspec(dllexport) int RDSCALL EditControlFrame_1(int CallMode, RDS_PBLOCKDATA BlockData, LPVOID 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; // Толщина рамки // Вспомогательные переменные RDS_PMOUSEDATA mouse; RDS_PDRAWDATA draw; int frz,x1,y1,x2,y2,xi1,yi1,xi2,yi2; switch(CallMode) { // Проверка типов статических переменных case RDS_BFM_VARCHECK: return strcmp((char*)ExtParam,"{SSDDDL}")? RDS_BFR_BADVARSMSG:RDS_BFR_DONE; // Реакция на нажатие кнопки мыши case RDS_BFM_MOUSEDOWN: mouse=(RDS_PMOUSEDATA)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 RDS_BFR_NOTPROCESSED; // Если не левая кнопка - не обрабатываем щелчок // и разрешаем вывести контекстное меню, если нужно if(mouse->Button!=RDS_MLEFTBUTTON) return RDS_BFR_SHOWMENU; // Нажата левая кнопка мыши, причем курсор попал // в рамку или блок в закрытом состоянии bypass=!bypass; // Переключаем состояние Ready=1; // Взводим сигнал готовности // Здесь намеренно не поставлен оператор break: необходимо // выполнить действия в следующем case (такт расчета) // Один такт расчета case RDS_BFM_MODEL: // В зависимости от состояния, подаем на выход // один из входов out=bypass?x_ext:x_int; break; // Рисование внешнего вида блока case RDS_BFM_DRAW: draw=(RDS_PDRAWDATA)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; // Рисуем красный прямоугольник с черной рамкой rdsXGSetPenStyle(0,PS_SOLID,1,0,R2_COPYPEN); rdsXGSetBrushStyle(0,RDS_GFS_SOLID,0xff); rdsXGRectangle(x1,y1,x2,y2); // Устанавливаем шрифт выстой в окно внутри блока rdsXGSetFont(0,"Arial",yi2-yi1,0, DEFAULT_CHARSET,0,FALSE,FALSE,FALSE,FALSE); // Преобразуем значение выхода в динамическую строку text=rdsDtoA(out,-1,NULL); // Определяем ширину получившейся строки на экране rdsXGGetTextSize(text,&w,NULL); // Выводим значение выхода туда, где в открытом // состоянии находится прозрачное окно rdsXGTextOut(xi2-w,yi1,text); // Освобождаем динамическую строку rdsFree(text); } else { // Открытое состояние rdsXGSetBrushStyle(0,RDS_GFS_SOLID,0xff00); // Рисуем рамку вокруг прозрачного окна из четырех // зеленых прямоугольников rdsXGFillRect(x1,y1,x2,yi1); rdsXGFillRect(x1,yi2,x2,y2); rdsXGFillRect(x1,yi1,xi1,yi2); rdsXGFillRect(xi2,yi1,x2,yi2); // Обрамляем черными линиями rdsXGSetPenStyle(0,PS_SOLID,1,0,R2_COPYPEN); rdsXGSetBrushStyle(0,RDS_GFS_EMPTY,0); rdsXGRectangle(x1,y1,x2,y2); rdsXGRectangle(xi1,yi1,xi2,yi2); } break; } return RDS_BFR_DONE; // Отмена макроопределений #undef bypass #undef out #undef x_int #undef x_ext #undef Ready #undef Start #undef pStart } //========================================= // Блок с "окном" - второй вариант // (добавлена поддержка режима редактирования) extern "C" __declspec(dllexport) int RDSCALL EditControlFrame(int CallMode, RDS_PBLOCKDATA BlockData, LPVOID 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; // Толщина рамки // Вспомогательные переменные RDS_PMOUSEDATA mouse; RDS_PDRAWDATA draw; int frz,x1,y1,x2,y2,xi1,yi1,xi2,yi2; switch(CallMode) { // Проверка типов статических переменных case RDS_BFM_VARCHECK: return strcmp((char*)ExtParam,"{SSDDDL}")? RDS_BFR_BADVARSMSG:RDS_BFR_DONE; // Реакция на нажатие кнопки мыши case RDS_BFM_MOUSEDOWN: mouse=(RDS_PMOUSEDATA)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 RDS_BFR_NOTPROCESSED; // Если не левая кнопка - не обрабатываем щелчок // и разрешаем вывести контекстное меню, если нужно if(mouse->Button!=RDS_MLEFTBUTTON) return RDS_BFR_SHOWMENU; // Нажата левая кнопка мыши, причем курсор попал // в рамку или блок в закрытом состоянии bypass=!bypass; // Переключаем состояние Ready=1; // Взводим сигнал готовности // Здесь намеренно не поставлен оператор break: необходимо // выполнить действия в следующем case (такт расчета) // Один такт расчета case RDS_BFM_MODEL: // В зависимости от состояния, подаем на выход // один из входов out=bypass?x_ext:x_int; break; // Рисование внешнего вида блока case RDS_BFM_DRAW: draw=(RDS_PDRAWDATA)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; // Рисуем красный прямоугольник с черной рамкой rdsXGSetPenStyle(0,PS_SOLID,1,0,R2_COPYPEN); rdsXGSetBrushStyle(0,RDS_GFS_SOLID,0xff); rdsXGRectangle(x1,y1,x2,y2); // Устанавливаем шрифт выстой в окно внутри блока rdsXGSetFont(0,"Arial",yi2-yi1,0, DEFAULT_CHARSET,0,FALSE,FALSE,FALSE,FALSE); // Преобразуем значение выхода в динамическую строку text=rdsDtoA(out,-1,NULL); // Определяем ширину получившейся строки на экране rdsXGGetTextSize(text,&w,NULL); // Выводим значение выхода туда, где в открытом // состоянии находится прозрачное окно rdsXGTextOut(xi2-w,yi1,text); // Освобождаем динамическую строку rdsFree(text); } else { // Открытое состояние rdsXGSetBrushStyle(0,RDS_GFS_SOLID,0xff00); // Рисуем рамку вокруг прозрачного окна из четырех // зеленых прямоугольников rdsXGFillRect(x1,y1,x2,yi1); rdsXGFillRect(x1,yi2,x2,y2); rdsXGFillRect(x1,yi1,xi1,yi2); rdsXGFillRect(xi2,yi1,x2,yi2); // Обрамляем черными линиями rdsXGSetPenStyle(0,PS_SOLID,1,0,R2_COPYPEN); rdsXGSetBrushStyle(0,RDS_GFS_EMPTY,0); rdsXGRectangle(x1,y1,x2,y2); rdsXGRectangle(xi1,yi1,xi2,yi2); } break;// Проверка возможности выбора блока мышью case RDS_BFM_MOUSESELECT: mouse=(RDS_PMOUSEDATA)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 RDS_BFR_NOTPROCESSED; // В окно не попали - функция вернет RDS_BFR_DONE break;} return RDS_BFR_DONE; // Отмена макроопределений #undef bypass #undef out #undef x_int #undef x_ext #undef Ready #undef Start #undef pStart } //=========================================