18.4. КОМПОНЕНТЫ СТРАНИЦЫ SYSTEM

В этом разделе не описаны расположенные на этой странице компоненты TDDEClient, TDDEClientItem, TDDEServer И TDDEServerItem.

Они рассчитаны на поддержку устаревшей технологии межпрограммного обмена данными DDE - Dynamic Data Exchange (динамический обмен данными), которая в современных программах полностью вытеснена технологией OLE.

18.4.1. TTimer - таймер

Компонент TTimer (таймер) служит для отсчета интервалов реального времени. Его свойство interval определяет интервал времени в миллисекундах, который должен пройти от включения таймера до наступления события onTimer. Таймер включается при установке значения True в его свойство Enabled. Раз включенный таймер все время будет возбуждать события onTimer до тех пор, пока его свойство Enabled не примет значения False.

Следует учесть, что в силу специфики реализации аппаратного таймера персонального IBM-совместимого компьютера минимальный реально достижимый интервал отсчета времени не может быть меньше 55 миллисекунд (этот интервал называется тиком). Более того, любой интервал времени, отсчитываемый с помощью таймера, всегда кратен 55 миллисекундам. Чтобы убедиться в этом, проделайте следующий эксперимент, в котором подсчитывается среднее время между двумя срабатываниями таймера:

- Положите на пустую форму компонент TTimer. Установите в его свойство interval любое число в диапазоне от 1 до 55 включительно.
- Напишите такой обработчик события onTimer:

var

BegTime: TDateTime;

procedure TForm1.Timer1Timer(Sender: TObject);

var

h, m, s, ms: Word;// Переменные для декодирования времени

const

MaxTick = 10; // Количество интервалов таймера

begin

if Tag = 0 then

BegTime := Time; // Запоминаем начальное время

Tag := Tag + 1; // Наращиваем счетчик тиков

if Tag = MaxTick then

begin

Timeri.Enabled := False; // Выключаем таймер

// Декодируем значение 1 тика

DecodeTime((Time-BegTime)/MaxTick, h, m, s, ms);

// Выводим результат в заголовке окна:

Caption := IntToStr(s) + ' s ' + IntToStr(ms) + ' ms'

end

end;

Обратите внимание на определение глобальной переменной BegTime в области видимости процедуры TimerlTimer. Необходимость нескольких (MaxTick) срабатываний для точного усреднения результата связана с тем, что системные часы также обновляются каждые 55 мс. После запуска программы в заголовке окна вы увидите строку

О s 55 ms ,

в которой указывается, сколько реального времени разделяет два соседних события OnTimer. Этот результат повторится для любых значений константы MaxTick. Если вы установите Interval таймера в диапазоне от 56 до 110 миллисекунд, в заголовке будет указано 110 ms И Т. Д.

18.4.1.1. Мультимедийный таймер

В ряде практически важных применений (при разработке игр, в системах реального времени для управления внешними устройствам и т. п.) интервал 55 мс может оказаться слишком велик. Современный ПК имеет мультимедийный таймер, период срабатывания которого может быть от 1 мс и выше. Однако этот таймер не имеет компонентного воплощения, поэтому для доступа к нему приходится использовать функции API.

Общая схема его использования такова. Сначала готовится процедура обратного вызова (call back) с таким заголовком:

procedure TimeProc(uID, uMsg: UINT; dwUser, dwi, dw2: DWORD);

stdcall;

Здесь uID - идентификатор события таймера (см. ниже); uMsg - не используется; dwuser - произвольное число, передаваемое процедуре в момент запуска таймера; dwi, dw2 - не используются. Запуск таймера реализуется функцией

function timeSetEnet(uDelay, uResolution: UINT;

IpTimeProc:Pointer;

dwUser: DWORD;

fuEvent: UINT): UINT;

stdcall;

external 'winmm.dll';

Здесь uDelay - требуемый период срабатывания таймера (в мс);

uResolution - разрешение таймера; значение 0 означает, что события срабатывания таймера будут возникать с максимально возможной частотой; в целях снижения нагрузки на систему вы можете увеличить это значение; IpTimeProc - адрес процедуры обратного вызова; dwUser - произвольное число, которое передается процедуре обратного вызова и которым программист может распоряжаться по своему усмотрению; fuEvent - параметр, управляющий периодичностью возникновения события таймера: time_oneshot (0) - событие возникает только один раз через uDelay мс; time_periodic (1) - события возникают периодически каждые uDelay мс. При успешном обращении функция возвращает идентификатор события таймера или 0, если обращение было ошибочным.

