Главная » Delphi » Мастер объектов COM

0

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

1.  Во вкладке  ActiveX диалогового окна New Item дважды щелкните на пиктограм ме ActiveX Library. При  этом  создается новая  библиотека DLL сервера COM,  в которую  можно будет добавлять новые  объекты COM.

2.  Во вкладке ActiveX диалогового окна New Item дважды щелкните на пиктограмме COM Object. Вызывается мастер  создания сервера COM. В диалоговом окне  мас тера введите имя и описание для создаваемого расширения оболочки и выберите вариант модели работы с потоками Apartment. По щелчку на кнопке OK будет соз дан новый модуль, содержащий код для разрабатываемого объекта COM.

Обработчики копирования

Как  уже упоминалось, расширения оболочки, связанные с копированием, позво ляют  устанавливать обработчики,  которые  будут получать  уведомления всякий раз при  выполнении операции копирования, удаления, перемещения или  переименова ния.  После  получения такого  уведомления обработчик может  пресечь выполнение соответствующей процедуры. Учтите, что этот  обработчик вызывается только  для объектов папок и принтеров и не вызывается для файлов и других объектов.

Создание обработчика копирования начинается с создания класса,  производного от класса  TComObject, в котором следует  реализовать интерфейс ICopyHook. Этот интерфейс определен в модуле ShlObj следующим образом:

type

ICopyHook = interface(IUnknown)

[‘{000214EF-0000-0000-C000-000000000046}’]

function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;

pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD;

pszDestFile: PAnsiChar;

dwDestAttribs: DWORD): UINT; stdcall;

end;

Метод CopyCallback()

Как видите, ICopyHook — достаточно простой интерфейс; в нем реализована лишь одна  функция CopyCallback(). Данная функция вызывается при  любых  манипуля циях с папкой. Ниже  описаны ее параметры.

Параметр Wnd — это дескриптор окна,  которое будет использовано обработчиком копирования в качестве родительского для отображаемых им окон.

Параметр wFunc указывает на выполняемую операцию; данный параметр может принимать одно из значений, приведенных в табл. 16.5.

Таблица 16.5. Значения параметра wFunc функции CopyCallback()

Константа

Значение

Назначение

FO_COPY

$2

Копирует файл, задаваемый параметром pszSrcFile, в

новое место, заданное параметром pszDestFile

FO_DELETE

$3

Удаляет  файл,  определяемый параметром pszSrc- File

FO_MOVE

$1

Перемещает файл, определяемый параметром pszSrc-

File, в новое  место,  заданное параметром pszDest- File

FO_RENAME

$4

Переименовывает  файл,  определяемый параметром

pszSrcFile

PO_DELETE

$13

Удаляет  принтер,  задаваемый параметром pszSrc- File

PO_PORTCHANGE

$20

Изменяет порт  принтера. Параметры pszSrcFile и

pszDestFile содержат списки, состоящие из строк,

которые  завершаются  двумя  нулевыми   символами.

Каждый  список  содержит имя принтера, за которым

следует  имя  порта. Имя  порта  из  параметра  psz-

SrcFile является именем порта текущего  принтера,

а  имя  порта из  параметра pszDestFile —   именем

порта нового принтера

PO_RENAME

$14

Переименовывает принтер, задаваемый параметром

pszSrcFile

PO_REN_PORT

$34

Комбинация  параметров  PO_RENAME и   PO_PORT- CHANGE

Параметр  wFlags содержит  флаги,  управляющие  операцией.  Этот  параметр  мо

жет быть комбинацией значений, представленных в табл. 16.6.

Таблица 16.6. Значения параметра wFlags функции CopyCallback()

Константа

Значение

Назначение

FOF_ALLOWUNDO

$40

Сохраняет   информацию   для    отмены действия (если это возможно) (undo)

FOF_MULTIDESTFILES

$1

Вместо одной  папки  для хранения всех исходных файлов функция SHFileOp- eration() определяет множество конеч ных файлов (по одному для каждого  исход ного файла). Обработчик копирования обычно игнорирует это значение

