Программный интерфейс плагинов приложения «LoggerXP» (описание) Версия интерфейса 5.1 Copyright © 2003 – 2010 Сокольский Р.Н. Общие сведения Приложение «LoggerXP» имеет программный интерфейс (API), через который оно способно взаимодействовать с плагинами (вернее бы сказать: плагины имеют этот API). В данном случае плагин – это обычная DLL, но имеющая в названии файла расширение «.lop» (logger plugin). При этом сам плагин должен экспортировать пять обязательных функций (процедур): RoexGetVersion, RoexGetInfo, RoexRun, RoexRelease, RoexSendNotify и одну необязательную: RoexShowOptionsDialog. В основе взаимодействия приложения с плагинами лежат несколько интерфейсов с определёнными идентификаторами GUID. Следует отметить, что это не имеет ни какого отношения к технологии COM. Благодаря использованию интерфейсов становиться возможным непосредственно из плагина обращаться к методам и компонентам форм, источникам данных и т.д.. Приложение «LoggerXP» написано в среде программирования (IDE) «Delphi 7». Все плагины лично мной также были написаны в этой IDE. Тестирование плагинов написанных в старших или младших версиях Delphi не производилось. В разделе uses файла проекта плагина первым должен быть подключён модуль ShareMem. Пример показан ниже. library QRZcom; uses ShareMem, {…остальные модули }; {$E lop} {$R *.res} exports RoexGetVersion, RoexGetInfo, RoexRun, RoexSendNotify, RoexRelease, RoexShowOptionsDialog; begin end. Экспортируемые плагинами процедуры и функции И так. Каждый плагин должен иметь ряд экспортируемых процедур и функций, через которые и происходит «общение» приложения с плагином (а вот «общение» плагина с приложением, как уже было сказано выше, осуществляется через интерфейсы). Рассмотрим эти процедуры и функции. После того, как плагин загружен приложением в память вызывается процедура: procedure RoexGetInfo(PlugInfo: PPlugInfo); stdcall; В параметре PlugInfo передаётся указатель на структуру TPlugInfo. Эта структура объявлена следующим образом: { Структура информации о плагине } PPlugInfo = ^TPlugInfo; TPlugInfo = packed record lpName : PChar; // имя плагина lpCopyright: PChar; // авторские права lpDescript : PChar; // описание плагина bGUI : Boolean; // True, если плагин должен загружаться только по команде меню end; Здесь: lpName – имя плагина, которое будет отображаться в меню, в окне управления плагинами приложения и в окне «О плагине…»; lpCopyright – авторские права отображаемые в окне «О плагине…»; lpDescript – краткое описание плагина отображаемое в окне «О плагине…»; bGUI – если плагин должен загружаться по команде меню (пользователем), то это значение должно быть True. Имя плагина в данном случае будет помещено в меню «Плагины» главного окна приложения. Если это значение False, то плагин будет загружаться автоматически во время загрузки приложения. При этом имя плагина в меню не помещается. Далее идёт вызов функции: function RoexGetVersion: Integer; stdcall; Она должна возвращать константу с минимальным номером версии API, на которую рассчитан плагин: PLUG_VERSION = 51; // версия интерфейса плагина Я оставляю за собой право увеличивать это значение по мере усовершенствования интерфейсов (добавление в них новых процедур функций и т.д.). Функция function RoexRun(PlugData: PPlugData; const hHandle: THandle): THandle; stdcall; вызывается приложением при запуске плагина на выполнение. В теле этой функции могут создаваться экземпляры форм, классов, выделяться ссылки и т.д. Функция имеет два параметра: PlugData – указатель на структуру TPlugData; hHandle – хэндл загруженного приложением плагина . Этот параметр передаётся из приложения в плагин и будет нужен для целей описанных ниже. Если в теле этой функции создаётся экземпляр главной формы плагина, то она должна обязательно возвращать хэндл этой формы. Иначе – 0. Например, в плагине пишем: function RoexRun(PlugData: PPlugData; const hHandle: THandle): THandle; stdcall; begin Result := 0; hPlugin := hHandle; if bIsRun then Exit; hOldApp := Application.Handle; Application.Handle := TApplication(PlugData^.MainForm.Application).Handle; MainForm := TMainForm.CreateParented(Application.Handle); Result := MainForm.Handle; bIsRun := True; end; Если форма не является модальной и вы желаете сделать её непотопляемой (т.е. она должна быть всегда поверх главного главного окна приложения), то для формы необходимо переопределить метод CreateParams. procedure TMainForm.CreateParams(var Params: TCreateParams); begin inherited; { Форма всегда поверх родительской. } with Params do WndParent := hParent; end; Здесь hParent := TForm(PlugData^.MainForm.Form).Handle; Так как созданная форма плагина не добавляется в объект TScreen, то при сворачивании главного окна приложения эта форма остаётся на экране монитора. Чтобы решить эту проблему в приложении был создан специальный менеджер управления окнами. Именно через функцию RoexRun хэндл формы плагина добавляется в этот менеджер. Если форма после своего закрытия не уничтожается, а просто скрывается то, чтобы она не отображалась вновь при разворачивании главного окна приложения (если оно было ранее свёрнуто на панель задач) в конструкторе Create формы всегда следует писать: procedure TMainForm.FormCreate(Sender: TObject); begin SetProp(Handle, PChar(RX_WS), 1); end; Здесь RX_WS: String = '{8E5FED65-0336-4379-92FD-0E509B91320F}'; То же самое следует писать и в обработчиках событий FormShow, FormClose или FormHide: procedure TMainForm.FormShow(Sender: TObject); begin SetProp(Handle, PChar(RX_WS), 2); end; В данном случае константа 2 показывает, что форма отображена на экране. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin SetProp(Handle, PChar(RX_WS), 1); end; Никогда не вызывайте для экземпляра главной плагина формы метод Free, если только форма не модальная. Это должно делаться только в процедуре RoexRelease, описанной ниже. Если всё-таки нужно уничтожить экземпляр формы при её закрытии, то в обработчике события FormClose следует написать: { Посылаем сообщение родительскому окну о необходимости очистить память. При этом, будет вызвана процедура RoexRelease. } PostMessage(hParent, RX_RELEASE, Integer(RX_WPARAM), Integer(hPlugin)); Здесь: RX_RELEASE RX_WPARAM: String = WM_USER + 132; = '{03B9C4A7-74B5-4657-A887-F6F4B031168F}'; При этом процедура RoexRelease будет вызвана автоматически. Процедура procedure RoexRelease; stdcall; вызывается приложением перед выгрузкой плагина. В теле этой процедуры можно освобождать выделенную ранее (в теле функции RoexRun) память и т.д. Функция function RoexSendNotify(const wMess, wParam: Word): WordBool; stdcall; вызывается приложением, чтобы передать плагину какое-то событие. Возвращаемый результат этой функции может обрабатываться приложением. Если он имеет значение True, то плагин может перекрыть некоторые функции приложения (в основном команды меню) и взять управление «на себя». Функция имеет два параметра передаваемых приложением: wMess – тип сообщения. Может принимать одну из следующих констант: SN_NONE SN_NOTIFY SN_FORMCREATE SN_FORMDESTROY SN_CLICKMENUFORM = 0; = 1; = 2; = 3; = 4; // нет события // событие (код события при этом в параметре wParam) // создание интерфейсной формы // удаление интерфейсной формы // щелчёк по кнопке меню Если wMess равен SN_FORMCREATE или SN_FORMDESTROY, то параметр wParam имеет одно из следующих значений: SNP_NEWQSOFORM SNP_DXCLFORM = 1; = 2; // окно "новое QSO" // окно "DX-кластер" SNP_CWFORM SNP_CALLBOOKFORM SNP_SENDSPOTFORM SNP_AWARDSFORM SNP_QSLVIAFORM SNP_AUDIOCENTERFORM SNP_ANTENNASFORM SNP_MAPFORM SNP_QSLPRINTFORM SNP_AWSTFORM SNP_PREFLISTFORM = 3; = 4; = 5; = 6; = 7; = 8; = 9; = 10; = 11; = 12; = 13; // окно "Телеграф" // окно "база данных позывных" // окно "Передать спот" // окно "Дипломы" // окно "QSL-менеджеры" // окно "Аудиоцентр" // окно "Управление антеннами" // окно "Карты" // окно "Печать QSL" // окно "Статистика по дипломам" // окно "База данных префиксов" Например, если вам нужно отловить момент создания формы «Новое QSO», то нужно написать: function RoexSendNotify(const wMess, wParam: Word): WordBool; stdcall; begin Result := False; if (wMess = SN_FORMCREATE) and (wParam = SNP_NEWQSOFORM) then begin // Здесь что-то с этим делаем //… end; end; С параметром wMess равным SN_CLICKMENUFORM передаётся одно из следующих значений wParam: SNP_IMPORT SNP_EXPORT SNP_EDITFORM SNP_DOCPROPFORM SNP_PREVIEWFORM SNP_DXCCSTATFORM SNP_MAPSFORM SNP_SHOWTOMAP SNP_SEARCHINCLBK SNP_REFRESHQSOINFO "Новое QSO" SNP_AWARDVIEWFORM программ" SNP_DXCLUSTERCONN SNP_DXCLUSTERDISCONN SNP_DCCLUSTEREDIT SNP_SENDALLTOEQSL SNP_SENDSELTOEQSL = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; // команда меню "Импорт данных" // команда меню "Экспорт данных" // команда меню "Редактирование" // команда меню "Свойства документа" // команда меню "Предварительный просмотр" // команда меню "Статистика по странам" // команда меню "Карты" // команда меню "Показать на карте" // команда меню "Найти в колбуках" // команда меню "Обновление информации о позывном" в окне = 24; // команда меню "Просмотр редактирование дипломных = 25; = 26; = 27; = 28; = 29; // нажатие кнопки подключения к кластеру // нажатие кнопки отключения от кластера // редактирование списка кластеров // отправить все QSO на eQSL // отправить только выбранные QSO на eQSL В этом случае из функции RoexSendNotify вы можете возвратить True, чтобы перехватить управление на себя. Например, в плагине пишем: function RoexSendNotify(const wMess, wParam: Word): WordBool; stdcall; begin Result := False; if (wMess = SN_CLICKMENUFORM) and (wParam = SNP_EXPORT) then begin Result := True; // Здесь показываем своё окно для экспорта данных //… end; end; С пареметром wMess равным SN_NOTIFY передаётся одно из следующих значений wParam: SNPN_ADDNEWQSO SNPN_TXRX SNPN_DXRSDSPOT SNPN_QSOREPEAT SNPN_CWSEND SNPN_SEARCHCALLBOOK SNPN_MAINTABS SNPN_NAMECHANGE SNPN_QTHCHANGE SNPN_CALLSIGNCHANGE SNPN_BANDCHANGE SNPN_MODECHANGE SNPN_RSTTCHANGE SNPN_RSTRCHANGE SNPN_QSLVIACHANGE SNPN_DATASETOPEN SNPN_DATASETCLOSE SNPN_DXSPOTTOQSOWND SNPN_AWARDSANALISER SNPN_DELETEQSO SNPN_DELETESELQSO SNPN_SETFREQ SNPN_CONFIGCHANGE SNPN_QSLVIASEARCH SNPN_OPENDOCUMENT SNPN_SAVEDOCUMENT SNPN_UNIONLOGS SNPN_ERRUNIONLOGS SNPN_DELETELOG SNPN_ERRDELETELOG SNPN_MAPSTABS SNPN_CALLBOOKTABS SNPN_DXCLASTERTABS SNPN_EXITCALLFLD SNPN_VIEWTOMAP SNPN_FILLAWARD SNPN_CREATABACKUP SNPN_DXCLUSTERCONFCHG SNPN_DXSENDSPOT SNPN_DXCLEARSPOTS = 4; = 5; = 6; = 7; = 8; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; // добавление в журнал новой записи // переключение приём/передача // получение спота из DX-кластера // проверка повторов // передача CW // поиск в колбуках // переключение закладок в главном окне // ввод имени // ввод QTH // ввод позывного // смена диапазона // смена вида модуляции // ввод рапорта // ввод рапорта // ввод QSL-менеджера в окно "Новое QSO" // DataSet AfterOpen // DataSet AfterClose // перенос спота в окно "Новое QSO" // анализ дипломных программ для нового QSO // удаление одного QSO // удаление нескольких выбранных QSO // установка частоты // изменение настроек приложения // поиск QSL - менеджера в окне "QSL - менеджеры" // открытие документа // сохранение документа // объединение журналов // ошибка объединения журналов // удаление журнала // ошибка удаления журнала // щелчок по закладкам окна "Карты" // щелчок по закладкам окна "База данных позывных" // щелчок по закладкам окна "DX-кластер" // выход курсора из поля "Позывной" окна "Новое QSO" // запрос положения на карте // начало автозаполнения дипломной программы // создание резервной копии журнала // изменение настроек кластера // передача спота // очистка принятых спотов Есть ещё одна необязательная процедура: procedure RoexShowOptionsDialog(const hHwnd: THandle); stdcall; Она должна присутствовать в плагине, если необходимо в нём иметь окно с опциями (настройками). Например: procedure RoexShowOptionsDialog(const hHwnd: THandle); begin with TOptionForm.CreateParented(hHwnd) do try ShowModal; finally Free; end; end; Интерфейсы Теперь рассмотрим более подробно структуру TPlugData передаваемую в параметре функции RoexRun. Все члены структуры являются интерфейсами, через которые и происходит взаимодействие плагина с приложением. Как уже было сказано выше, это позволяет иметь полное или частичное (ограниченное тем или иным интерфейсом) взаимодействие плагина с формами и компонентами приложения. Структура TPlugData объявлена следующим образом: PPlugData = ^TPlugData; TPlugData = packed record Config : IConfig; Document : IDocument; ExData : IExData; Logs : ILogs; Repiats : IRepiats; Transceiver : ITransceiver; MainForm : IMainForm; NewQSOForm : INewQSOForm; DxClusterForm: IDxClusterForm; SendSpotForm : ISendSpotForm; CWForm : ICWForm; CallBookForm : ICallBookForm; QSLViaForm : IQSLViaForm; AwardsForm : IAwardsForm; MapsForm : IMapsForm; QSLPrintForm : IQSLPrintForm; AntennasForm : IAntennasForm; end; Перед использованием каждого члена данной структуры он должен быть предварительно проверен на nil! Интерфейс IConfig Интерфейс IConfig предназначен для доступа к конфигурации (настройкам) приложения. Все свойства интерфейса в основном имеют права только на чтение. Интерфейс объявлен следующим образом: IConfig = interface ['{164ECBD2-DFE9-40B1-9C07-F14E7374B935}'] function GetBandIndex: Integer; function GetModeIndex: Integer; procedure SetBandIndex(const Value: Integer); procedure SetModeIndex(const Value: integer); function GetBandName: String; function GetModeName: String; function GetConfigPath: String; function GetProfilePath: String; function GetPluginsDataPath: String; function GetUserLat: Double; procedure SetUserLat(const Value: Double); function GetUserLong: Double; procedure SetUserLong(const Value: Double); property BandIndex: Integer read GetBandIndex write SetBandIndex; property ModeIndex: Integer read GetModeIndex write SetModeIndex; property BandName: String read GetBandName; property ModeName: String read GetModeName; property ProfilePath: String read GetProfilePath; property ConfigPath: String read GetConfigPath; property PluginsDataPath: String read GetPluginsDataPath; property UserLat: Double read GetUserLat write SetUserLat; property UserLong: Double read GetUserLong write SetUserLong; function GetInsertColor: TColor; function GetSelectedColor: TColor; property InsertColor: TColor read GetInsertColor; property SelectedColor: TColor read GetSelectedColor; function GetFontColor: TColor; function GetFontName: TFontName; function GetFontSize: Integer; function GetFontStyle: TFontStyles; property FontName: TFontName read GetFontName; property FontSize: Integer read GetFontSize; property FontStyle: TFontStyles read GetFontStyle; property FontColor: TColor read GetFontColor; function GetToolbarStyle: Integer; property ToolbarStyle: Integer read GetToolbarStyle; function GetImageStyle: String; property ImageStyle: String read GetImageStyle; function GeteQSLLogin: String; property eQSLLogin: String read GeteQSLLogin; function GeteQSLPSW: String; property eQSLPSW: String read GeteQSLPSW; function GeteQSLProxyHost: String; property eQSLProxyHost: String read GeteQSLProxyHost; function GeteQSLProxyPort: Integer; property eQSLProxyPort: Integer read GeteQSLProxyPort; function GeteQSLProxyLogin: String; property eQSLProxyLogin: String read GeteQSLProxyLogin; function GeteQSLProxyPsw: String; property eQSLProxyPsw: String read GeteQSLProxyPsw; function GeteQSLProxyEnable: Boolean; property eQQSProxyEnable: Boolean read GeteQSLProxyEnable; function GeteQSLReadTimeout: Integer; property eQSLReadTimeout: Integer read GeteQSLReadTimeout; function GetProxyBasicAuthentication: Boolean; property ProxyBasicAuthentication: Boolean read GetProxyBasicAuthentication; function GetGQSLLogin: String; property GQSLLogin: String read GetGQSLLogin; function GetGQSLPSW: String; property GQSLPSW: String read GetGQSLPSW; function GetGQSLReadTimeout: Integer; property GQSLReadTimeout: Integer read GetGQSLReadTimeout; function GetPluginsInterfaceVersion: Integer; function GetInternalExplorer: Boolean; property InternalExplorer: Boolean read GetInternalExplorer; function GetInternalMailClient: Boolean; property InternalMailClient: Boolean read GetInternalMailClient; function SaveConfig: Boolean; end; BandIndex ModeIndex BandName ModeName ProfilePath ConfigPath PluginsDataPath UserLat UserLong InsertColor SelectedColor FontName FontSize FontStyle FontColor ToolbarStyle ImageStyle eQSLLogin eQSLPSW eQSLProxyHost eQSLProxyPort eQSLProxyLogin eQSLProxyPsw Текущий индекс диапазона. Индекс изменяется при смене диапазона в окне «Новое QSO» или через CAT. Текущий индекс вида модуляции. Индекс изменяется при смене вида модуляции в окне «Новое QSO» или через CAT. Текущее имя диапазона (например, 1.8 МГц). Имя изменяется при смене диапазона в окне «Новое QSO» или через CAT. Текущее имя вида модуляции (например, SSB). Имя изменяется при смене вида модуляции в окне «Новое QSO» или через CAT. Путь к текущему профилю пользователя. Например, c:\Documents and Settings\Admin\Application Data\RS SoftX\loggerxp\Profiles\{E6596DAF55B2-45CE-9F86-28BFF990A084} Путь к корневой папке конфигурации приложения. Например, c:\Documents and Settings\Admin\Application Data\RS SoftX\loggerxp Путь к папке конфигурации и данных плагинов. Например, c:\Documents and Settings\Admin\Application Data\RS SoftX\loggerxp\Plugins Data Географическая широта пользователя, заданная по умолчанию в редакторе настроек. Географическая долгота пользователя, заданная по умолчанию в редакторе настроек. Цвет выбранных записей таблиц. Цвет отмеченных QSO главной таблицы приложения. Имя шрифта таблиц. Размер шрифта таблиц. Стиль шрифта таблиц. Цвет шрифта таблиц. Стиль меню и панелей. Имя темы кнопок (изображений на них). Логин для доступа к eQSL. Хранится в зашифрованном виде с использованием 96-битного шифрования. Пароль для доступа к eQSL. Хранится в зашифрованном виде с использованием 96-битного шифрования. Имя хоста прокси – сервера. Данное название свойства оставлено из-за соображения совместимости с предыдущими версиями когда прокси – сервер использовался только для eQSL. Номер порта прокси – сервера. Данное название свойства оставлено из-за соображения совместимости с предыдущими версиями когда прокси – сервер использовался только для eQSL. Логин для доступа к прокси – серверу. Хранится в зашифрованном виде с использованием 96-битного шифрования. Данное название свойства оставлено из-за соображения совместимости с предыдущими версиями когда прокси – сервер использовался только для eQSL. Пароль для доступа к прокси – серверу. Хранится в зашифрованном виде с использованием 96-битного шифрования. Данное название свойства eQQSProxyEnable eQSLReadTimeout ProxyBasicAuthentication GQSLLogin GQSLPSW GQSLReadTimeout InternalExplorer GetPluginsInterfaceVersion InternalMailClient SaveConfig оставлено из-за соображения совместимости с предыдущими версиями когда прокси – сервер использовался только для eQSL. Используется ли к прокси – сервер или нет. Данное название свойства оставлено из-за соображения совместимости с предыдущими версиями когда прокси – сервер использовался только для eQSL. Время ожидания данных с eQSL. Прокси – сервер требует логин и пароль. Логин для доступа к Gold QSL. Хранится в зашифрованном виде с использованием 96-битного шифрования. Пароль для доступа к Gold QSL. Хранится в зашифрованном виде с использованием 96-битного шифрования. Время ожидания данных с Gold QSL. Если True, то используется внутренний Интернет – браузер. Функция возвращает текущий номер программного интерфейса Если True, то используется внутренний почтовый клиент. Процедура сохраняет конфигурацию. Интерфейс IRoexForm Все формы приложения описанные структурой TPlugData наследуют этот интерфейс. IRoexForm = interface ['{8271DA52-7186-4CDF-A47B-B7401CF3EA30}'] function GetForm: Pointer; { TForm } property Form: Pointer read GetForm; end; Свойство GetForm возвращает указатель на саму форму. Используется, например, так: if pPlugData^.DxClusterForm <> nil then TForm(pPlugData^.DxClusterForm).Form.Caption := ‘Это работает плагин’; Интерфейс ITab Формы приложения описанные структурой TPlugData и способные создавать закладки (например, MainForm, MapForm, DXClusterForm и др.) наследуют этот интерфейс. ITab = interface(IRoexForm) ['{303100F1-F0B7-45E8-ABB9-492C778B6DC7}'] function GetTabIndex: Integer; function CreateTab(const ACaption: String; const PlugHandle: THandle): THandle; procedure DeleteTab(const Hndl: THandle); procedure ShowTabImage(const Hndl: THandle; const ShowImage: Boolean); { TCustomControl } function GetTab: Pointer; property TabIndex: Integer read GetTabIndex; procedure SetActiveTab(const Hndl: THandle); function GetTabOfHandle(const Hndl: THandle): Pointer; end; Свойство TabIndex возвращает индекс текущей активной закладки. Для первой закладки – это ноль. Функция CreateTab создаёт новую закладку. Здесь: ACaption – текст заголовка закладки; PlugHandle – хэндл плагина создающего закладку. Этот параметр используется только в том случае, если закладка создаётся у главного окна приложения. Функция CreateTab возвращает хэндл только, что созданной закладки. Далее значение возвращённое этой функцией должно быть использовано при вызове DeleteTab (удаляет закладку), ShowTabImage (показывает изображение в заголовке (только для окна CallBookForm)), SetActiveTab (устанавливает активную закладку, если ноль, то это первая закладка), GetTabOfHandle (возвращает указатель типа TCustomControl на закладку с данным хэндлом). Функция GetTab возвращает указатель типа TCustomControl на текущую активную закладку. Интерфейс IMainForm Данный интерфейс позволяет получить доступ к главной форме приложения, к объектам TApplication, TScreen и к другим объектам и компонентам этой формы. IMainForm = interface(ITab) ['{E91BB80E-E0F6-4A13-8107-449C8F5120D1}'] function GetApplication: Pointer; function GetScreen: Pointer; function GetCurrentDBGrid: Pointer; function GetRepiatDBGrid: Pointer; function GetStatusBarText(const Index: Integer): String; function GetMenu: Pointer; procedure SetStatusBarText(const Index: Integer; const Value: String); { TApplication } property Application: Pointer read GetApplication; { TScreen } property Screen: Pointer read GetScreen; { TDBGrid } property CurrentDBGrid: Pointer read GetCurrentDBGrid; { TDBGrid } property RepiatDBGrid: Pointer read GetRepiatDBGrid; { TStrings } property Menu: Pointer read GetMenu; function AddStatusBarPanel(const AWidth: Integer; const AText: String): Integer; procedure DeleteStatusBarPanel(const Index: Integer); function GetConnection: Pointer; function GetCurrentDataSet: Pointer; { TADOConnection } property Connection: Pointer read GetConnection; { TDataSet } property CurrentDataSet: Pointer read GetCurrentDataSet; procedure DataFormsConnected(const Connected: Boolean); { TClientDataSet} function GetReportDataSet: Pointer; property ReportDataSet: Pointer read GetReportDataSet; procedure ViewFilterStatus; procedure ViewRecordCount; procedure EQSLConfirmNew; procedure EQSLConfirmAll; procedure ShowMCHint(const Text: String); procedure CreateBackupDataBase; end; SetStatusBarText Application Screen CurrentDBGrid RepiatDBGrid Menu AddStatusBarPanel DeleteStatusBarPanel Connection CurrentDataSet DataFormsConnected ReportDataSet ViewFilterStatus ViewRecordCount EQSLConfirmNew EQSLConfirmAll ShowMCHint CreateBackupDataBase Процедура выводит текст на панель с индексом Index строки состояния. Указатель на объект T Application. Указатель на объект TScreen. Свойство возвращает указатель на текущую таблицу Свойство возвращает указатель на таблицу повторных QSO Свойство возвращает указатель типа TStrings. Будет рассмотрено ниже. Функция добавляет новую панель в строку состояния. В настоящий момент не реализована. Процедура удаляет панель из строки состояния. В настоящий момент не реализована. Указатель на компонент TADOConnection. Указатель на объект TDataSet. Возвращает текущий DataSet, в зависимости от текущего документа: журнал или архив. Если Connected = False, то процедура отключает всех потребителей от источника данных. Указатель возвращает TClientDataSet отчёта. Процедура выводит текущий статус фильтра в строку состояния. Процедура выводит количество записей в строку состояния. Процедура запускает процесс подтверждения новых QSO имеющихся на eQSL. Процедура запускает процесс подтверждения всех QSO имеющихся на eQSL. Процедура отображает всплывающее сообщение в системном трее Windows. В настоящий момент не реализована. Процедура запускает мастер резервной копии базы данных или создаёт резервную копию данных, если в настройках приложения включена опция автоматического создания резервной копии. Как уже было сказано, интерфейс имеет свойство Menu в виде указателя на объект TStrings. Это свойство имеется также в интерфейсе IDxClusterForm. По сути дела это список команд создаваемых плагинами в меню «Плагины» главного окна приложения и контекстного меню. Пример создания пункта меню (команды) показан ниже. const RX_COMMAND_NAME = ‘Это команда меню созданного плагином’; var sCommandName: String = RX_COMMAND_NAME; procedure CreateMenu; var i, iCount: Integer; begin { Создаём пункт меню, при этом проверяем его уникальность. Если такое имя уже есть, то к немуу добавляем цифру и проверяем вновь. } if pPlugData^.MainForm <> nil then with TStrings(pPlugData^.MainForm.Menu) do begin iCount := Count - 1; for i := 0 to iCount do if AnsiSameText(TStrings(pPlugData^.MainForm.Menu)[i], sCommandName) then sCommandName := RX_COMMAND_NAME + ' ' + IntToStr(i + 1); TStrings(pPlugData^.MainForm.Menu).Add(sCommandName); end; end; Когда пользователь в приложении выбирает команду меню с именем RX_COMMAND_NAME, то всем плагинам посылается сообщение RX_COMMAND. При этом переменная Message. WParam будет содержать значение RX_COMMAND_NAME. Чтобы другие плагины не реагировали на эту команду, значение RX_COMMAND_NAME должно быть уникальным. Как раз уникальность и проверяется в выше приведённом примере. Если команда меню создана, то её необходимо и обрабатывать. Сообщение RX_COMMAND должно обрабатываться только в форме. При этом форма должна быть постоянно создана, но показывать её не обязательно. В разделе private формы следует определить обработчик сообщения: procedure RXCommand(var Message: TMessage); message RX_COMMAND; Здесь RX_COMMAND = WM_USER + 134; Далее в теле процедуры пишем: procedure TMainForm.RXCommand(var Message: TMessage); begin with Message do if String(WParam) = sCommandName then { Здесь что-то делаем… }; end; Когда плагин выгружается, созданную команду меню следует удалять: procedure DeleteMenu; begin { Удаляем себя из меню. } if pPlugData^.MainForm <> nil then with TStrings(pPlugData^.MainForm.Menu) do Delete(IndexOf(sCommandName)); end; Интерфейс IDocument Интерфейс позволяет осуществлять доступ к некоторым свойствам текущего документа (журнал, архив, отчёт) и к компонентам TOpenDialog, TSaveDialog. IDocument = interface ['{5C9FAF21-D72F-46D9-ABAE-112AD6566634}'] { TOpenDialog } function GetOpenDocumentDialog: Pointer; property OpenDocumentDialog: Pointer read GetOpenDocumentDialog; { TSaveDialog } function GetSaveDocumentDialog: Pointer; property SaveDocumentDialog: Pointer read GetSaveDocumentDialog; function GetDocPath: String; property DocPath: String read GetDocPath; function GetDocType: TDocType; function GetCurrentDocName: String; end; Свойство DocPath возвращает путь к файлу текущего документа. Если это журнал, то DocPath = ‘’. Функция GetDocType возвращает тип текущего документа. TDocType = (dtLog, dtArchive, dtReport, dtOther); И последняя функция GetCurrentDocName возвращает имя текущего документа. Интерфейс INewQSOForm Интерфейс позволяет осуществить доступ к окну «Новое QSO». Назначение свойств вполне понятно из объявления интерфейса. Процедура SetVisible управляет видимостью формы без генерации событий OnHide и OnShow. INewQSOForm = interface(IRoexForm) ['{ED48A729-418D-4DF0-8BEC-B54EE6F3772E}'] function GetBandField: Pointer; function GetModeField: Pointer; function GetCallsignField: Pointer; function GetQTHField: Pointer; function GetNameField: Pointer; function GetRSTTField: Pointer; function GetRSTRField: Pointer; function GetQSLViaField: Pointer; procedure SetVisible(const Value: Boolean); { TComboBox } property BandField: Pointer read GetBandField; { TComboBox } property ModeField: Pointer read GetModeField; { TEdit } property CallsignField: Pointer read GetCallsignField; { TComboBox } property QTHField: Pointer read GetQTHField; { TComboBox } property NameField: Pointer read GetNameField; { TEdit } property RSTTField: Pointer read GetRSTTField; { TEdit } property RSTRField: Pointer read GetRSTRField; { TEdit } property QSLViaField: Pointer read GetQSLViaField; { TEdit } function GetQTHLocField: Pointer; property QTHLocField: Pointer read GetQTHLocField; end; Интерфейс IExData Интерфейс позволяет осуществлять доступ к дополнительным источникам данных приложения таким как, список префиксов, список регулярных выражений префиксов, список QSL-менеджеров и QSL-бюро. Кроме того имеет процедуры, свойства и функции облегчающие работу с этим интерфейсом. IExData = interface ['{873F0EF0-C556-4878-964D-DD870BAAA4BD}'] function GetConnection: Pointer; function GetPrefixesDataSet: Pointer; function GetRegExpDataSet: Pointer; function GetQSLViaDataSet: Pointer; function GetQSLBuroDataSet: Pointer; function GetFreqModeMapDataSet: Pointer; function GetTimeZone: Double; function GetQSLVia(Callsign: String): String; function GetQSLBuro(Callsign: String): String; function GetFreqModeMap(const Freq: Integer; out Mode, Band: String): Boolean; { TADOConnection } property Connection: Pointer read GetConnection; { TADOQuery } property PrefixesDataSet: Pointer read GetPrefixesDataSet; { TADOQuery } property RegExpDataSet: Pointer read GetRegExpDataSet; { TADOQuery } property QSLViaDataSet: Pointer read GetQSLViaDataSet; { TADOQuery } property QSLBuroDataSet: Pointer read GetQSLBuroDataSet; { TADOQuery } property FreqModeMapDataSet: Pointer read GetFreqModeMapDataSet; property TimeZone: Double read GetTimeZone; function AddNewQSLVia(Callsign, Manager: String; Note: String = ''; ShowException: Boolean = True): Boolean; function GetCurrentStdCallsign: String; property CurrentStdCallsign: String read GetCurrentStdCallsign; function GetCallsignInfo(Callsign: String; var IsFind: Boolean; const ShortMode: Boolean = False): TCallsignInfo; overload; function GetCallsignInfo(Callsign: String; QSODate: TDateTime; var IsFind: Boolean; const ShortMode: Boolean = False): TCallsignInfo; overload; procedure ShowDataEditor(DataSet: Pointer); end; GetQSLVia GetQSLBuro GetFreqModeMap Connection PrefixesDataSet RegExpDataSet QSLViaDataSet QSLBuroDataSet FreqModeMapDataSet TimeZone AddNewQSLVia CurrentStdCallsign GetCallsignInfo ShowDataEditor Функция возвращает позывной QSL-менеджера для позывного Callsign. Функция возвращает адрес QSL-бюро для позывного Callsign. Функция в параметрах Mode и Band возвращает вид модуляции и название диапазона для частоты Freq согласно сетке распределения частот и видов модуляций. Указатель на объект типа TADOConnection, который подключён к базе данных dataex.mdb. Указатель на объект типа TADOQuery – список префиксов стран. Указатель на объект типа TADOQuery – список регулярных выражений для префиксов стран. Указатель на объект типа TADOQuery – список QSL-менеджеров. Указатель на объект типа TADOQuery – список QSL-бюро. Указатель на объект типа TADOQuery – сетка частот и видов модуляций. Временная зона для текущего позывного, для которого получается информация. Функция добавляет QSL-менеджера для позывного Callsign. Если параметр Manager = ‘’, то менеджер для этого позывного удаляется. Текущий позывной, для которого получается информация. При этом префикс позывного заменяется на DXCC-префикс. Например, RA3GBV будет заменён на UA3GBV. Функция возвращает информацию о позывном. Структура TCallsignInfo описана ниже. Если параметр ShortMode = True, то возвращаются только основные данные (DXCC, Континент). Процедура отображает редактор данных. В параметре DataSet передаётся указатель на редактируемый объект типа TDataSet. { Информация о позывном } TCallsignInfo = record dLat, dLong: Double; // широта и долгота корреспондента dBearing : Double; // азимут корреспондента dTimeZone : Double; // часовой пояс корресапондента sTerritory : String; // название территории sITU, sCQ : String; // зоны sDXCC : String; // префикс DXCC sContinent : String; // континент sDistance : String; // расстояние до корреспондента sManager : String; // QSL- менеджер корреспондента sGrid : String; // QTH - локатор end; Интерфейс ILogs Интерфейс позволяет читать имена таблиц журналов, имена журналов. Осуществляет доступ к DataSet текущего журнала (через свойство CurrentLog). ILogs = interface ['{CC0BD663-A983-4320-A79A-D849EC36424B}'] { TStrings } function GetTables: Pointer; function GetCurrentTableName: String; function GetCurrentLog: Pointer; property CurrentTableName: String read GetCurrentTableName; { TADOQuery } property CurrentLog: Pointer read GetCurrentLog; procedure ContinentAndDXCCRepiat(const Continent, DXCC: String; const AllLogs: Boolean; out Result1, Result2: Boolean); procedure UpdateContinentDXCCRepiat; end; Функция GetTables возвращает указатель на объект типа TStrings, в котором находятся имена всех таблиц журналов. Процедура ContinentAndDXCCRepiat позволяет проверять континент и DXCC на повтор. Процедура UpdateContinentDXCCRepiat обновляет данные о повторах по континентам и DXCC. Интерфейс IRepiats Интерфейс позволяет осуществлять доступ к данным о повторных QSO. При помощи функции InstallRepeatFilter можно проверить позывной на повтор. При этом информация отобразиться в таблице повторных QSO главного окна приложения. Процедура Clear очищает эту таблицу. IRepiats = interface ['{790046B9-392E-47AE-9303-2D6155A291FD}'] function GetDataSet: Pointer; { TADOQuery } property DataSet: Pointer read GetDataSet; function InstallRepeatFilter(const TableName, ID, Callsign: String; NotOne, AllLogs: Boolean): Boolean; procedure Clear; end; Интерфейс IDxClusterForm Интерфейс позволяет осуществлять доступ к данным и компонентам окна «DX-кластер». IDxClusterForm = interface(ITab) ['{E0BEF533-518B-4E26-A724-6A2B3254ACF9}'] { TMemo } function GetTerminal: Pointer; property Terminal: Pointer read GetTerminal; { TIdTelnet } function GetIdTelnet: Pointer; property IdTelnet: Pointer read GetIdTelnet; { TDBGrid } function GetDBGrid: Pointer; property DBGrid: Pointer read GetDBGrid; { TClientDataSet } function GetDataSet: Pointer; procedure SetDataSet(Value: Pointer); property DataSet: Pointer read GetDataSet write SetDataSet; { TStrings } function GetMenu: Pointer; property Menu: Pointer read GetMenu; { TStrings } function GetClusterList: Pointer; property ClusterList: Pointer read GetClusterList; function GetClusterItemIndex: Integer; property ClusterItemIndex: Integer read GetClusterItemIndex; function GetSpotsStopped: Boolean; property SpotsStopped: Boolean read GetSpotsStopped; function GetSendSpotData: String; property SendSpotData: String read GetSendSpotData; { Сообщение другим плагинам о приёме спота. } procedure SendSpotNotify; { Переместить спот в окно "Новое QSO" } procedure MoveSpot(Grid: Pointer); { Показать контекстное меню } procedure ShowPopupMenu; procedure ShowHiddedInfo(const Callsign: String; const Distance: Integer); function GetStatusBarText(const Index: Integer): String; procedure SetStatusBarText(const AText: String; const Index: Integer); { Опции кластера } function GetSelectedColor1: TColor; property _SelectedColor1: TColor read GetSelectedColor1; function GetSelectedColor2: TColor; property _SelectedColor2: TColor read GetSelectedColor2; function GetAutoConnectToCluster: Boolean; property _AutoConnectToCluster: Boolean read GetAutoConnectToCluster; function GetClusterAutoScroll: Boolean; property _ClusterAutoScroll: Boolean read GetClusterAutoScroll; function GetClusterNotCarryComment: Boolean; property _ClusterNotCarryComment: Boolean read GetClusterNotCarryComment; function GetClusterMarkCarrying: Boolean; property _ClusterMarkCarrying: Boolean read GetClusterMarkCarrying; function GetMaxDistance: Integer; property _MaxDistance: Integer read GetMaxDistance; function GetSelectedSpotByDistance: Boolean; property _SelectedSpotByDistance: Boolean read GetSelectedSpotByDistance; end; Terminal IdTelnet DBGrid DataSet Menu ClusterList ClusterItemIndex SpotsStopped Указатель на поле терминала TMemo. Указатель на компонент TIdTelnet. Указатель на таблицу принятых спотов. Указатель на компонент TClientDataSet. Указатель на объект TStrings – список команд меню. Работа с меню описана для интерфейса IMainForm. Указатель на объект TStrings – список доступных кластеров. Индекс выбранного кластера из списка кластеров ClusterList. True, если приём спотов остановлен. SendSpotData SendSpotNotify MoveSpot ShowPopupMenu ShowHiddedInfo GetStatusBarText SetStatusBarText _SelectedColor1 _SelectedColor2 _AutoConnectToCluster _ClusterAutoScroll _ClusterNotCarryComment _ClusterMarkCarrying _MaxDistance _SelectedSpotByDistance Содержит передаваемую в кластер информацию. Вызов этой процедуры сообщает всем плагинам, что принят очередной спот. Процедура перемещает спот из таблицы в окно «Новое QSO». Параметр Grid – это указатель на таблицу принятых спотов. Может быть nil, но в этом случае перемещённый спот не выделиться цветом, если эта опция включена в настройках. Отображает контекстное меню. Выводит информацию во всплывающем окне, если окно «DX-кластер» скрыто. Возвращает текст панели с индексом Index строки состояния. Index не может иметь значение более чем два. Задаёт текст панели с индексом Index строки состояния. Index не может иметь значение более чем два. Цвет выделенной строки при переносе спота в окно «Новое QSO». Цвет выделенной строки, если расстояние до DX больше заданного. True, если включена опция автоматического подключения к выбранному кластеру. True, если включена опция автопрокрутки принятых спотов в таблице. False, если запрещён перенос комментария при переносе спота в окно «Новое QSO». True, если включена опция выделения цветом спота в таблице при переносе его в окно «Новое QSO». Максимальное расстояние, свыше которого принятый спот следует выделять цветом. True, если в опциях разрешено выделять принятый спот при превышении максимального расстояния. Интерфейс ISendSpotForm Этот интерфейс позволяет осуществлять доступ к окну передачи спота в кластер и к его и компонентам. Имеет два свойства в виде указателей на компоненты TEdit. ISendSpotForm = interface(IRoexForm) ['{88927E51-1B4E-4D1E-8047-1723ADBBFB14}'] function GetFreqField: Pointer; function GetCommentField: Pointer; { TEdit } property FreqField: Pointer read GetFreqField; { TEdit } property CommentField: Pointer read GetCommentField; end; Интерфейс ITransceiver Интерфейс обеспечивает доступ к системе управления трансивером через CAT или PTT. Управление через CAT возможно в том случае, если установлен соответствующий плагин. ITransceiver = interface ['{EED75C00-F296-42CE-98E0-B70223D234AE}'] function GetTx: Boolean; procedure SetTx; procedure SetRx; property Tx: Boolean read GetTx; function GetFreq: Integer; procedure SetFreq(const Value: Integer); function GetOnFreqChange: TNotifyEvent; procedure SetOnFreqChange(Value: TNotifyEvent); property Freq: Integer read GetFreq write SetFreq; property OnFreqChange: TNotifyEvent read GetOnFreqChange write SetOnFreqChange; function GetPTTCW: Boolean; procedure SetPTTCW(const Value: Boolean); property PTTCW: Boolean read GetPTTCW write SetPTTCW; function GetPTTCWPin: Integer; procedure SetPTTCWPin(const Value: Integer); property PTTCWPin: Integer read GetPTTCWPin write SetPTTCWPin; function GetRigNumber: Integer; procedure SetRigNumber(const Value: Integer); property RigNumber: Integer read GetRigNumber write SetRigNumber; end; Tx SetTx SetRx Freq OnFreqChange PTTCW PTTCWPin RigNumber Если True, то трансивер в режиме передачи. Переводит трансивер на передачу. Переводит трансивер на приём. Текущая частота. Событие возникающее при смене частоты. Должна генерироваться CAT – плагином. Разрешает или запрещает CW-манипуляцию через один порт совместно с CAT. Номер ножки порта для передачи CW-манипуляции. Номер управляемого через CAT трансивера 1 или 2. Интерфейс ICWForm Интерфейс обеспечивает доступ к окну «CW». Свойство TextInputMemo возвращает указатель на компонент TMemo – поле ввода передаваемого текста. Процедура SendText передаёт текст заданный в параметре Text. Если передача текста завершена то CwDone = True. ICWForm = interface(IRoexForm) ['{7920EB5E-420C-481B-8DD7-560D53A37A7B}'] function GetCwDone: Boolean; function GetTextInputMemo: Pointer; procedure SendText(Text: String); property CwDone: Boolean read GetCwDone; { TMemo } property TextInputMemo: Pointer read GetTextInputMemo; end; Интерфейс ICallBookForm Интерфейс обеспечивает доступ к окну «База данных позывных» и к его компонентам. ICallBookForm = interface(ITab) ['{A8ED0729-B165-42AA-A40E-182B718D3ACF}'] function Find(const Callsign: String; out AName, QTH: String): Boolean; procedure SetResult(const Value: Boolean); procedure SetAName(const Value: String); procedure SetQTH(const Value: String); function GetResult: Boolean; function GetAName: String; function GetQTH: String; function GetCallsign: String; property Result: Boolean read GetResult write SetResult; property Name: String read GetAName write SetAName; property QTH: String read GetQTH write SetQTH; property Callsign: String read GetCallsign; end; Функция Find осуществляет поиск по всем имеющимся колбукам (основной и плагины). Если позывной найден, то функция возвращает True. При этом в параметрах будут возвращены имя и QTH корреспондента. Если вы пишите плагин-колбук, то в теле функции RoexSendNotify должны обрабатывать сообщение SNPN_SEARCHCALLBOOK. При этом свойство Callsign возвращает позывной, который необходимо найти. Если в вашем плагине позывной найден, то свойству Result следует присвоить значение True. При необходимости следует свойствам имя и QTH присвоить соответствующие значения. Интерфейс IQSLViaForm Интерфейс обеспечивает доступ к окну «QSL – менеджеры». Пока в интерфейсе всего одно свойство – указатель на компонент TEdit поля ввода информации для поиска. IQSLViaForm = interface(ITab) ['{402D5BD5-759F-4437-A679-0E260F18B9F2}'] { TEdit } function GetCallField: Pointer; property CallField: Pointer read GetCallField; end; Интерфейс IAwardsForm Интерфейс обеспечивает доступ к форме анализа дипломных программ. Эта форма отображается в виде таблицы в окне «Новое QSO». IAwardsForm = interface(IRoexForm) ['{E2F7F72D-AB8A-4FB8-9C96-04A49CF97AE8}'] function GetAwardName: String; procedure SetState(const Value: String); function GetCallsign: String; property AwardName: String read GetAwardName; property Callsign: String read GetCallsign; procedure Reload; procedure SetResult(const Value: Boolean); end; AwardName Callsign Reload Freq SetResult Имя текущего диплома, для которого ведётся анализ позывного. Анализируемый позывной. Процедура перечитывает условия всех имеющихся дипломных программ. Текущая частота. Процедура предназначена для принудительной установки результата анализа позывного на текущую дипломную программу. Интерфейс IMapsForm Интерфейс обеспечивает доступ к окну «Карты» и к егопроцедурам и свойствам. IMapsForm = interface(ITab) ['{659B08E1-3C35-42BE-9864-0048F36C814D}'] procedure ClearCoordinates; procedure ViewCallsignCoordinates(const Callsign: String); function GetCallsign: String; property Callsign: String read GetCallsign; end; Процедура ClearCoordinates очищает текущие координаты корреспондента. Процедура ViewCallsignCoordinates отображает координаты корреспондента с позывным Callsign. Свойство Callsign возвращает текущий позывной, координаты которого отображаются в данный момент. Интерфейс IQSLPrintForm Интерфейс обеспечивает доступ к окну «Печать QSL – карточек», к его компонентам и процедурам. IQSLPrintForm = interface(IRoexForm) ['{5DAFFF0B-9BB0-4FD2-BE85-23CDC43F6724}'] function GetDBGrid: Pointer; property DBGrid: Pointer read GetDBGrid; function GetDataSet: Pointer; property DataSet: Pointer read GetDataSet; procedure SendToeQSL(const AOnlySelected: Boolean); procedure RefreshData; procedure RemoveFromQSLSend; procedure Printed(const Selected: Boolean); end; DBGrid DataSet SendToeQSL RefreshData Возвращает указатель на таблицу окна. Возвращает указатель на TDataSet, содержащий данные. Процедура отправляет QSO на сервер eQSL. Процедура обновляет данные в таблице главного окна приложения. RemoveFromQSLSend Printed Процедура удаляет все QSO, для которых карточки были отправлены или напечатаны. Процедура отображает окно предварительного просмотра/печати. Интерфейс IAntennasForm Интерфейс обеспечивает доступ к окну управления антеннами, к его компонентам, процедурам и свойствам. IAntennasForm = interface(IRoexForm) ['{CD147B15-B8B1-48EC-AA2C-9082305CF34C}'] { TEdit } function GetAzimutField: Pointer; property AzimutField: Pointer read GetAzimutField; procedure RotationByBearing(const Bearing: Double); procedure Rotation(const Direction: Byte); procedure Switch(const Index: Integer); procedure ClearANTData; procedure SendANTData(const Mode, Callsign, DXCC, Cont: String; const ID, Dist, Az: Integer); procedure GetSpots(DataSet: Pointer); function GetAntIndex: Integer; property _AntIndex: Integer read GetAntIndex; function GetDBGrid: Pointer; property DBGrid: Pointer read GetDBGrid; { TClientDataSet } function GetDataSet: Pointer; property DataSet: Pointer read GetDataSet; end; AzimutField RotationByBearing Rotation Switch ClearANTData SendANTData GetSpots _AntIndex DBGrid DataSet Указатель на компонент TEdit. Процедура поворачивает антенну на заданный угол. Процедура управляет поворотом антенны (влево, вправо, стоп). Процедура переключает антенны (управляет антенным коммутатором). Процедура очищает таблицу принятых спотов. Процедура добавляет новый спот в таблицу принятых спотов. Процедура заполняет таблицу принятых спотов на основе данных DataSet. Текущий индекс включённой антенны. Возвращает указатель на таблицу окна. Указатель на компонент TClientDataSet. В этом компоненте содержаться данные принятых спотов.