Таймер останавливается, и связанные с ним системные ресурсы освобождаются функцией

function timeKillEvent(uID: UINT): UINT;

stdcall; external 'winmm.dll';

Здесь uID - идентификатор события таймера, полученный с помощью timeSetEvent.

В следующем примере иллюстрируется особенность использования мультимедийного таймера.

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, ExtCtrls;

type

TfmExample = class(TForm)

Panell: TPanel;

bbRun: TBitBtn;

bbClose: TBitBtn;

edinput: TEdit;

IbOutput: TLabel;

mmOutput: TMemo;

procedure bbRunClick(Sender: TObject);

procedure FormActivate(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations

end;

var

fmExample: TfmExample;

implementation

{$R *.DFM} // Объявление экспортируемых функций:

function timeSetEvent(uDelay, uReolution: UINT; IpTimeProc:

Pointer;

dwUser: DWORD; fuEvent: UINT): Integer;

stdcall;

external

'winmm';

function timeKillEvent (uiD: UINT): Integer;

stdcall;

external 'winmm' ;

// Объявление глобальных переменных

var

uEventID: UINT; // Идентификатор события таймера

BegTime: TDateTime; // Засечка времени

Counter: Integer; // Счетчик повторений

Delay: Word; // Период срабатывания

procedure ProcTime(uID, msg:. UINT; dwUse, dwi, dw2: DWORD);

stdcall;

// Реакция на срабатывание таймера (процедура обратного вызова)

var

h, m, s, ms: Word; // Переменные для декодирования времени

const

MaxCount = 55; // Количество повторений

begin

timeKillEvent(uEventID); // Останавливаем таймер

Counter := Counter+1; // Наращиваем счетчик

if Counter=MaxCount then // Конец цикла?

begin // - Да: декодируем время

DecodeTime((Time-BegTime)/MaxCount, h, m, s, ms);

fmExample.mmOutput.Lines.Add(

// Сообщаем результат

Format('Задано %s ms. Получено %d ms', [fmExample.edinput.Text, ms ] ) ) ;

fmExample.edinput.Text := ''; // Готовим повторение fmExample.edinput.SetFocus

end

else // - Нет: вновь пускаем таймер

uEventID := timeSetEvent(Delay,0,@ProcTime,0,1);

end;

procedure TfmExample.bbRunClick(Sender: TObject);

// Запускает таймер, edinput содержит требуемый период.

begin

// Проверяем задание периода

if edinput.Text= '' then Exit;

try

Delay := StrToInt(edinput.Text)

except

ShowMessage('Ошибка ввода числа');

edinput.SelectAll;

edinput.SetFocus ;

Exit

end;

Counter := 0;

// Сбрасываем счетчик

BegTime := Time;

// Засекаем время

// Запускаем таймер:

uEventID := timeSetEvent(Delay,0,@ProcTime,О,1);

if uEventID=0 then

ShowMessage('Ошибка запуска таймера ' )

end;

procedure TfmExample.FormActivate(Sender: TObject);

begin

edinput.SetFocus

end;

end.

18.4.2. TPaintBox - окно для рисования

Назначение компонента TPaintBox - дать вам простое окно с канвой для рисования произвольных изображений. Канва содержится в свойстве Canvas компонента, графические инструменты - в свойствах Font, pen и Brush, а собственно рисование осуществляется в обработчике события OnPaint. Особенности использования этих инструментов см. в п. 16.4. Например, следующий обработчик создаст окно, показанное на рис. 18.35:

Рис. 18.35. Пример использования TPaintBox

procedure TFormI.PaintBoxIPaint(Sender: TObject);

var

X, Y: Integer;

begin

with PaintBoxl, Canvas do

begin

Brush.Color := cIRed;

Ellipse (0, 0, Width, Height);

Font.Name := 'Arial';

Font.Size := Height div 5;

Font.Style := [fsBold, fsltalic];

Font.Color := clWhite;

X := (Width - TextWidth('Delphi')) div 2;

Y := (Height - TextHeight('D')) div 2;

TextOut(X, Y, 'Delphi')

end

end;

При повторении примера положите на пустую форму компонент

TPaintBox И установите его размеры: Height = 100/ Width = 300.

18.4.3. TMediaPlayer - медиаплейер

Компонент TMediaPlayer представляет собой набор кнопок (рис. 18.36), предназначенных для управления различными мультимедийными устройствами (компакт-дисками, звуковыми картами и т. п.).

Рис. 18.36 . Кнопки компонента TMediaPlayer

Если ваш компьютер оснащен звуковой картой, вставьте этот компонент в пустую форму, в его свойство FileName поместите название любого файла с расширением WAV (из каталога с: | winsows | media), установите в свойство Autoopen компонента значение True и запустите программу - после щелчка мышью по кнопке вы услышите звучание выбранного музыкального фрагмента. Как видите, использование компонента предельно просто. Он автоматически распознает тип мультимедийного устройства по расширению файла и берет на себя управление этим устройством. Разумеется, в каждый момент времени компонент может управлять лишь одним устройством, однако с помощью изменения содержимого FileName или явно с помощью свойства DeviceType программа может менять устройство, связанное с компонентом.

Каждая кнопка компонента имеет собственное имя, позволяющее программисту сделать какую-либо кнопку невидимой или недоступной. В следующей таблице приводится имя и назначение каждой кнопки (под носителем информации подразумеваются файлы и физические устройства, которые могут служить источником или приемником информации).

btStop | Останавливает запись или воспроизведение
btNext | Позиционирует устройство на следующую дорожку или в конец носителя информации, если устройство не имеет дорожек
btPrev | Позиционирует устройство на предыдущую дорожку или в начало носителя информации, если устройство не имеет до
btStep | рожек Позиционирует устройство на один блок кадров ближе к концу носителя информации. Количество кадров в блоке
btBack | содержится в свойстве Frames компонента Позиционирует устройство на один блок кадров ближе к началу носителя информации
btRecord | Начинает запись в носитель информации
btEject | Освобождает устройство от носителя информации
btPlay | Запуск
btPause | Пауза

Свойства компонента:

property AutoEnable: Boolean; | Разрешает/запрещает автоматическое определение доступных и запрещенных кнопок
property AutoOpen: Boolean; | Разрешает/запрещает автоматический старт записи/воспроизведения в момент создания формы, в которую вставлен компонент
property AutoRewind: Boolean; | Разрешает/запрещает автоматическую “перемотку” носителя информации в момент начала записи или воспроизведения. Игнорируется, если устройство имеет дорожки или если установлены значения в свойства startpos и EndPos
TMPDevCaps = (mpCanStep, mpCanEject, mpCanPlay, mpCanRecord, mpUsesWindows); TMPDevCapsSet = set of TMPDevCaps; | Содержит возможности устройства, связанного с компонентом mpCanStep, - может смещать носитель на кадр вперед или назад (устройство типа Animation, AVI Video, Digital Video, Overlay, или VCR); mpCanEject - может автоматически удалять носитель из устройства; mpCanPlay - может воспроизводить информацию; mpCanRecord - может записывать информацию; mpUsesWindows - может использовать окно для отображения процесса
property Capabilities: TMPDevCap sSet; TMPBtnType = (btPlay, btPause, btStop, btNext, btPrev, btStep, btBack, btRecord, btEject); | Кнопки, перечисленные в этом свойстве, будут использовать умалчиваемые цвета, не перечисленные кнопки будут черно-белыми.
TButtonSet = set of TMPBtnType;property ColoredButtons: Tbutton Set; | По умолчанию множество ColoredButtons содержит все кнопки
property DeviceID: Word; | Содержит Windows-идентификатор устройства, связанного с компонентом. Доступно только для чтения

TMPDeviceTypes = (dtAutoSelect,

dtAVIVideo, dtCDAudio, dtDAT,

dtDigitalVideo, dtMMMovie,

dtOther, dtOverlay, dtScanner, dtSequencer, dtVCR, dtVideodisc,

dtWaveAudio);

property DeviceType: TMPDevice

Types;

Содержит тип устройства. Если Device-

Type" dtAutoSelect, тип определяется

автоматически по расширению файла в свойстве FileName. Каждое мультимедийное устройство в момент инсталляции указывает в файле system. ini, файлы с какими расширениями оно поддерживает

property Display: TWinContrn: | Содержит ссылку на окно для устройств, которые могут его использовать в процессе записи/воспроизведения
property DisplayRect: TRect; | Содержит область окна Display, которое устройство может использовать для отображения процесса записи/воспроизведения. Для улучшения процесса отображения рекомендуется в DisplayRect указывать умалчиваемые размеры(задаются координатами 0,0 для правого нижнего угла)
property EnabledButtons: TButtonSet; | Содержит множество доступных кнопок (тип TButtonSet описан выше для свойства ColoredButtons)
property EndPos: Longint; | Содержит положение носителя информации в момент прекращения записи или воспроизведения. Переустановка значения приводит к повторению записи или воспроизведения
property Error: Longint; | Содержит код ошибки. Доступно только для чтения
property ErrorMessage: String; | Содержит сообщение об ошибке. Доступно только для чтения
property FileName: String; | Содержит имя читаемого или записываемого файла
property Frames: Longing; | Определяет количество кадров, пропускаемых при выполнении методов step или Back
property Length: Longint; | Содержит текущую длину носителя информации. Доступно только для чтения
TMPModes = (mpNotReady,-ipStopped, mpPlaying, mpRecord- ing, mpSeeking, mpPaused, -npOpen) ; property Mode: TMPModes; | Показывает текущее состояние мультимедийного устройства: mpNotReady - не готово; mpStopped - остановлено; mpPlaying - воспроизводит информацию; mpRecording -записывает информацию; mpSeeking - перемещает носитель информации; mpPaused - Приостановлено; mpOpen - от крыто. Доступно только для чтения
property Notify: Boolean; PNotifyValues = (nvSuccessful, Superseded, nvAborted, nvFailre); | Содержит True, если методы Back, Close, Eject, Next, Open, Pause, PauseOnly, Play, Previous, StartRecording, Resume, Rewind, Step и Stop будут создавать событие OnNotify Содержит результат последней команды, создающей событие OnNotify: nvSuccessful - выполнена успешно; nvSuperseded
property NotifyValue: TMPNotify; Values; | заменена другой командой; nvAborted досрочно прервана; nvFailure - завершилась ошибкой. Доступно только для чтения
property Position: Longint; | Содержит текущую позицию носителя информации
property Shareable: Boolean; | Разрешает/запрещает другим компонентам и программам использовать устройство, связанное с данным компонентом
property Start: Longing; | Содержит позицию от начала носителя, с которой начинается запись или воспроизведение. Определяется в момент открытия устройства и доступно только для чтения
property StartPos: Longint; | Содержит текущую позицию от начала носителя, с которого начинается запись или воспроизведение
TMPTimeFormats = (tfMilliseconds, tfHMS, tfMSF, tfFrames,tfSMPTE24, tfSMPTE25, tfSMPTESO,tfSMPTE30Drop, tfBytes, tfSam ples, tfTMSF);property TimeFormat: TMPTimeFor mats; | Определяет формат представления данных в свойствах StartPos, Length, Position, Start и Endpos (см. пояснения ниже)
property TrackLength[TrackNum: Integer]: Longint; | Возвращает длину (в формате TimeFormat) дорожки с индексом TrackNum. Доступно только для чтения
property TrackPosition[TrackNum: Integer]: Longint | Возвращает стартовую позицию (в формате TimeFormat) дорожки С индексом TrackNum. Доступно только для чтения
property Tracks: Longint; | Содержит количество дорожек в открытом устройстве. Доступно только для чтения
property VisibleButtons: TButtonSet; | Содержит множество видимых кнопок (тип TButtonSet описан выше для свойства ColoredButtons)
property Wait: Boolean; | Если содержит True, управление возвращается в программу только после завершения перехода устройства в другое состояние, связанное с методами Back, Close, Eject, Next, Open, Pause, PauseOnly, Play, Previous, StartRecording, Resume, Rewind, Step или Stop

Если свойство AutoEnabie имеет значение True, компонент автоматически по типу устройства или расширению файла и значению свойства Mode определяет, какие кнопки будут доступны пользователю. Если AutoEnabie=Faise, доступными будут только те кнопки, которые входят в множество EnabiedButtons. Множество Enabied-

Buttons игнорируется, если AutoEnable=True.

Свойство AutoRewind игнорируется, если устройство имеет дорожки или если процесс записи/воспроизведения вызван изменением значения в свойстве StartPos или Endpos.

Положение носителя В свойствах StartPos, Length, Position, Start и EndPos В Зависимости от значения свойства TimeFormat должно интерпретироваться следующим образом (отсчет ведется от начала носителя информации):

tfMilliseconds | Миллисекунды в диапазоне от 0 до 4 294 967 295 Часы, минуты, секунды.
tfHMS | Занимают в порядке перечисления по одному байту начиная с младшего. Старшин байт Longint не используется
tfMSF | Минуты, секунды и кадры. Занимают в порядке перечисления по одному байту начиная с младшего. Старший байт Longint не используется
tfFrames | Кадры в диапазоне от 0 до 4 294 967 295
tfSMPTE24 | Часы, минуты. секунды и количество блоков по 24 кадра в секунду. Занимают в порядке перечисления по одному байту начиная с младшего
tfSMPTE25 | Часы, минуты, секунды и количество блоков по 25 кадров в секунду
tfSMPTE30 | Часы, минуты, секунды и количество блоков по 30 кадров в секунду
tfSMPTE30Drop | Часы, минуты, секунды и количество пропущенных блоков по 30 кадров в секунду
tfBytes | Байты в диапазоне от 0 до 4 294 967 295
tfSamples | Количество условных блоков информации в диапазоне от 0 до 4294967295
tfTMSF | Дорожки, минуты, секунды и кадры. Занимают в порядке перечисления по одному байту начиная с младшего

Свойство TimeFormat недоступно из окна Инспектора объектов и устанавливается автоматически при открытии мультимедийного устройства методом open. В связи с этим значения в свойствах StartPos, Position и EndPos могут устанавливаться, а в свойствах Length, Start, TrackLength И TrackPosition Становятся действительными только после вызова СPеn.

Методы компонента:

procedure AutoButtonSet(Btn: TMPBtnType); dynamic; | Реализует разрешение/запрещение кнопок компонента при установке в свойство AutoEnable значения True Перемещает текущую позицию в носителе информации назад на количество кадров, содержащихся В свойстве Frames
procedure Back; | По умолчанию вызывает обработчик события OnClick.
procedure Click(Button: TMPBtnType; var DoDefault: eoolean); dynamic ; | Предназначен для перекрытия в потомках
procedure Close; | Закрывает связанное с компонентом устройство
procedure DoNotify; dynamic; | По умолчанию вызывает обработчик события OnNotify. Предназначен для перекрытия в потомках
procedure Eject; | Выгружает носитель информации из устройства
procedure MMNotify(var Message: TMessage); message :MCINOTIFY; | Реализует отклик на сообщение Windows мм mcinotify. По умолчанию вызывает метод DoNotify
procedure Next; | Перемещает текущую позицию носителя на начало следующей дорожки, а если устройство не имеет дорожек - в конец носителя
procedure Notification ( AComponent: TComponent; Operation: TOperation); override; | Извещает компонент AComponent о том, что завершилась операция Operation
procedure Open; | Открывает мультимедийное устройство
procedure Pause; | Приостанавливает процесс воспроизведения или записи информации. Если устройство уже было приостановлено, восстанавливает процесс с помощью вызова метода Resume
procedure PauseOnly; | Приостанавливает процесс воспроизведения или записи информации. Если устройство уже было приостановлено, ничего не делает
procedure Play; | Начинает воспроизведение с позиции StartPos, а если это свойство не установлено - с текущей позиции position
procedure PostClick (Button: TMPBtnType); dynamic; | Реализует отклик на событие OnPostClick. По умолчанию вызывает соответствующий обработчик события
procedure Previous; | Перемещает текущую позицию носителя на начало предыдущей дорожки, а если устройство не имеет дорожек - в начало носителя
procedure Resume; | Восстанавливает процесс записи или воспроизведения. Вызывается при повторном щелчке по кнопке btPause
procedure Rewind; | Перемещает текущую позицию носителя к положению, определяемому свойством Start
procedure Save; | Сохраняет информацию в файле с именем FileName
procedure StartRecording; | Начинает запись информации с текущей позиции или позиции StartPos
procedure Step; | Перемещает текущую позицию в носителе информации вперед на количество кадров, содержащихся В свойстве Frames
procedure Stop; | Прекращает запись или воспроизведение информации
Для компонента определены следующие события:
EMPNotify = procedure (Sender: TObject; Button: TMPBtnType; var DoDefault: Boolean) of object; property OnClick: EMPNotify; | Возникает после щелчка по кнопке Button компонента. Если DoDefault=True, вызывается метод, связанный с этой кнопкой
property OnNotify: TNotifу Event; | Возникает после завершения вызова одного из методов Back, Close, Eject, Next, Open, Pause, PauseOnly, Play, Previous, Resume, Rewind, StartRecording, Step или Stop,если свойство Notify имеет значение True
EMPPostNotify = procedure (Sender: TObject; Button: TMPBtnType) of object; property OnPostClick: EMPPost-Notify; | Если wait=True, событие OnPostClick возникает только после завершения соответствующей операции, вызванной событием OnClick, в противном случае - немедленно после OnClick

Примечание

> Иногда требуется воспроизвести короткий звуковой сигнал для привлечения внимания пользователя программы - например, после завершения длительного , по времени процесса- обновления данных. Стандартная для Delphi процедура без параметров Веер извлекает сигнал из системного динамика только в том случае, если ПК не оснащен звуковой картой. С другой стороны, мощные возможности компонента TMediaPlayer кажутся излишними для решения этой задачи на ПК, оснащенных звуковой картой. В этом случае может пригодиться API-функция MessageBeep, с помощью которой Windows 32 озвучивает стандартниге диалоговые окна. Единственным параметром обращения к ней является один из следующих идентификаторов стандартного звука: mb_IconAsfcerisk, mb_IconExcla-mation, mb_IconHand, mb IconQuestion, mb Ok. Обращение с параметром $ffffffff игнорирует звуковую карту и извлекает “бип” из системного динамика. Сразу после обращения функция возвращает управление программе и воспроизводит звук асинхронно.

> Значительно более богатыми возможностями в этом отношении имеет, API-функция PlaySound, которая способна воспроизводить любые звуковые клипы.

> Заголовок функции:

> function PlaySound(pszSound: PChar; hmod: HINST;

> fdw.Sound: Cardinal): .Boolean;

> 3десь pszSound - имя воспроизводимого файла; hmod - указывает Экземпляр программы, если звук берется из ресурсного файла ( в противном случае содержит 0); fdwSound - параметр, уточняющий воспроизведение. Его значениями могут быть: snd_async звук воспроизводится асинхронно (функция возвращает управление сразу после обращения к ней); end loop звук воспроизводится постоянно до тех пор, пока не будет .вызвана та же функция с параметром pszSound=0;

> SND_NOSTOP функция пытается воспроизвести звук, если устройство не занято; в противном случае не воспроизводит ничего; если устройство занято, но этот параметр не указан, функция прервет воспроизведение старого звука и начнет воспроизведение нового;

> SND_NOWAIT если устройство занято, функция не будет воспроизводить новый звук;

> SND_PORGE. прекращает, воспроизведение всех звуков для данной задачи;

> SND SYNC воспроизводит звук синхронно и возвращает управление только после полного его воспроизведения.

18.4.4. TOleContainer - контейнер объектов OLE

Компонент является удобным контейнером для размещения связанного или внедренного OLE-объекта. Такие объекты (таблицы, картинки, фрагменты текста и т. п.) на форме Delphi-программы выглядят как обычно или заменяются пиктограммами. Замечательной особенностью OLE-объекта является то, что его активизация (обычно с помощью двойного щелчка мышью) приводит к активизации связанной с объектом программы, которая называется OLE-сервером и которая после загрузки показывает на экране свое окно и предоставляет пользователю средства редактирования объекта.

Типичными OLE-серверами являются такие системные утилиты, как Paint и Notepad, текстовый процессор Word, табличный процессор Excel и др.

Чтобы наглядно продемонстрировать возможности компонента, проделайте следующее.

- Создайте новое приложение с пустой формой и вставьте в нее компонент TOleContainer. Установите в его свойство Align значение alСlient.
- Сохраните проект вместе с формой в каком-либо каталоге и скопируйте средствами Windows в этот же каталог файл Athena, bmp, который находится В каталоге Images | Splash | 16color[ См. замечание в начале главы. ].
- Напишите такой обработчик события OnCreate для формы Form1:

procedure TFormI.FormCreate(Sender: TObject);

begin

{Поскольку в следующем операторе имя файла указано без маршрута поиска, файл 'athena.bmp' должен находиться в каталоге запуска программы!}

OleContainerI.CreateObjectFromFile('athena.bmp',False)

end;

Запустите программу и дважды щелкните по изображению мышью. После паузы, вызванной загрузкой программы-сервера, вы увидите окно, показанное на рис. 18.37.

Рис. 18.37. Пример связывания OLE-обьекта с сервером Paint

Теперь вы можете использовать средства графического редактора Paint для редактирования изображения. Чтобы завершить редактирование, нажмите Esc - окно примет первоначальный вид, но изображение в нем сохранит все внесенные в него изменения.

Не правда ли, весьма впечатляющая демонстрация мощных возможностей компонента: ведь для полноценного доступа к сложной технологии OLE понадобился единственный вызов одного из его методов.

Компонент может создавать как связанные, так и внедренные объекты и открывать окно сервера как в отдельном окне, так и в окне содержащей его программы. В последнем случае при запуске сервера происходит автоматическая замена опций главного меню программы с групповыми индексами 1, 3 и 5 (если они есть) на опции главного меню сервера, а также вставка в окно программы инструментальных панелей сервера. Если компонент открывается в окне программы, его свойство Align (или такое же свойство панели, на которую он помещен) должно иметь значение alClient.

Свойства компонента:

property AllowActiveDoc: Boolean; | Разрешает/запрещает компоненту использовать специализированный интерфейс для документов loleDocumentSite
property AllowInPlace: Boolean; | Определяет способ размещения OLE- сервера. Если имеет значение True и свойство Icon=False, окно сервера с редактируемым объектом размещается в пределах размера компонента, в противном случае создается отдельное окно для сервера (независимо от значения icon)
TAutoActivate = (aaManual, aaGet- Focus, aaDoubleClick) ; property AutoActivate: TAutoActivate; | Определяет способ активизации OLE- объекта: aaManual - активизируется путем программного вызова метода doVerb(ovShow);aaGetFocus - активизирует ся при получении фокуса ввода; aaDouble Click - активизируется при двойном щелчке мышью
property AutoVerbMenu: Boolean; | Если имеет значение True, для компонента автоматически создается вспомогательное меню, содержащее доступные команды OLE-сервера
TBorderStyle = bsNone..bsSingle; property BorderStyle: Tborder Style; | Определяет стиль рамки: bsNone - компонент не имеет рамки; bsSingle - компонент имеет рамку толщиной 1 пиксель
property CanPaste: Boolean; | Содержит True, если буфер clipboard содержит OLE-объект (или связь с ним), который(ую) можно вставить в компонент. Доступно только для чтения
property CopyOnSave: Boolean; | Если содержит True, перед сохранением объекта в файле или потоке он предварительно сжимается для экономии размеров файла (потока). Если в компоненте размещен очень большой объект и динамической памяти может не хватить для создания временной копии сжатого объекта, в свойство следует поместить значение False
property Iconic: Boolean; | Содержит True, если объект будет заменяться пиктограммой OLE-сервера, и False если объект изображается так, как он будет виден в окне сервера
property Linked: Boolean; | Содержит True, если объект связан с программой, и False - если является ее частью (внедрен в нее). Доступно только для чтения
property Modified: Boolean; | Содержит True, если объект был изменен (в том числе заменен другим или уничтожен)
Property Newlnserted: Boolean; | Содержит True, если объект был заново создан с помощью метода insertOb jectDialog. В этом случае вызывайте DoVerb (ovShow), чтобы показать объект в окне сервера. Доступно только для чтения
property ObjectVerbs: TStrings; | Содержит список команд, которые программа может посылать серверу. Доступно только для чтения
property OldStreamFormat: Boolean; | В это свойство следует поместить True перед чтением объекта из файла или потока, если объект был создан версией Delphi 1
property OleClassName: String; | Содержит имя класса, под которым был зарегистрирован OLE-сервер в реестре Windows. Доступно только для чтения
property OleObject: Variant; | Содержит ссылку на OLE-объект
property OleObjectInterface: IQleObject; | Предоставляет доступ к OLE-объекту через интерфейс сloleObject
property PrimaryVerb: Integer; TSizeMode = (smClip, smCenter, smScale, smStretch, smAutoSize) ; property SizeMode: TSizeMode; | Содержит индекс умалчиваемой команды для OLE-объектаОпределяет способ размещения OLEобъекта в контейнере: smClip - отсекаются любые части объекта, выходящие за границы контейнера; smCenter - центрируется в контейнере; smScale - масштабируется так, чтобы целиком заполнить границы контейнера; smStretch - масштабируется так, чтобы не нарушились пропорции объекта; smAutoSize - изменяются границы контейнера, чтобы полностью отобразить объект без искажений
property SourceDoc: String; | Содержит имя файла для связанного объекта
type TObjectState = (osEmpty, osLoaded, osRunning, osOpen, os InPlaceActive, osUIActive); property State: TObjectState; | Определяет состояние OLE-объекта: osEmpty - контейнер не содержит объект; osLoaded - объект загружен, но его сервер не запущен; osRuftning - запущен OLE-сервер; osOpen - объект открыт в отдельном окне; osinPlaceActive - объект открыт в окне контейнера, но сервер еще не заменил опции меню и инструментальные панели программы на свои (промежуточное состояние перед osOIActive); osUIActive -объект открыт в окне контейнера
property Storagelnterface: IStorage; | Открывает доступ к интерфейсу низкого уровня istorage, использующемуся для обращения к API OLE
Методы компонента:
function ChangeIconDialog: Boolean; | Создает и показывает диалоговое окно смены пиктограммы, заменяющей изображение объекта. Возвращает True, если пользователь закрыл окно кнопкой ОК
procedure Close; | Закрывает сервер. Все сделанные к этому моменту изменения в объекте автоматически сохраняются
procedure Copy;rocedure CreateLinkToFile(const FileName: String; Iconic: Boolean) ; | Создает связанный объект по имени файла-FileName. Параметр Iconic содержит True, если изображение объекта заменяется пиктограммой
procedure CreateObject(const OleClassName: String; Iconic: Boolean) ; | Создает внедренный объект по имени класса сервера oleClassName. Параметр iconic содержит True, если изображение объекта заменяется пиктограммой
procedure CreateObjectFromFile(const FileName: String;Iconic: Boolean) ; | Создает внедренный объект по имени файла FileName. Параметр iconic содержит True, если изображение объекта заменяется пиктограммой
procedure CreateObjectFromInfo (const Createlnfo: TCreateInfo); | Создает объект по информации, хранящейся в Createlnfo (см.ниже)
procedure DestroyObject; | Уничтожает объект без сохранения сделанных в нем изменений
procedure DoVerb(Verb: Integer); | Требует от объекта выполнить действие с индексом verb из списка objectVerbs
function GetIconMetaPict: HGlobal; | Возвращает указатель на распределенный в куче метафайл для прорисовки пиктограммы объекта на другой канве
function InsertObjectDialog: Boolean; | Создает и показывает диалоговое окно создания объекта. Возвращает True, если пользователь закрыл окно кнопкой OK
procedure LoadFromFile (constFileName: String); | Загружает объект из файла FileName. Если OldStreamFormat содержит True, загружает объект, созданный с помощью Delphi 1
procedure LoadFromStream(Stream:TStream) ; | Загружает объект из потока Stream. Если OldStreamFormat содержит True, загружает объект, созданный с помощью Delphi 1
function ObjectPropertiesDialog:Boolean; | Создает и показывает диалоговое окно изменения свойств объекта. Возвращает True, если пользователь закрыл окно кнопкой OK
procedure Paste; | Создает объект по данным, хранящимся в буфере Сlipboard
function PasteSpecialDialog: Boolean; | Создает и показывает диалоговое окно специальной вставки объекта. Возвращает True, если пользователь закрыл окно кнопкой ОК
procedure Run; | Запускает сервер, но не активизирует объект. Активизация объекта при запущенном сервере происходит значительно быстрее
procedure SaveAsDocument(const FileName: Strings- | Сохраняет объект в файле FileName с ис пользованием формата OLE Document
procedure SaveToFile(const FileName: String) ; | Сохраняет объект в файле FileName. Если OldStreamFormat содержит True, объект может быть загружен программой, созданной с помощью Delphi 1
procedure SaveToStream(Stream:TStream); | Сохраняет объект в потоке Stream. Если OldStreamFormat содержит True, объект может быть загружен программой, созданной с помощью Delphi 1
procedure UpdateObject; | Обновляет объект, вновь загружая его из источника
procedure UpdateVerbs; | Обновляет список Objectverbs (некоторые команды могут его изменить, например, команда Play может заменить Play на Stop)

Метод СreateObjectFrominfo использует запись типа

type

TCreateInfo = record

CreateType: TCreateType;

ShowAsIcon: Boolean;

IconMetaPict: HGlobal;

ClassID: TCLSID;

FileName: String;

DataObject: IDataObject;

end;

type TCreateType = (ctNewObject, ctFromFile, ctLinkToFile, ctFromData, ctLinkFromData) ;

поля которой имеют следующие назначения:

CreateType | Тип объекта и его источник: ctNewObject - внедренный объект, заданный идентификатором класса ClassID; ctFromFile - внедренный из файла FileName; ctLinkToFile - связанный С файлом FileName; ctFromData - внедренный по данным DataObject; CtLinkFromData -связанный сданными DataObject
ShowAsIcon | Если True, объект изображается пиктограммой
IconMetaPict | Дескриптор глобальной памяти, в которой распределен метафайл для пиктограммы. Если содержит 0 и showAslcon= True, используется стандартная пиктограмма Идентификатор класса сервера
ClassID FileName | Имя файла
DataObject | Данные для объекта

Для компонента определены такие события:

property OnActivate: TNoti-fyEvent; | Возникает сразу после активизации объекта
property OnDeactivate: TNotifyEvent; | Возникает сразу после перехода объекта в неактивное состояние
type TObjectMoveEvent = procedure( OleContainer: TOleCon-tainer; const Bounds: TRect) of object; | Возникает при перемещении или изменении размеров объекта. Параметр Bounds содержит границы объекта в координатах клиентской части контейнера
property On.ObjectMoye: TObjectMoveEvent; property OnResize: TNotifyEvent; | Возникает при изменении размеров окна контейнера