

| стрелялки |
| спорт |
| драки |
| стратегии |
| гонки |
| логические |
| азартные |
| аркады |
| эротические |
| фильмы онлайн |
| Место класса THandleStream |
|
К сожалению, в огромном списке компонентов VCL Delphi не нашлось места для специализированных классов, инкапсулирующих методы для работы с почтовыми слотами или именованными каналами. Однако в Delphi реализован потенциальный прототип для создания объектов, работающих в рамках изучаемых в этой главе технологий, - класс THandleStream. В Windows почтовые слоты и именованные каналы реализованы в виде драйверов файловой системы. Этим объясняется то, что при работе с перечисленными механизмами программисты опираются на методы, предназначенные для работы с файлами. Заслуга класса THandleStream состоит в том, что он инкапсулирует то общее, что имеется в механизмах почтовых слотов и именованных каналов. Под «общим» следует понимать набор свойств и методов, обеспечивающих операции ввода/вывода в разделяемый коммуникационный ресурс. Снабдив класс всем необходимым для работы, например с mailslot, можно получить великолепный экземпляр компонента VCL. Этим мы займемся позже, а пока немного теории. У класса THandleStream всего три свойства. В первую очередь это дескриптор коммуникационного ресурса: property Handle: Integer; //только для чтeния В этом свойстве может оказаться дескриптор почтового слота, именованного канала или чего-то другого. Все зависит от того, в целях какой технологии будет применен экземпляр класса. Следующие два свойства, унаследованные от его непосредственного предка TStream, информируют программиста о размере ресурса и местоположении в нем курсора чтения/записи: property Size: Int64; //paзмep property Position: Int64; //позиция Для создания экземпляра класса вызывается конструктор: constructor Create(AHandle: Integer); Обратите внимание, что в качестве параметра необходимо передать дескриптор коммуникационного объекта, который создается по-прежнему с помощью функций Win32 API (несколько позже это будет проиллюстрировано на примере только что изученного почтового слота). Кроме того, класс THandle-Stream вооружен методами чтения и записи: function Read(var Buffer; Count: Longint): Longint; override; function Write(const Buffer; Count: Longint): Longint; override; Здесь Buffer - буфер для чтения (записи) и Count - количество прочитанных (записанных) байт. Еще два метода обеспечивают позиционирование и определение размеров ресурса: function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override; procedure SetSize(const NewSize: Int64); override; А теперь рассмотрим листинг, объединяющий в себе преимущества VCL и гибкость методов Win32 API. В примере создается класс TMailSlot, обладающий всеми функциональными возможностями почтового ящика. Вначале рассмотрим заголовок модуля, в котором объявляются наши намерения: unit vcl_mailslot; interface uses Windows, Classes, SysUtils; type TMailSlot=class(THandleStream) public constructor Create(const SlotAddress : string); destructor Destroy; function ReadMail(MailText : TStrings): boolean; procedure WriteMail(const MailAddress, MailText : string); end; В интерфейсной части модуля объявлен класс TMailSlot - прямой наследник только что изученного класса THandleStream. С его помощью мы планируем решать следующие задачи: 1. Создание почтового слота. С этой целью объявлен конструктор Create(). 2. Освобождение ресурса почтового слота, например при завершении работы программы. С этой целью реализован деструктор Destroy(). 3. Просмотр поступившей почты - метод ReadMail(). 4. Отправка почты заданному адресату - метод WriteMail(). Исходя из этого раздел реализации будет выглядеть примерно так: implementation { TMailSlot } constructor TMailSlot.Create(const SlotAddress: string); begin fHandle:=CreateMailSlot(pAnsiChar(SlotAddress), 0, MAILSLOT_WAIT_FOREVER, nil); if fHandle=INVALID_HANDLE_VALUE then raise EOSError.CreateFmt('Ошибкa почтового cлoтa %d',[GetLastError]); end; В конструктор передается всего один параметр - строка с названием почтового слота на серверной стороне. Дескриптор почтового ящика, созданного методом Win32 API CreateMailSlot(), передается в поле fHandle и позже используется при чтении полученной корреспонденции. В случае возникновения ошибки при создании слота инициируем ошибку. Сейчас, чтобы не отвлекаться на возможные варианты ее обработки, просто создадим экземпляр класса EOSError. Определение деструктора элементарно: метод CloseHandle() освобождает ресурс почтового слота: destructor TMailSlot.Destroy; begin CloseHandle(Handle); end; Следующий метод предназначен для чтения полученных сообщений: function TMailSlot.ReadMail(MailText : TStrings) : boolean; var NextSize, MessageCount : Cardinal; Buf: PChar; begin {пepвoнaчaльнo получим дaнныe о почтовом ^0Te} GetMailSlotInfo(Handle, nil, NextSize, @MessageCount, nil); Предлагаемая функция ReadMail() в качестве параметра получает ссылку на набор строк MailText:TStrings. Благодаря этому метод может применяться совместно с компонентом класса TMemo. Например, следующая строка кода: MailSlot.ReadMail(Memo1.Lines); получит все почтовые отправления из объекта MailSlot : TMailSlot и загрузит их в строки memo-поля Memol. Сам код функции получения корреспонденции не будет для нас откровением. Метод Win32 API GetMailslotInfo() информирует о наличии сообщений в почтовом ящике с дескриптором Handle. Если сообщения есть (MessageCount>0), они перебираются в цикле и считываются методом Read(), унаследованным от класса THandleStream. |
