altИногда мне бывает необходимо, чтобы ссылка на мое приложение была в пункте контекстного меню «Отправить». Это меню можно вызвать сплошь и рядом, а значит, я смогу запустить свое приложение из любого места системы. Причем не просто запустить, а передать конкретный файл (ы) для дальнейшей обработки. Например, представь, что ты пишешь программу для отправки файлов. было бы здорово отправить файл путем простого вызова контекстного меню в проводнике и выбора в нем ссылки на твою программу. В этой небольшой заметке, я расскажу тебе о том, как этого можно добиться.

ОТКУДА В ЭТОМ МЕНЮ БЕРУТСЯ ЯРЛЫКИ

Перед тем как окунуться в дебри кодинга рассмотрим небольшую теоретическую часть и узнаем, откуда вообще берется список ярлыков, отображаемых в пункте «отправить». Итак, пункт меню «отправить» представляет из себя обычную папку, расположенную в твоем профиле (т.е. \document and settengs\\sendto).

Сразу напрашивается ответ на вопрос: «Как добавить ярлык на свое приложение в этот заветный список?». Нужно всего лишь создать в этой папке ярлык на твою программу! Никаких лишних телодвижений! Ради спортивного интереса попробуй скопировать в эту папку какое-нибудь приложение (например, созданный в Delphi пустой проект). После этого вызови где-нибудь контекстное меню и убедись, что в меню «отправить» действительно появилась ссылка на твое приложение.

А КАК ЭТО СДЕЛАТЬ КРАСИВО

Да, скопировать свое приложение в эту папку — дело простое и врядли требует пояснений. Вот только, увы, это решение нельзя назвать красивым. Почему? Все же работает! Да, работает, но те же гвозди можно забивать плоскогубцами, а можно молотком. Согласись, последним инструментом это делать удобней? Мы находимся в точно такой же ситуации. Либо будем делать все по- гангстерски (т.е. копировать свою программу в эту папку), либо соблюдать правила.
По правилам, в этой папке должны храниться лишь ярлыки. Ни о каких исполняемых файлах никакой речи и быть не может. Я не знаю, умеешь ли ты создавать ярлыки программно или нет, но буквально через 15 минут ты точно этому научишься!



ПРАКТИКА

Попробуем отодвинуться от теории, и реализуем класс, позволяющий создавать ярлыки в папке «sendTo». Запускай Delphi, создавай новый проект и бросай на форму один компонент TButton. Далее переходи в редактор кода и потрудись переписать код из листингов 1-3. В нем я описал класс, который будет использовать для создания ярлыков.



ЛИСТИНГ 1: КЛАСС ДЛЯ БЫСТРОГО СОЗДАНИЯ ЯРЛЫКОВ

type
TShortcutMaker = class
private
public
procedure CreateShortCut(SpecialFolderCSIDL:Integer; ShortcutName:string);
end;
procedure TShortcutMaker.CreateShortCut(SpecialFolderCSIDL: Integer;
ShortcutName: string);
var
IObject : IUnknown;
ISLink : IShellLink;
IPFile : IPersistFile;
PIDL : PItemIDList;
InFolder : array[0..MAX_PATH] of Char;
TargetName : String;
LinkName : WideString;
begin
TargetName := ParamStr(0) ;
IObject := CreateComObject(CLSID_ShellLink) ;
ISLink := IObject as IShellLink;
IPFile := IObject as IPersistFile;
with ISLink do
begin
SetPath(pChar(TargetName)) ;
SetWorkingDirectory(pChar(ExtractFilePath(TargetName))) ;
end;
SHGetSpecialFolderLocation(0, SpecialFolderCSIDL, PIDL) ;
SHGetPathFromIDList(PIDL, InFolder) ;
LinkName := Format(‘%s\%s.lnk’,[InFolder, shortcutName]) ;
IPFile.Save(PWChar(LinkName), false) ;
end;
ЛИСТИНГ 2: ПРИМЕР ИСПОЛЬЗОВАНИЯ

var
MyShortCutMaker:TShortCutMaker;
begin
MyShortCutMaker := TShortCutMaker.Create;
MyShortCutMaker.CreateShortCut(CSIDL_SENDTO, ‘My Delphi Application’);
MyShortCutMaker.Free;
end;
ЛИСТИНГ 3: ПРИМЕР ОБРАБОТКИ ПЕРЕДАННЫХ ПАРАМЕТРОВ

procedure TForm1.FormCreate(Sender: TObject);
begin
if (ParamCount > 0) then
ShowMessage(ParamStr(1));
end;
ЛИСТИНГ 4: СПИСОК ВСЕХ ВОЗМОЖНЫХ КОНСТАНТ, ОПРЕДЕЛЯЮЩИХ СПЕЦ ПАПКИ