Окончание табл. 16.6.

Константа

Значение

Назначение

FOF_NOCONFIRMATION

$10

В   любом    диалоговом   окне    ответом является вариант Yes to All (Да, для всех)

FOF_NOCONFIRMMKDIR

$200

Если  операция требует   создания новой

папки,  то  подтверждающее  сообщение

отображаться не будет

FOF_RENAMEONCOLLISION

$8

Предлагает           для      файла     новое     имя

(например  Copy  #1  of… (Копия  #1…))

при операциях копирования, перемеще

ния   или   переименования,  если   файл

назначения  с   указанным    именем   уже

существует

FOF_SILENT

$4

Не отображает индикатор процесса

FOF_SIMPLEPROGRESS

$100

Отображает индикатор процесса, но  не

показывает имена файлов

Используются также  следующие  параметры: pszSourceFile — имя исходной пап ки; dwSrcAttribs —  атрибуты исходной папки;  pszDestFile —  имя  папки  назначе ния; dwDestAttribs — атрибуты папки назначения.

В отличие от большинства методов, данный интерфейс  не  возвращает результи рующего  кода OLE. Вместо  этого  он возвращает одно  из значений, определенных в модуле Windows (они перечислены в табл. 16.7).

Таблица 16.7. Значения параметра wFlags, возвращаемые функцией

CopyCallback()

Константа

Значение

Назначение

IDYES

6

Разрешает операцию

IDNO

7

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

IDCANCEL

2

Препятствует    выполнению   текущей    операции  и отменяет все остальные операции

Реализация TCopyHook

Поскольку класс TCopyHook реализует интерфейс лишь с одним методом, его опи

сание выглядит достаточно компактно:

type

TCopyHook = class(TComObject, ICopyHook)

protected

function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;

end;

pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD;

pszDestFile: PAnsiChar;

dwDestAttribs: DWORD): UINT; stdcall;Реализация метода CopyCallback() также невелика по объему. Для подтвержде

ния                выполнения       какой либо     операции       вызывается      функция       API       Win32

MessageBox().  Кстати,  значение,  возвращаемое  методом  CopyCallback(),  анало

гично  значению, возвращаемому функцией MessageBox():

function TCopyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD; pszDestFile: PAnsiChar;

dwDestAttribs: DWORD): UINT;

const

MyMessage: string = ‘Are you sure you want to mess with "%s"?';

begin

// Подтвердить операцию

Result := MessageBox(Wnd, PChar(Format(MyMessage,

[pszSrcFile])), ‘DDG Shell Extension’,

MB_YESNO);

end;

CОВЕТ

Обратите внимание: для вывода сообщений вместо функции Delphi MessageDlg() или ShowMessage() используется функция API Win32 MessageBox(). Причина этого проста: она заключается в размере кода и эффективности его выполнения. Вызов лю- бой функции модуля Dialogs или Forms привел бы к тому, что к создаваемой библио- теке DLL была бы подсоединена значительная часть кода библиотеки VCL. Отказав- шись от использования функций из таких двух модулей, можно существенно сократить размер созданной библиотеки DLL. Примерно на 70 Кбайт.

Возможно, в это трудно поверить, но об объекте TCopyHook сказано все, что нуж но. Да, вот еще одна деталь:  прежде чем использовать любое  расширение оболочки, оно должно быть зарегистрировано в системном реестре.

Регистрация

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

HKEY_CLASSES_ROOT\directory\shellex\CopyHookHandlers

Более  того,  в Windows NT требуется, чтобы  все расширения оболочки были  заре гистрированы как утвержденные (approved). В этом  случае регистрация осуществля ется и в дополнительной ветви:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\

?ShellExtensions\ApprovedДля  регистрации расширений оболочки можно  использовать несколько способов. Они  могут быть  зарегистрированы с помощью  файла  .reg или программы установки. И,  наконец, библиотека DLL с расширением оболочки может  быть  саморегистрирую щейся.  Последнее решение, хотя и требует  несколько больших усилий,  является все же наилучшим, поскольку  при  этом  расширение является самодостаточным пакетом, раз мещенным в единственном файле.

