Пятница, 2024-05-17, 9:56 AM
Главная страница | Регистрация | Вход Приветствую Вас заблудившийся пакет | RSS
Меню сайта

Категории каталога
Программирование [58]
.. все с этим делом связаное..
Нейронные сети [4]
Нейронные сети, использование алгоритмы роботы
OC [6]
Unix, FreeBSD, Windows, Linux Описание, совети, секреты, настройки
WEB [25]
web-programming и все с этим связаное
Сети [2]
Описание сетей, сетевых технологий, настройки и некоторые секреты
Мабила [9]
Описание мобильных технологий, программинг под мабилу, и просто интересные моменты
Разное [10]
то что не вошло в другие категории.. прикольные истории про программеров и деятелей информационной индустрии
История [6]
История этого компьтерного мира и некоторых ее учасников
FREE [3]
free on the web..

Наш опрос
Оцените мой сайт

Результаты · Архив опросов

Всего ответов: 129

Начало » Статьи » Программирование

Расширь контекст
Расширение системного контекстного меню Windows

Расширение оболочки — удивительно мощный элемент Windows, позволяющий разработчику создавать максимально комфортные и удобные для пользователя приложения. Ты постоянно встречаешься с разными его проявлениями — например, с новыми пунктами контекстного меню: "Проверить" — у антивируса, "Extract" — у WinRAR, новые тулбары в панели задач и т.д. В этом материале я покажу, как легко с помощью Delphi создать свои расширения, добавив пункт "Зашифровать" к контектному меню всех файлов.

[COM-объекты]

Начнем мы, пожалуй, с того, что любое расширение оболочки реализуется с помощью COM-объекта. COM или Component Object Model (Модель Многокомпонентных Объектов) является основой для технологий ActiveX и OLE. COM определяет API и двоичные стандарты для связи объектов, не зависящих от языка программирования или платформы. COM-объект имеет один или несколько интерфейсов, которые, по сути, представляют собой таблицы функций, связанных с этим объектом. COM определяет стандарты для расположения в памяти функций объектов — они располагаются в виртуальных таблицах. Описание каждой виртуальной таблицы в языке программирования называется интерфейсом. Все COM-интерфейсы неясно выведены из интерфейса IUnknown, который в модуле System определен так:

type

IUnknown = interface

['{00000000-0000-0000-C000-000000000046}']

function QueryInterface (const IID: TGUID; out Obj): Integer; stdcall;

function _AddRef : Integer; stdcall;

function _Release: Integer; stdcall;

end;

Встречаются следующие расширения оболочки:

* Обработчики контекстных меню — реализуются двумя интерфейсами: IContextMenu и IShellExtInit. Позволяют добавлять новые пункты в контекстное меню файловых объектов оболочки.

* Обработчики перемещений — реализуются интерфейсом ICopyHook. Они позволяют контролировать и отменять копирование, перемещение, удаление и переименование.

* Обработчики перетаскивания правой кнопкой мыши — реализуются, как и обработчики контекстных меню, двумя интерфейсами: IContextMenu и IShellExtInit, но они добавляют новый пункт в контекстное меню, которое появляется при перетаскивании объекта в новое место, с помощью правой кнопки мыши.

* Обработчики страниц свойств — реализуются интерфейсами IShellPropSheetExt и IShellExtInit. Позволяют добавлять новые страницы в диалоговые окна свойств файлов.

* Обработчики пиктограмм — реализуются интерфейсами IExtractIcon и IPersistFile. Этот обработчик позволяет присваивать одному типу файлов различные пиктограммы.

* Обработчики цели — реализуются интерфейсами IDropTarget и IPersistFile. Определяют действия оболочки при перетаскивании одного объекта оболочки на другой.

Нам же сегодня потребуется только обработчик контекстных меню. Для того чтобы добавить свой пункт в меню, необходимо создать COM-объект. Он будет реализован в виде динамически подключаемой библиотеки, в основе которой лежат два интерфейса: IShellExtinit и IContextMenu. Прежде всего, после вызова контекстного меню, обработчик должен быть инициализирован. Делается это при помощи интерфейса IShellExtinit, у которого только один метод Initialize. Сразу после инициализации происходит вызов TContextMenu.QueryContextMenu (Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): hResult – он добавляет новый пункт в меню. Параметры этого метода означают:

* Menu — дескриптор системного меню.

* IndexMenu — номер строки меню, в которую следует вставить пункт.

* IdCmdFirst,IdCmdLast — диапазон допустимых значений для идентификаторов вставляемых пунктов меню.

* uFlags — набор флагов.

Далее идет вызов метода TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HRESULT – этот метод предназначен для получения подсказки для конкретной команды меню. Параметры:

* idCmd – идентификатор пункта меню, соответствует IdCmdFirst.

* uType - запрашивает тип информации: GCS_VERB или GCS_HELPTEXT.

* pwReserved – забронирован.

* pszName – определяет буфер-строку.

* cchMax – определяет размер буфера.

Когда происходит нажатие нашего пункта, то вызывается ContextMenu.InvokeCommand, в котором мы опишем, что должно происходить. Параметром этого метода является лишь запись типа TCMInvokeCommandInfo. Вот поля записи:

* cbSize – определяет размер структуры (sizeof (TCMInvokeCommandInfo))

* hwnd – определяет окно, которое будет владельцем всех окон.

* fMask – определяет, заданы или нет параметры dwHotkey/hicon.

* lpVerb – определяет вызываемую команду.

* lpParameters – параметры (опция).

* lpDirectory – рабочая папка (опция).

* nShow – флаг передаваемый ShowWindow (SW_*).

* dwHotKey – горячая клавиша, ассоциированная с приложением после вызова (опция).

