Автор: Пользователь скрыл имя, 06 Февраля 2013 в 01:52, аттестационная работа
Класс TList -- универсальный список. Он представляет собой массив нетипированных указателей и поэтому годится для хранения набора любых, в том числе разнотипных, данных и объектов. При добавлении/удалении в список данные не создаются и не уничтожаются -- эта обязанность лежит на программисте. Приведем доступные ему методы и свойства класса.
часы/минуты/секунды/кадры. Числа 24, 25 и 30 означают число кадров в секунду;
tfBytes -- число байт;
tfSamples -- число отсчетов;
tfTMSF -- младший байт: дорожки/минуты/секунды/кадры.
Для кодирования и декодирования информации в этих форматах используйте модуль MMSystem, где предусмотрены соответствующие функции. Для устройств, имеющих дорожки (типов dtCDAudio и dtVideoDisc), в конструкторе устанавливается формат tfTMSF.
Два свойства предназначены специально для устройств видео (таких, как dtAVIVideo, dtDigitalVideo, dtOverlay, dtVCR, dtVideodisc). Первое из них
(Pb) property Display: TWinControl;
задает окно (оконный элемент управления), в котором будет производиться отображение видеоданных. Если это свойство равно nil, то драйвер устройства создаст собственное окно. Если устройство не поддерживает альтернативные окна, свойство игнорируется. Прямоугольная область окна Display, в которой должно происходить отображение, задается вторьм свойством:
property DisplayRect: TRect;
Если значение свойства не определено, вывод в область не производится.
Уже говорилось о том, что для пользователя компонент TMediaPlayer выглядит как набор кнопок, каждая из которых соответствует команде MCJ. Все типы кнопок определены в множестве:
TMPBtnType = (btPlay, btPause, btStop, btNext, bCPrev, btStep, btBack, btRecord, btEject) ;
TButtonSet = set of TMPBtnType;
Отображением кнопок в составе TMediaPlayer во время выполнения управляют три свойства:
(Pb) property VisibleButtons: TButtonSet;
определяет множество видимых кнопок. По умолчанию видны все кнопки, но программисту имеет смысл удалить те, операции которых не поддерживаются данным устройством. Кнопки можно удалить и на стадии разработки, и во время исполнения. Например:
if not (rnpCanRecord in Capabilities) then VisibleButtons := VisibleButtons-[btRecord],
Свойство
(Pb) property ColoredButtons: TButtonSet;
определяет цветовую раскраску кнопок. Каждой операции (как это принято, например, в бытовой технике) соответствует свой цвет. Значок операции на кнопках, попавших в это множество, в случае их видимости также будет цветным. По умолчанию все кнопки имеют это свойство. Следующее свойство
(Pb) property EnabledButtons: TButtonSet;
определяет множество разрешенных кнопок. Оно должно изменяться в зависимости от выполняемой операции (например, при нажатии Pause запрещается и Stop). Объект сам может управлять состоянием своих кнопок, если его свойство:
(Pb) property AutoEnable: Boolean;
установлено в True. Еще три опубликованных свойства:
(Pb) property AutoOpen: Boolean;
-- если это свойство установлено в True, устройство автоматически открывается сразу после загрузки TMediaPlayer;
'Pb) property FileName: string;
-- имя файла. Используется в том случае, если данные мультимедиа хранятся в файле (например, для dtAVIVideo и dtWaveAudio);
^Pb) property Shareable: Boolean;
-- используется при открытии устройства. True означает возможность одновременного открытия его другими задачами (другими объектами TMediaPlayer).
Пара событий, возникающих при нажатии кнопок TMediaPlayer определяется свойствами:
(Pb) property OnClick: EMPNotify;
EMPNotify = procedure (Sender: TObject; Button: TMPBtnType;
var DoDefault: Boolean) of object;
(Pb) property OnPostClick: EMPPostNotify;
EMPPostNotify = procedure (Sender: TObject;
Button: TMPBtnType) of object;
Обработчику события OnClick передается тип нажатой кнопки в параметре Button. В результате обработки он должен вернуть значение в параметре DoDefault. Если оно равно True, вызывается соответствующая кнопке функция MCI и после этого -- OnPostClick. Если оно равно False, ничего не происходит (подразумевается, что пользователь сам вызвал требуемые функции MCI).
Для того чтобы проиллюстрировать работу компонента TMediaPlayer, на прилагаемой к книге дискете имеется пример использования проигрывателя CD-аудиодисков CDPLAYER. В нем реализованы все команды управления проигрывателем и отображается его текущее состояние в компоненте-индикаторе типа TGauge.
Динамический обмен данными (DDE)
DDE -- давний и прижившийся протокол обмена данными между разными приложениями, появившийся еще на заре эры Windows. С тех пор на его базе был создан интерфейс OLE, а в 32-разрядном API Windows появились и другие методы межпрограммного взаимодействия. Но ниша, занимаемая DDE, осталась неизменной -- это оперативная передача и синхронизация данных в приложениях.
Приложения, использующие DDE, разделяются на две категории -- клиенты и серверы (не путать с одноименной архитектурой СУБД). Оба участника процесса осуществляют контакты (conversations) по определенным темам (topic), при этом в рамках темы производится обмен элементами данных (items). Устанавливает контакт клиент, который посылает запрос, содержащий имена контакта и темы. После установления контакта всякое изменение элемента данных на сервере передается данным клиента. Подробно функции DDE описаны в [4].
Первоначально программирование DDE было чрезвычайно сложным делом -- оно требовало взаимосвязанной обработки более чем десяти сообщений Windows. В версии Windows 3.1 появилась библиотека DDEML, которая перевела управление DDE на уровень вызова процедур. Разработчики подсистемы DDE в Delphi, верные идеологии создания VCL, свели интерфейс этого протокола к четырем компонентам -- двум для сервера и двум для клиента.
На уровне поддержания контакта лежат компоненты TDDEServerConv и TDDEClientConv. Первый играет пассивную роль -- он только указывает имя одной из поддерживаемых сервером тем. Все операции по установлению и разрыву контакта осуществляет из приложения-клиента второй компонент.
Посредством одного контакта могут быть связаны и синхронизированы несколько пар элементов данных. Для их описания предназначены компоненты
TDDEServerItem и TDDEClientItem. Каждый из них во время работы должен указывать на контакт, к которому он привязан. Кроме того, в составе обоих есть свойства, содержащие некий текст. При установленном контакте их содержимое синхронизируется.
Помимо этого в модуле DDEMAN описан и пятый компонент, который управляет всеми связями DDE. Его рассмотрение выходит за рамки книги.
Начнем с рассмотрения двух компонентов, необходимых для создания сервера DDE.
Компонент TDDeServerConv
TObject-->TPersistent->
Модуль DDEMAN
Страница Палитры компонентов System
В этом компоненте самую важную роль играет единственное свойство -- Name. Имя компонента совпадает с именем темы, которую он поддерживает. Клиент должен знать это имя при установлении контакта, за исключением того случая, когда он подключается к данным контакта, которые скопированы в буфер обмена (это реализует компонент TDDEServerItem).
В моменты открытия и закрытия контакта возникают события:
(ph) property OnOpen: TNotifyEvent;
(РЕ) property OnClose: TNotifyEvent;
Первоначально протокол DDE был ориентирован только на оперативное получение данных клиентом от сервера, но позже его возможности расширились. Клиент может передать для выполнения серверу набор макрокоманд -- для этого у него есть нужные методы. На стороне сервера за их исполнение отвечает обработчик события:
(pb) property OnExecuteMacro: TMacroEvent;
TMacroEvent = procedure(Sender: TObject; Msg: TStrings) of object;
Если вы хотите, чтобы ваш сервер DDE мог исполнять команды, то нужно предусмотреть такой обработчик. Передаваемые команды содержатся в параметре Msg в виде набора строк. Можно вызвать процесс выполнения команд и из приложения, с помощью метода:
function ExecuteMacro(Data: HDDeData): Longint;
В этом случае параметр Data должен содержать дескриптор строки с командами (типа pChar).
Компонент TDDeServerltem
TObject--"TPersistent-->
Модуль DDEMAN
Страница Палитры компонентов System
Этот компонент реализует элемент данных, которые при установленном контакте будут передаваться клиенту. В принципе, протокол DDE подразумевает обмен любыми данными, формат которых зарегистрирован в буфере обмена. Но для рассматриваемых компонентов Delphi эти возможности ограничиваются
только текстовыми данными. Так что свойство, содержащее формат обмена данными,
property Fmt: Integer;
всегда равно CF_TEXT. Данные содержатся в свойствах:
(^ property Text: string;
(Йэ) property Lines: TStrings;
По сути дела, первое свойство представляет собой подмножество второго. При чтении Text равен первой строке Lines. Но если вы присваиваете ему значение, все прочие строки Lines очищаются. Элемент данных должен быть связан с определенной темой. В свойстве:
(Pb) property ServerConv: TDDeServerConv;
может быть задана ссылка на компонент типа TDDEServerConv, чье имя будет темой контакта DDE. Можно обойтись и без использования такого компонента. В этом случае именем темы будет являться заголовок (Caption) той формы, которая содержит TDDEServerItem. Элемент данных может быть скопирован в буфер обмена в специальном формате (в виде информации о контакте), с помощью метода:
procedure CopyToClipboard;
Для вступления в контакт посредством буфера обмена клиент может вызвать функцию GetPasteLinkInfo (см. ниже), и, проанализировав имена сервера, темы и элемента, принять решение о вступлении. Клиент может переустановить данные сервера. При переустановке возникает событие:
(Pb) property OnPokeData: TNotifyEvent;
Кроме того, для этого вами может быть использован метод:
function PokeData(Data: HDDeData): Longint;
Параметр Data должен представлять собой дескриптор области памяти, в которой содержится текстовая строка типа pChar. В отличие от OnPokeData, событие:
(Pb) property OnChange: TNotifyEvent;
возникает при любом изменении данных, как при присвоении значений свойствам Text или Lines, так и при вызове PokeData. Оно может также быть вызвано явно из метода: ^
procedure Change;
Компонент TDDECIIentConv
TObject->TPersistent->
Модуль DDEMAN
Страница Палитры компонентов System
Компонент TDDEClientConv осуществляет контакт на клиентской стороне. Именно в нем описаны методы, отвечающие за установление контакта. Имена требуемых сервера DDE и темы содержатся в свойствах:
§ property DDEService: String;
property DDETopic: String;
Сервер и тема устанавливаются при вхождении в контакт. Предусмотрены два режима вхождения в него:
(Pb) property ConnectMode: TDataMode;
TDataMode = (ddeAutomatic, ddeManual);
Метод
function SetLink(const Service: string; const Topic: string): Boolean;
присваивает серверу и теме имена, равные Service и Topic, а если выбран режим контакта ddeAutomatic -- то и устанавливает контакт. Будьте внимательны при задании параметров метода-- здесь учитывается регистр символов. В случае режима ddeManual для установления контакта необходимо вызвать дополнительно метод:
function OpenLink: Boolean;
Этот метод сначала закрывает предыдущий контакт, затем он пытается связаться с сервером DDEService на тему DDETopic. Если это не удается сразу (например, если требуемый сервер DDE отсутствует), то делается попытка загрузить программу с именем, определенным в свойстве
(Pb) property ServiceApplication: String;
и установить контакт с ней. Если оно не определено (ServiceApplication = "), то в качестве последней попытки для контакта пробуется имя, представляющее собой конкатенацию имен сервера и темы, разделенных пробелом. В случае неудачи метод OpenLink возвращает False.
Можно связаться с сервером, если он поместил данные о контакте в буфер обмена. В этом случае метод
function PasteLink: Boolean;
переключит компонент на новый контакт и вернет значение True. Наконец, метод
procedure CloseLink;
разрывает контакт с сервером DDE.
Метод
function StartAdvise: Boolean;
инициирует начало обмена данными. Обычно он вызывается в методе OpenLink.
Как уже упоминалось, основное направление потоков данных -- от сервера к клиенту, однако возможно и обратное. При помощи двух методов можно присвоить новые значения элементу данных сервера:
function PokeDataLines(const Item: string; Data: TStrings): Boolean;
function PokeData(const Item: string; Data: PChar): Boolean;
Здесь Item -- имя элемента данных, Data -- передаваемые текстовые данные. Кроме того, некоторые серверы DDE имеют собственные наборы макрокоманд, запрос на выполнение которых можно послать от клиента. К ним относятся многие приложения, в т. ч. СУБД и электронные таблицы, такие, как Paradox и MS Excel; наиболее типичным примером служит Program Manager. Запрос на выполнение макрокоманд посылают методы:
function ExecuteMacroLines(Cmd: TStrings; waitFIg: Boolean): Boolean-function ExecuteMacro(Cmd: PChar; waitFIg: Boolean): Boolean;
Серверу может потребоваться определенное время для выполнения этих операций. Если до их окончания снова загрузить его работой, то это может привести к непредсказуемым результатам. Чтобы отследить состояние сервера, нужно установить параметр функции waitFIg в True. С началом операции свойство
(Ro) property WaitStat: Boolean;
устанавливается в True. При этом вызовы последних четырех описанных методов отрабатываться не будут, пока сервер не известит об окончании операции, и WaitStat не примет значение False. Это свойство доступно только по чтению. Клиент может запросить данные от сервера немедленно с помощью метода:
function RequestData(const Item: string): PChar;
Формат обмена данными можно узнать из свойства:
(Ro) property DDEPmt: Integer;
Перефразируя Генри Форда, скажем, что можно обмениваться данными любого формата, если этот формат -- CF_TEXT.
Если возможностей, предоставляемых методами и свойствами класса, недостаточно, то для вызова процедур библиотеки DDEML программисту доступен дескриптор контакта:
(Ro) property Conv: HConv;
В полученном от сервера тексте могут быть специальные управляющие символы -- <Enter>, <Tab>, <Backspace> и другие. Их можно отфильтровать (подавить), если свойство
(Pb) property FormatChars: Boolean;
установлено в False. В этом случае все символы ASCII с десятичными кодами от 1 до 31 заменяются на пробел (код 32). В случае True преобразования не происходит.
Так же, как и в TDDEServerConv, при открытии и закрытии контакта вы можете выполнить специфотеские действия путем обработки событий:
(pk) property OnOpen: TNotifyEvent;
(Pb) property OnClose: TNotifyEvent;
Свойство
property DataMode: TDataMode;
по-видимому, зарезервировано ддя дальнейших применений.
Компонент TDDECIientltem
TObject-->TPersistent--"
Модуль DDEMAN
Страница Палитры компонентов System
Этот компонент представляет элемент данных на клиентской стороне. После установления контакта с сервером нужно присвоить свойству
(Pb) property DDEConv: TDDEClientConv;
указатель на объект, соответствующий появившемуся контакту, а свойству
(Pb) property DDEItem: String;
имя элемента данных сервера. В этом случае все изменения будут отслеживаться.
В рассмотренном ниже примере приложение-клиент вступает в контакт с сервером InfbServer на тему TimeTopic. При нажатии кнопки TimeButton связь устанавливается, при отпускании -- разрывается. Метод TimeConvOpen, служащий обработчиком события ОпОреп, присваивает значения именам темы и элемента данных.