Полный исходный текст на языке C++ для библиотеки (DLL) с моделью блока, добавляющего в главное меню RDS пункт для открытия родительской подсистемы.
// Добавление пунктов в системное меню #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 TOpenSysWinData { public: RDS_MENUITEM MenuItem; // Идентификатор созданного пункта меню // Настроечные параметры char *Caption; // Название пункта int Key; // Клавиша (или 0,если ее нет) DWORD KeyShifts; // Состояние Ctrl, Alt и Shift // Создание пункта меню с заданными параметрами или // изменение параметров уже созданного пункта void RegisterMenuItem(void); int Setup(void); // Открыть окно настройки void SaveBin(void); // Сохранить параметры int LoadBin(void); // Загрузить параметры // Конструктор класса TOpenSysWinData(void) { Caption=NULL; Key=0; KeyShifts=0; MenuItem=NULL; }; // Деструктор класса ~TOpenSysWinData() { // Освободить память, занятую строкой Caption rdsFree(Caption); // Удалить пункт меню rdsUnregisterMenuItem(MenuItem); }; }; //========================================= // Создание или модификация пункта меню // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" void TOpenSysWinData::RegisterMenuItem(void) { // Вспомогательная переменная для заголовка пункта меню: // если Caption==NULL, пункт получит заголовок "Открыть окно" const char *text=Caption?Caption:"Открыть окно"; // Флаги пункта меню: если клавиша определена (Key!=0), // пункт будет иметь "горячую клавишу" DWORD options=Key?RDS_MENU_SHORTCUT:0; if(MenuItem) // Пункт уже есть - изменяем rdsChangeMenuItem(MenuItem,text,options,Key,KeyShifts,0,0); else // Пункта еще нет - создаем MenuItem=rdsRegisterMenuItem(text,options,Key,KeyShifts,0,0); } //========================================= // Запись параметров блока void TOpenSysWinData::SaveBin(void) { BYTE tag; // Переменная для байта тега int len=Caption?strlen(Caption):0; // Длина строки Caption tag=1; // Тег 1 – название пункта меню rdsWriteBlockData(&tag,sizeof(tag)); rdsWriteBlockData(&len,sizeof(len)); // Длина строки if(len) // При ненулевой длине – запись самой строки rdsWriteBlockData(Caption,len); tag=2; // Тег 2 – "горячая клавиша" rdsWriteBlockData(&tag,sizeof(tag)); rdsWriteBlockData(&Key,sizeof(Key)); rdsWriteBlockData(&KeyShifts,sizeof(KeyShifts)); tag=0; // Тег 0 – конец данных rdsWriteBlockData(&tag,sizeof(tag)); } //========================================= // Загрузка параметров блока int TOpenSysWinData::LoadBin(void) { BYTE tag; // Переменная для байта тега int len; // Прежде всего, освобождаем память, которую занимало старое // название пункта меню – сейчас загрузится новое rdsFree(Caption); Caption=NULL; for(;;) { if(!rdsReadBlockData(&tag,sizeof(tag))) break; // Тег не считан – данные неожиданно кончились switch(tag) { case 0: // Конец данных RegisterMenuItem(); // Создаем или изменяем пункт меню return RDS_BFR_DONE; case 1: // Название пункта rdsReadBlockData(&len,sizeof(len)); // Читаем длину if(len) // Длина ненулевая – читаем len байтов строки { // Отводим место с учетом нуля в конце строки Caption=(char*)rdsAllocate(len+1); rdsReadBlockData(Caption,len); // Читаем строку Caption[len]=0; // Дописываем нулевой байт в конец } break; case 2: // Данные "горячей клавиши" rdsReadBlockData(&Key,sizeof(Key)); rdsReadBlockData(&KeyShifts,sizeof(KeyShifts)); break; default: // Тег не опознан – ошибка return RDS_BFR_ERROR; } } // Вышли из цикла из-за неожиданного конца данных блока - ошибка return RDS_BFR_ERROR; } //========================================= // Настройка параметров блока // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" int TOpenSysWinData::Setup(void) { RDS_HOBJECT window; // Идентификатор объекта-окна BOOL ok; // Пользователь нажал "OK" // Создание окна window=rdsFORMCreate(FALSE,-1,-1,"Открытие окна"); // Поле ввода для строки названия rdsFORMAddEdit(window,0,1,RDS_FORMCTRL_EDIT, "Текст пункта меню:",200); rdsSetObjectStr(window,1,RDS_FORMVAL_VALUE,Caption); // Поле ввода для "горячей клавиши" rdsFORMAddEdit(window,0,2,RDS_FORMCTRL_HOTKEY, "Клавиша:",150); rdsSetObjectInt(window,2,RDS_FORMVAL_VALUE,Key); rdsSetObjectInt(window,2,RDS_FORMVAL_HKSHIFTS,KeyShifts); // Открытие окна ok=rdsFORMShowModalEx(window,NULL); if(ok) { // Нажата кнопка OK – запись параметров в блок rdsFree(Caption); // Уничтожение старой строки // Создание динамической копии введенной строки Caption=rdsDynStrCopy(rdsGetObjectStr(window,1, RDS_FORMVAL_VALUE)); // Чтение параметров клавиши Key=rdsGetObjectInt(window,2,RDS_FORMVAL_VALUE); KeyShifts=rdsGetObjectInt(window,2,RDS_FORMVAL_HKSHIFTS); // Создание пункта меню на основе изменившихся параметров RegisterMenuItem(); } // Уничтожение окна rdsDeleteObject(window); // Возвращаемое значение return ok?RDS_BFR_MODIFIED:RDS_BFR_DONE; } //========================================= // Блок, открывающий окно родительской подсистемы extern "C" __declspec(dllexport) int RDSCALL OpenSysWin(int CallMode, RDS_PBLOCKDATA BlockData, LPVOID ExtParam) { // Указатель на личную область данных блока,приведенный к // правильному типу TOpenSysWinData *data=(TOpenSysWinData*)(BlockData->BlockData); switch(CallMode) { case RDS_BFM_INIT: // Инициализация BlockData->BlockData=data=new TOpenSysWinData(); 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_MENUFUNCTION:// Выбор пункта меню rdsOpenSystemWindow(BlockData->Parent); break; } return RDS_BFR_DONE; } //=========================================