В главе 15, “Разработка приложений COM”, речь  шла о том, что объекты COM все гда создаются из фабрик классов.  В среде  VCL объекты фабрики класса ответственны также  и за регистрацию создаваемого объекта COM. Если объект COM требует  точки входа в системный реестр (как в случае с расширением оболочки), то для их установ ки  достаточно  переопределить  стандартный  метод   UpdateRegistry() фабрики класса.  В листинге 16.9 приведен код модуля CopyMain, содержащего специализиро ванную фабрику  класса для выполнения регистрации.

Листинг 16.9. CopyMain.pas — главный модуль реализации обработчика копирования

unit CopyMain;

interface

uses Windows, ComObj, ShlObj;

type

TCopyHook = class(TComObject, ICopyHook)

protected

function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;

pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD;

pszDestFile: PAnsiChar;

dwDestAttribs: DWORD): UINT; stdcall;

end;

TCopyHookFactory = class(TComObjectFactory)

protected

function GetProgID: string; override;

procedure ApproveShellExtension(Register: Boolean;

const ClsID: string); virtual;

public

procedure UpdateRegistry(Register: Boolean); override;

end;

implementation

uses ComServ, SysUtils, Registry;

{ TCopyHook }

// Этот метод вызывается оболочкой для операций с папками

function TCopyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;

pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD;

pszDestFile: PAnsiChar;

const

dwDestAttribs: DWORD): UINT;

MyMessage: string = ‘Are you sure you want to mess with "%s"?';

begin

// Подтвердить операцию

Result := MessageBox(Wnd, PChar(Format(MyMessage,

[pszSrcFile])), ‘DDG Shell Extension’,

MB_YESNO);

end;

{ TCopyHookFactory }

function TCopyHookFactory.GetProgID: string;

begin

// Идентификатор программы (ProgID) для расширения оболочки

// не нужен.

Result := ”;

end;

procedure TCopyHookFactory.UpdateRegistry(Register: Boolean);

var

ClsID: string;

begin

ClsID := GUIDToString(ClassID);

inherited UpdateRegistry(Register);

ApproveShellExtension(Register, ClsID);

if Register then

// Добавить идентификатор класса (clsid) расширения оболочки в

// раздел CopyHookHandlers системного реестра.

CreateRegKey(‘directory\shellex\CopyHookHandlers\’ +

ClassName, ”, ClsID)

else

DeleteRegKey(‘directory\shellex\CopyHookHandlers\’ +

ClassName);

end;

procedure TCopyHookFactory.ApproveShellExtension(Register: Boolean; const ClsID: string);

// Этот элемент системного реестра необходим для корректной работы

// расширения под управлением Windows NT.

const

SApproveKey = ‘SOFTWARE\Microsoft\Windows\CurrentVersion\

?Shell Extensions\Approved';

begin

with TRegistry.Create do

try

RootKey := HKEY_LOCAL_MACHINE;

if not OpenKey(SApproveKey, True) then Exit;

if Register then WriteString(ClsID, Description)

else DeleteValue(ClsID);

finally

Free;

end;end;

const

CLSID_CopyHook:TGUID = ‘{66CD5F60-A044-11D0-A9BF-00A024E3867F}';

initialization

TCopyHookFactory.Create(ComServer, TCopyHook, CLSID_CopyHook,

‘DDG_CopyHook’, ‘DDG Copy Hook Shell Extension Example’,

ciMultiInstance, tmApartment);

end.Движущей  силой, заставляющей фабрику  класса TCopyHookFactory работать, яв ляется  тот  факт,  что  именно ее  экземпляр, а не  обычный объект TComObjectFactory, создается в разделе инициализации (initialization) этого модуля. На  рис. 16.7 показано, что  происходит при  попытке переименовать папку в системной оболочке после установки библиотеки DLL с расширением копирования.

Рис.  16.7.  Расширение  копирова

ния в действии

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии