Текущий раздел:

Описания RDS

Руководство программиста

Глава 2. Создание моделей блоков

§2.12. Реакция блоков на действия пользователя

§2.12.4. Реакция блоков на клавиатуру

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

      // Реакция блока на клавиатуру
      #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;
      }
      //========= Конец главной функции =========

      //====== Класс личной области данных ======
      class TPlusMinusData
      { public:
          int KeyPlus;       // Клавиша увеличения
          DWORD ShiftsPlus;  // и ее флаги
          int KeyMinus;      // Клавиша уменьшения
          DWORD ShiftsMinus; // и ее флаги

          int Setup(void);   // Функция настройки клавиш
          void SaveBin(void);// Сохранение параметров
          int LoadBin(void); // Загрузка параметров

          // Конструктор класса
          TPlusMinusData(void)
            { KeyPlus=ShiftsPlus=KeyMinus=ShiftsMinus=0;};
      };
      //=========================================
      // Функция задания клавиш
      // ВАЖНО: Исходный текст программы должен быть записан в UTF8,
      //   в противном случае необходимо использовать версии функций
      //   с суффиксом "W" и символьные константы с префиксом "L"
      int TPlusMinusData::Setup(void)
      { RDS_HOBJECT window; // Идентификатор вспомогательного объекта
        BOOL ok;            // Пользователь нажал "OK"
        // Создание окна
        window=rdsFORMCreate(FALSE,-1,-1,"Плюс/минус");
        // Добавление полей ввода
        rdsFORMAddEdit(window,0,1,RDS_FORMCTRL_HOTKEY,
                       "Клавиша увеличения:",80);
        rdsFORMAddEdit(window,0,2,RDS_FORMCTRL_HOTKEY,
                       "Клавиша уменьшения:",80);
        // Занесение исходных значений кодов клавиш в поля ввода
        rdsSetObjectInt(window,1,RDS_FORMVAL_VALUE,KeyPlus);
        rdsSetObjectInt(window,1,RDS_FORMVAL_HKSHIFTS,ShiftsPlus);
        rdsSetObjectInt(window,2,RDS_FORMVAL_VALUE,KeyMinus);
        rdsSetObjectInt(window,2,RDS_FORMVAL_HKSHIFTS,ShiftsMinus);
        // Открытие окна
        ok=rdsFORMShowModalEx(window,NULL);
        if(ok)
          { // Нажата кнопка OK - запись кодов клавиш в класс
            KeyPlus=rdsGetObjectInt(window,1,RDS_FORMVAL_VALUE);
            ShiftsPlus=rdsGetObjectInt(window,1,RDS_FORMVAL_HKSHIFTS);
            KeyMinus=rdsGetObjectInt(window,2,RDS_FORMVAL_VALUE);
            ShiftsMinus=rdsGetObjectInt(window,2,RDS_FORMVAL_HKSHIFTS);
          }
        // Уничтожение окна
        rdsDeleteObject(window);
        // Возвращаемое значение
        return ok?RDS_BFR_MODIFIED:RDS_BFR_DONE;
      }
      //=========================================
      // Сохранение параметров
      void TPlusMinusData::SaveBin(void)
      { BYTE tag; // Переменная для байта тега

        tag=1; // Тег 1 - клавиша увеличения
        rdsWriteBlockData(&tag,sizeof(tag));
        rdsWriteBlockData(&KeyPlus,sizeof(KeyPlus));
        rdsWriteBlockData(&ShiftsPlus,sizeof(ShiftsPlus));

        tag=2; // Тег 2 - клавиша уменьшения
        rdsWriteBlockData(&tag,sizeof(tag));
        rdsWriteBlockData(&KeyMinus,sizeof(KeyMinus));
        rdsWriteBlockData(&ShiftsMinus,sizeof(ShiftsMinus));

        tag=0; // Тег 0 - конец данных
        rdsWriteBlockData(&tag,sizeof(tag));
      }
      //=========================================
      // Загрузка параметров
      int TPlusMinusData::LoadBin(void)
      { BYTE tag;

        for(;;) // Цикл до тех пор, пока данные не кончатся
          { // Читаем байт тега
            if(!rdsReadBlockData(&tag,sizeof(tag)))
              break; // Тег не считан - данные кончились
            // Анализируем считанный тег
            switch(tag)
              { case 0: // Конец данных блока
                  return RDS_BFR_DONE; // Загрузка успешно завершена
                case 1: // Данные клавиши увеличения
                  rdsReadBlockData(&KeyPlus,sizeof(KeyPlus));
                  rdsReadBlockData(&ShiftsPlus,sizeof(ShiftsPlus));
                  break;
                case 2: // Данные клавиши уменьшения
                  rdsReadBlockData(&KeyMinus,sizeof(KeyMinus));
                  rdsReadBlockData(&ShiftsMinus,sizeof(ShiftsMinus));
                  break;
                default: // Неопознанный тег
                  return RDS_BFR_ERROR; // Сообщаем RDS об ошибке
              }
          }
        // Данные кончились до тега 0 - сообщаем об ошибке
        return RDS_BFR_ERROR;
      }
      //=========================================

      // Увеличение/уменьшение значения по щелчку и клавишам
      extern "C" __declspec(dllexport)
        int RDSCALL PlusMinus(int CallMode,
                          RDS_PBLOCKDATA BlockData,
                          LPVOID ExtParam)
      {
      // Макроопределения для статических переменных
      #define pStart ((char *)(BlockData->VarTreeData))
      #define Start (*((char *)(pStart)))
      #define Ready (*((char *)(pStart+RDS_VSZ_S)))
      #define v (*((RDSINT32 *)(pStart+2*RDS_VSZ_S)))
        // Вспомогательная — указатель на структуру события мыши
        RDS_PMOUSEDATA mouse;
        // Вспомогательная — указатель на структуру события клавиатуры
        RDS_PKEYDATA key;
        // Указатель на личную область данных блока,приведенный к
        // правильному типу
        TPlusMinusData *data=(TPlusMinusData*)(BlockData->BlockData);
        switch(CallMode)
          { // Проверка типа статических переменных
            case RDS_BFM_VARCHECK:
              return strcmp((char*)ExtParam,"{SSI}")?
                RDS_BFR_BADVARSMSG:RDS_BFR_DONE;

            // Реакция на нажатие кнопки мыши
            case RDS_BFM_MOUSEDOWN:
              // Приведение ExtParam к нужному типу
              mouse=(RDS_PMOUSEDATA)ExtParam;
              if(mouse->Button==RDS_MLEFTBUTTON)
                { // Нажата левая кнопка
                  // Проверяем, есть ли у блока картинка (получаем
                  // описание блока)
                  RDS_BLOCKDESCRIPTION descr;
                  descr.servSize=sizeof(descr);
                  rdsGetBlockDescription(BlockData->Block,&descr);
                  if(descr.Flags & RDS_BDF_HASPICTURE)
                    { // Картинка есть – определяем идентификатор
                      // элемента под курсором
                      int id=rdsGetMouseObjectId(mouse);
                      v+=id;
                    }
                  else if(mouse->y<mouse->Top+mouse->Height/2)
                    v++; // В верхней половине блока - увеличиваем
                  else
                    v--; // В нижней половине блока — уменьшаем
                  // Взводим сигнал готовности
                  Ready=1;
                }
              break;

            case RDS_BFM_INIT: // Инициализация
              BlockData->BlockData=new TPlusMinusData();
              break;
            case RDS_BFM_CLEANUP: // Очистка данных
              delete data;
              break;
            case RDS_BFM_SETUP: // Настройка параметров
              return data->Setup();
            case RDS_BFM_SAVEBIN:// Сохранение параметров
              data->SaveBin();
              break;
            case RDS_BFM_LOADBIN: // Загрузка параметров
              return data->LoadBin();

            // Реакция на нажатие клавиши
            case RDS_BFM_KEYDOWN:
              // Приведение ExtParam к нужному типу
              key=(RDS_PKEYDATA)ExtParam;
              // Сравнение нажатой клавиши с клавишами уменьшения
              // и увеличения
              if(key->KeyCode==data->KeyPlus &&
                 key->Shift==data->ShiftsPlus)
                { v++; Ready=1; }
              else if(key->KeyCode==data->KeyMinus &&
                      key->Shift==data->ShiftsMinus)
                { v--; Ready=1; }
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef v
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================