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

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

  // Регистрация исполнителя функции
  #include <windows.h>
  #include <stdio.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;
  }
  //========= Конец главной функции =========

  //====================================================================
  // Имя и параметры функции
  //====================================================================
  // Функция вывода сообщения
  #define PROGGUIDEMESSAGEFUNC ""
  // Структура параметров функции
  typedef struct
  { DWORD servSize;   // Размер этой структуры
    char *MessageStr; // Текст сообщения
    int Level;        // Уровень важности (0, 1 или 2)
  } ;
  //=========================================
  // Глобальная переменная для идентификатора функции
  int =0;
  //=========================================


  //====================================================================
  // Блок-исполнитель функции, показывающей сообщение пользователю
  //====================================================================
  extern "C" __declspec(dllexport)
    int  MessageFuncBlock_Box(int CallMode,
         BlockData,
         ExtParam)
  {  func;
    switch(CallMode)
      { // Инициализация
        case :
          // Регистрируем функцию
          if(==0)
            =(PROGGUIDEMESSAGEFUNC);
          // Объявляем этот блок ее исполнителем
          (,FALSE);
          break;

        // Очистка
        case :
          // Отменяем регистрацию данного блока как исполнителя
          ();
          break;

        // Вызов функции
        case :
          // Приводим ExtParam к правильному типу
          func=()ExtParam;
          if(func->Function==)
            { // Вызвана ""
               *params=
                (*)(func->Data);
               icon;
              char *caption;
              // Проверяем наличие параметров и их размер
              if(params==NULL ||
                 params->servSize<sizeof())
                break; // Параметров нет или неверный размер
              // В зависимости от уровня важности сообщения
              // устанавливаем иконку и заголовок
              // 
              // 
              // 
              switch(params->Level)
                { case 0:  icon=;
                           caption="Информация";
                           break;
                  case 1:  icon=;
                           caption="Предупреждение";
                           break;
                  default: icon=;
                           caption="Ошибка";
                }
              // Показываем сообщение пользователю
              (params->MessageStr,caption,icon | );
            }
          break;
      }
    return ;
  }
  //=========================================

  //====================================================================
  // Блок, вызывающий функцию вывода сообщения
  //====================================================================

  // Личная область данных блока, выводящего сообщение
  class TMessageFuncUserData
  { public:
      // Указатель на структуру подписки
       Link;

      // Функция настройки блока
       Setup( Block,int NumTypeVar,int NumMessVar);

      // Конструктор класса
      TMessageFuncUserData(void)
        { // Регистрируем функцию
          if(==0)
            =(PROGGUIDEMESSAGEFUNC);
          // Подписываемся на блок-исполнитель
          Link=();
        };
      // Деструктор класса
      ~TMessageFuncUserData()
        { // Прекращаем подписку
          ();
        };
  };
  //=========================================

  // Блок, выводящий сообщение по сигналу
  extern "C" __declspec(dllexport)
    int  ShowMessage(int CallMode,
         BlockData,
         ExtParam)
  { // Указатель на личную область данных
    TMessageFuncUserData *data=
        (TMessageFuncUserData*)(BlockData->BlockData);
  // 
  #define pShow ((char *)(BlockData->VarTreeData))
  #define Show (*((char *)(pShow)))
  #define Ready (*((char *)(pShow+RDS_VSZ_S)))
  #define Message (*((char **)(pShow+2*RDS_VSZ_S)))
  #define Type (*((RDSINT32 *)(pShow+2*RDS_VSZ_S+RDS_VSZ_A)))

    switch(CallMode)
      { // Инициализация – создание личной области
        case :
          BlockData->BlockData=new TMessageFuncUserData();
          break;

        // Очистка – удаление личной области
        case :
          delete data;
          break;

        // Проверка типов переменных
        case :
          return strcmp((char*)ExtParam,"{SSAI}")?
              :;

        // Настройка блока
        case :
          return data->Setup(BlockData->Block,3,2)?1:0;

        // Такт расчета (реакция на сигнал Show)
        case :
          if(data->Link!=NULL) // Есть структура подписки
            {  params;
              // Готовим структуру параметров функции
              params.servSize=sizeof(params);
              params.MessageStr=Message;
              params.Level=Type;
              // Вызываем функцию по данным подписки
              (data->Link->Block,
                data->Link->FuncId,&params);
            }
          break;
      }
    return ;
  // Отмена макрооперделений
  #undef Type
  #undef Message
  #undef Ready
  #undef Show
  #undef pShow
  }
  //=========================================

  // Функция настройки блока
  // 
  // 
  // 
   TMessageFuncUserData::Setup( Block,
            int NumTypeVar,int NumMessVar)
  {  window; // Объект-окно
     ok;            // Пользователь нажал "OK"
    char *defval;

    // Создание окна
    window=(FALSE,-1,-1,"Сообщение");

    // Важность сообщения
    // Получение значения переменной по умолчанию
    defval=(Block,NumTypeVar,NULL);
    // Добавление поля – выпадающий список
    (window,0,1,,"Тип:",150);
    // Установка списка вариантов
    (window,1,,
        "Информация\nПредупреждение\nОшибка");
    // Установка текущего значения поля
    (window,1,,defval);
    // Освобождение defval
    (defval);

    // Текст сообщения
    // Получение значения переменной по умолчанию
    defval=(Block,NumMessVar,NULL);
    // Добавление поля – многострочное
    (window,0,2,,"Текст:",80);
    // Установка текущего значения поля
    (window,2,,defval);
    // Установка высоты поля в точках экрана (~3 строки)
    (window,2,,3*24);
    // Освобождение defval
    (defval);

    // Открытие окна
    ok=(window,NULL);
    if(ok)
      { // Пользователь нажал OK – запись измененных параметров
        defval=(window,1,);
        (Block,NumTypeVar,defval);
        defval=(window,2,);
        (Block,NumMessVar,defval);
      }
    // Уничтожение окна
    (window);
    return ok;
  }
  //=========================================

  //====================================================================
  // Блок-исполнитель функции, записывающий сообщение в файл
  //====================================================================

  // Функция настройки блока вывода сообщения в файл
  // 
  // 
  // 
   MessageFuncBlockFileSetup(
     Block, // Идентификатор блока
    int NumFileVar,    // Номер переменной имени файла
    int NumClearVar)   // Номер переменной флага очистки
  {  window;// Идентификатор объекта-окна
     ok; // Пользователь нажал "OK"
    char *defval;

    // Создание окна
    window=(FALSE,-1,-1,"Запись в файл");

    // Поле ввода для имени файла
    // Чтение значения переменной по умолчанию
    defval=(Block,NumFileVar,NULL);
    // Поле ввода – выбор файла с диалогом сохранения
    (window,0,1,,"Файл:",300);
    // Фильтр типов файлов для диалога сохранения
    (window,1,,
        "Текстовые файлы (*.txt)|*.txt\nВсе файлы|*.*");
    // Запись значения в поле ввода
    (window,1,,defval);
    // Освобождение defval
    (defval);

    // Очистка при загрузке схемы
    // Чтение значения переменной по умолчанию
    defval=(Block,NumClearVar,NULL);
    // Поле ввода - флаг
    (window,0,2,,
        "Очищать при загрузке схемы",0);
    // Запись значения в поле ввода
    (window,2,,defval);
    // Освобождение defval
    (defval);

    // Открытие окна
    ok=(window,NULL);
    if(ok)
      { // Пользователь нажал OK – запись измененных значений
        defval=(window,1,);
        (Block,NumFileVar,defval);
        defval=(window,2,);
        (Block,NumClearVar,defval);
      }
    // Уничтожение окна
    (window);
    return ok;
  }
  //=========================================

  // Блок-исполнитель функции, выводящий сообщение в файл
  // 
  // 
  // 
  extern "C" __declspec(dllexport)
    int  MessageFuncBlock_File(int CallMode,
         BlockData,
         ExtParam)
  {  func;
  // 
  #define pStart ((char *)(BlockData->VarTreeData))
  #define Start (*((char *)(pStart)))
  #define Ready (*((char *)(pStart+RDS_VSZ_S)))
  #define FileName (*((char **)(pStart+2*RDS_VSZ_S)))
  #define ClearOnLoad (*((char *)(pStart+2*RDS_VSZ_S+RDS_VSZ_A)))
    switch(CallMode)
      { // Инициализация
        case :
          // Регистрация функции
          if(==0)
            =(PROGGUIDEMESSAGEFUNC);
          // Объявляем данный блок ее исполнителем
          (,FALSE);
          break;

        // Очистка
        case :
          // Отмена регистрации блока как исполнителя
          ();
          break;

        // Проверка типов статических переменных
        case :
          return strcmp((char*)ExtParam,"{SSAL}")?
            :;

        // Вызов функции настройки
        case :
          return MessageFuncBlockFileSetup(BlockData->Block,2,3)?1:0;

        // Загрузка схемы только что завершилась
        case :
          if(ClearOnLoad) // Включена очистка файла при загрузке
            { // Формируем в fullpath полный путь к файлу, т.к.
              // введенный пользователем может быть неполным
              char *fullpath=(FileName,NULL,NULL);
              if(fullpath) // Полный путь существует
                { // Преобразуем в UTF16
                   fullpath_w=(fullpath,FALSE);
                  DeleteFileW(fullpath_w); // Удаляем файл
                  // Освобождаем память
                  (fullpath_w);
                  (fullpath);
                }
            }
          break;

        // Вызов функции
        case :
          func=()ExtParam;
          if(func->Function==MessageFunc)
            { // Вызвана наша функция – приводим параметры к правильному типу
               *params=
                  (*)(func->Data);
              char *levelstr,*fullpath;
               fullpath_w; // Для имени файла в UTF16
              if(params==NULL ||
                 params->servSize<sizeof())
                break; // Параметров нет или неверный размер
              // Записываем в переменную levelstr строку,
              // соотвествующую важности сообщения
              switch(params->Level)
                { case 0:  levelstr="Информация";
                           break;
                  case 1:  levelstr="Предупреждение";
                           break;
                  default: levelstr="Ошибка";
                }
              // Формируем в fullpath полный путь к файлу
              fullpath=(FileName,NULL,NULL);
              if(fullpath) // Полный путь сформирован
                { HANDLE h;
                  // Преобразуем в UTF16
                  fullpath_w=(fullpath,FALSE);
                  // Открываем файл fullpath на запись
                  h=CreateFileW(fullpath_w,GENERIC_WRITE,0,NULL,
                                OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
                  if(h!=INVALID_HANDLE_VALUE)
                    { // Файл открыт
                      char buf[100];  temp; SYSTEMTIME time;
                      // Перемещаем указатель файла в конец
                      SetFilePointer(h,0,NULL,FILE_END);
                      // Получаем текущую дату и время
                      GetLocalTime(&time);
                      // Формируем строку с датой и временем в buf
                      sprintf(buf,"%02d-%02d-%04d %02d:%02d:%02d "
                        "%s: ",time.wDay,time.wMonth,time.wYear,
                        time.wHour,time.wMinute,time.wSecond,
                        levelstr);
                      // Записываем дату, время и важность
                      WriteFile(h,buf,strlen(buf),&temp,NULL);
                      // Записываем текст сообщения
                      if(params->MessageStr)
                        WriteFile(h,params->MessageStr,
                          strlen(params->MessageStr),&temp,NULL);
                      // Записываем перевод строки
                      WriteFile(h,"\r\n",2,&temp,NULL);
                      // Закрываем файл
                      CloseHandle(h);
                    }
                  // Освобождаем память, отведенную под полный путь
                  (fullpath_w);
                  (fullpath);
                }
            }
          break;
      }
    return ;
  // Отмена макроопределений
  #undef ClearOnLoad
  #undef FileName
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================


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