const
REGSTR_PATH_SPECIAL_FOLDERS = REGSTR_PATH_EXPLORER + ‘\Shell Folders’;
CSIDL_DESKTOP = $0000;
CSIDL_INTERNET = $0001;
CSIDL_PROGRAMS = $0002;
CSIDL_CONTROLS = $0003;
CSIDL_PRINTERS = $0004;
CSIDL_PERSONAL = $0005;
CSIDL_FAVORITES = $0006;
CSIDL_STARTUP = $0007;
CSIDL_RECENT = $0008;
CSIDL_SENDTO = $0009;
CSIDL_BITBUCKET = $000a;
CSIDL_STARTMENU = $000b;
CSIDL_DESKTOPDIRECTORY = $0010;
CSIDL_DRIVES = $0011;
CSIDL_NETWORK = $0012;
CSIDL_NETHOOD = $0013;
CSIDL_FONTS = $0014;
CSIDL_TEMPLATES = $0015;
CSIDL_COMMON_STARTMENU = $0016;
CSIDL_COMMON_PROGRAMS = $0017;
CSIDL_COMMON_STARTUP = $0018;
CSIDL_COMMON_DESKTOPDIRECTORY = $0019;
CSIDL_APPDATA = $001a;
CSIDL_PRINTHOOD = $001b;
CSIDL_ALTSTARTUP = $001d;
CSIDL_COMMON_ALTSTARTUP = $001e;
CSIDL_COMMON_FAVORITES = $001f;
CSIDL_INTERNET_CACHE = $0020;
CSIDL_COOKIES = $0021;
CSIDL_HISTORY = $0022;
Кода получилось достаточно мало и сложного в нем ничего нет. Единственное, с чем у тебя могли возникнуть проблемы — неизвестные функции. Вот про них мы сейчас и поговорим. Начнем с CreateComObject.

Функция CreateComObject описана в модуле ComObj. С помощью нее создается объект класса, связанный с идентификатором класса переданным в качестве параметра. В примере я передаю CLSID_ShellLink. CLSID_ShellLink — это и есть идентификатор класса, который представляет из себя обычный GUID. Если говорить применительно к Delphi, то идентификатор соответствует типу TGUID. Можешь открыть модуль ShlObj и попробовать поискать в нем текст по CLSID_ShellLink. Не успеешь вбить, значение как наткнешься на примерно такой текст:

{$EXTERNALSYM CLSID_ShellLink}
CLSID_ShellLink: TGUID = (
D1:$00021401; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
Если функция CreateComObject выполнится успешно, то она вернет ссылку на идентификатор интерфейса типа lUnknown. Надеюсь, общую идею ты уловил. Двигаем дальше. Получив ссылку на интерфейс, тип lUnknown, мы можем инициализировать наши переменные типа ISheellLink и IPersistFile. Обрати внимание, имя типа этих переменных начинается с буквой I, т.е. этот тип является интерфейсом. Чтобы привести IUnknown к IShellLink я использую конструкцию: IObject as IShellLink. Что здесь делает «as»? Открой любую книгу по Delphi и там, в разделе описания основ нюансов ООП этот оператор обязательно упоминается. Обламывает копаться в хелпе? Тогда просто смотря на слово «as» представляй в голове «как». Т.е. условно вышеприведенную конструкцию можно прочитать так: считать IObject как IShellLink. Теперь понятно? Ок!
Все необходимые переменные инициализированы, теперь перейдем к созданию самого ярлыка. Для этого, нужно поработать с интерфейсом IShellLink выполнив несколько его функций:
— SetPath — Путь к приложению, для которого создается ярлык. Мы передаем сюда путь к нашему приложению, который получаем при помощи функции (ParamStr(0)).
— SetWorkingDirectory(); — Рабочая папка. Тут думаю и так все должно быть ясно. Рабочую папку получаем традиционным ExtractFilePath().
Выполнив предыдущие функции, мы сотворим скелет ярлыка. Остается лишь получить путь к спец папке (в нашем случае «Отправить»). Решить эту задачу нам помогут две функции:
— SHGetSpecialFolderLocation — возвращает указатель на структуру ITEMIDLIST, содержащую информацию о специальных папках. Эта функция принимает три параметра:
1) .hWndOwner — зарезирвирован.
2) .nFolder — идентификатор папки, путь к которой хотим получить.
3) .ppidl — указатель на PItemIDList.
— SHGetPathFromIDList — конвертирует идентификаторы путей к специальным папкам в нормальные системные пути. Для работы, функция требует два параметра:
1) .pidl — Ссылка на список идентификаторов, полученных с помощью функции SHGetSpecialFolderLocation.
2) .pszPath — буффер, в который будет помещен полученный путь.

После выполнения функции, в переменной InFolder (ее мы передаем во втором параметре) будет находится путь к специальной папке. Для удобства, я выдираю этот путь в переменную LinkName, предварительно оформив с помощью функции Format. Зная путь к системной папке (напомню, в нашем случае это «Отправить») ни что нам не мешает окончательно создать ярлык. Делается это при помощи функции Save интерфейса IPersistFile. Все, наш ярлык готов!

ТЕСТИРОВАНИЕ

Попробуй запустить пример и произвести тест. Нажав на одну единственную кнопку, ты создашь ярлык в папке «Отправить». Классно? А главное все просто! Ради интереса, передай методу нашего класса другой идентификатор системной папке (см. третий листинг), запусти приложение и опять кликни на кнопку. Результат не заставит себя ждать — в указанной тобой папке появится ярлык на твое приложение.

News Reporter