* hIcon – определяет иконку (опция).

* hMonitor – определяет монитор по умолчанию (опция).

Мы рассмотрели все методы двух интерфейсов, необходимых нам непосредственно для создания COM-объекта, но чтобы он заработал, нам нужно его еще зарегистрировать. Для этого нужно создать такие значения в реестре:

1. HKEY_CLASSES_ROOT\CLSID\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}- регистрирует наш COM-сервер.

2. HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\ContMenu\CLSID, вместо CLSID – наш номер. Эта запись указывает на то, какие типы файлов будет вызывать наш обработчик (в данном случае * - для любого файла).

3. HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved – это значение разрешает использовать нашу DLL и погружает ее в ОЗУ сразу же после первого вызова.

[шифруем]

Я не стал заморачиваться с изучением сложных криптоалгоритмов и решил, что отпимальнее всего будет просто заксорить файл. Алгоритм шифрующей процедуры в этом случае нарисовался такой: открываем файл, считываем один байт, ксорим его и записываем на то же место. В итоге мы получим файл той же длины, с тем же названием, но байты в нем будут совсем другими. Чтобы получить исходный файл, нам нужно просто проксорить его по новой. Да, кстати, так как мы будем все это делать для нетипизированных файлов, то для записи/чтения нужно использовать процедуры BlockRead и BlockWrite. Они объявляются так:

Procedure BlockRead(var F: File; var Buf; Count: Integer[; var Result: Integer]);

Procedure BlockWrite(var F: File; var Buf; Count: Integer[; var Result: Integer]);

F – переменная нетипизированного файла, Buf – переменная, где хранится прочитанные данные, Count – количество записей, которые нужно считать (в нашем случае 1), Result означает, сколько на самом деле записей было прочитано/записано. Впрочем, все лучше увидеть на примере:

procedure Shifr (FFileName: string);

// FFileName – это имя файла, которое будем шифровать

var

F: File;

BRead, BWritten, TotalRead : Integer;

Buf: Byte;

begin

AssignFile(F,FFileName);

Reset(F,1); // открываем для чтения/записи

try

TotalRead:=0; // количество всех прочитанных байт

repeat

// считываем в Buf 1 байт из F

BlockRead(F,Buf, 1, BRead);

if BRead > 0 then

begin

// ставим указатель перед последним прочитанным байтом

seek(F,TotalRead);

Buf:=Buf xor 7; // ксорим семеркой

BlockWrite(F,Buf, BRead, BWritten); // записываем уже зашифрованный байт

if BRead <> BWritten then

// если количествово прочитанных байт <> количествуву записанных

raise Exception.Create('Ошибка при шифровании!')

else begin

TotalRead:= TotalRead + BRead;

end;

end;

until BRead=0;

finally

CloseFile(F);

end;

Реализуем все прочитанное

Теперь мы разобрали все необходимое, поэтому я предлагаю открыть пример расширения контекстного меню из поставки Delphi (Borland\Delphi7\Demos\ActiveX\ShellExt\contmenu.dpr) и отредактировать его. Для начала в Class_ContextMenu изменим значение TGUID на любое другое. В TContextMenu.QueryContextMenu пункт InsertMenu 'Compile...' меняем на название нашего пункта, то есть "Зашифровать". Далее идет GetCompilerPath. Эту функцию благополучно удаляем, и на ее место вставляем нашу — Shifr. Как известно, TContextMenu.InvokeCommand выполняется после нажатия на наш пункт в меню, поэтому мы здесь напишем только Shifr (FFileName), а остальное удалим :). Ну, с TContextMenu.GetCommandString тоже все ясно, так что оставляем без изменений. А вот TContextMenuFactory.UpdateRegistry нужно подправить: просто все пути в реестре меняем на свои. Вот и все, делать больше нечего... теперь компилируем и получившуюся DLL кидаем, например, в C:\WINDOWS\system32. А что дальше? А дальше запускаем cmd, набираем Regsvr32 C:\WINDOWS\system32\ContMenu.dll — и наше расширение готово к работе! Для того чтобы отменить регистрацию, достаточно выполнить Regsvr32 /u C:\WINDOWS\system32\ContMenu.dll.

Открываем любую папку, щелкаем по любому файлу — и любуемся новым пунктом в меню!

Вот таким несложным образом можно добавить свой пункт в любой тип файлов. А если хочется и иконку добавить рядом с пунктом (как у WINRAR), то для этого нужно использовать не только IContextMenu, но и IContextMenu3.

Вот, собственно, и все. Если что-то непонятно, то пиши на мыло.

Уникальные идентификаторы

GUID представляет некоторое 128-разрядное целое число, используемое в технологии COM для уникальной идентификации интерфейсов. GUID генерируется при помощи API-функции CoCreateGUID(), а алгоритм генерации нового GUID основывается на комбинации следующей информации: текущая дата и время, частота процессора, номер сетевой карты. Если на компьютере установлена сетевая карта, то сгенерированный на этом компьютере GUID будет действительно уникальным, так как уникальность сетевой карты гарантируется встроенным в нее глобальным идентификатором (ID). Если же на компьютере нет сетевой карты, то ее номер можно заменить другим, синтезировав его с помощью параметров другого установленного в компьютере оборудования.

Источник: http://xakep.ru

Категория: Программирование | Добавил: X-SAM (2006-07-27) | Автор: Алексей Соколов aka Aggressor
Просмотров: 964 | Рейтинг: 0.0

Всего комментариев: 0
Имя *:
Email *:
Код *:

Украинская Баннерная Сеть
Поиск по каталогу

Кнопки друзей

Статистика
Рейтинг сайтов Powered by MyPagerank.Net

Copyright DEBUGGER © 2007 Используются технологии uCoz