Назло блокноту. Или всё для работы с расширениями в Windows с помощью Delphi

Источник: куфдсщвштп

Статья показывает на конкретных примерах, как ассоциировать вашу программу с каким-либо расширением Windows, самому зарегистрировать свое расширение в системе и как добавить пункт в контекстном меню Windows (типа "открыть в...") для открытия документов вашей прогой (по-видимому текстовым редактором:)

Небольшое вступление, которое надо прочитать

Привет всем кодерам! Эта статья посвящается широкому кругу читателей - будь вы новичок в программировании на Delphi или продвинутый кодер. Я надесь, информация, представленная здесь мной, будет вам интересна. Ну да ладно, это так - отступление, приступим к главному, то бишь к кодингу! Но сначала я расскажу вам, зачем стал писать это пособие...

Недавно я закончил делать текстовый редактор. А когда закончил, то подумал, неплохо было бы встроить в Maks Editor (в дальнейшем за этим названием будет подразумеваться мой текстовый процессор) функции ассоциации с различными расширениями Windows, заодно сделать так, чтобы можно было самому регистрировать расширения и прописывать пункты в контекстном меню Windows, отвечающие за запуск документов (типа "открыть в...") моим текстовым процессором!!!

Кто разобрался в том, что я сказал, может пропускать следующие 3 параграфа и читать дальше, кто нет - сейчас объясню суть вышесказанных слов... Помните, когда вы создаете текстовый файл (неважно каким способом), то перед вами раскрывается блокнот (раскрываться может и что-либо другое), и значок вашего файла заменяется значком блокнота (или программы, отвечающей за обработку файлов с расширением .txt). Так вот, за каждое расширение в Windows отвечает одна программа, называемая "программой по умолчанию". Эту программу конечно можно легко изменить для любого расширения: выбираете пункт "открыть с помощью", находите нужную прогу и ставьте галочку - использовать её для всех файлов такого типа.

С ассоциацией расширений вроде бы разобрались - едем дальше. Что значит - самому регистрировать расширения? А это значит, вы должны сказать Windows: "Вот тебе новое расширение, засоси, подруга!" и прописать прогу, которая будет работать с этим расширением - будет "прогой по умолчанию". То есть: зарегистрируете вы расширение .maks, и теперь при каждом открытия файла типа *.maks, будет открываться ваша прога (которую вы, наверное, сами создали) и появляться значок, соответствующий значку проги.

С этим тоже вроде бы всё ясно - прем вперед...Прописка пункта контекстного меню. Ну тут всё легко - в главном контексте Windows создается ваш пункт, при нажатии по которому открывается ваше приложение с содержимым того файла, относительно которого находилось меню. Прогу тоже можно сделать любой.

Так вот, все эти вещи могут понадобиться вам, если вы, например, создаете текстовый редактор. Причем, не обязательно стараться над кодингом редактора - можно просто положить какой-нибудь RichEdit на форму и все... прописать пункт в контекстном меню Виндоуз типа "Открыть с MyEditor". И написать вот это в событие onshow формы:

if (ParamCount > 0) and FileExists(ParamStr(1)) then
RichEdit.LoadFromFile(ParamStr(1)); // если мы сразу открываем файл из Windows, то загружаем его в эдитор

Теперь вы можете легко и быстро работать с документами с помощью вашего эдитора без предварительного инсталлированя его в систему!!! Виндоуз сама опознает поле для редактирования и будет заносить туда данные после открытия!

И запомните, все, что я вам сейчас покажу, требует знаний работы с реестром - но это в принципе не главное. Просто я все делал под Windows XP, а реестр XP и реестр "Леноллиума" - это разные вещи. Поэтому я не даю никакой гарантии, что у вас все будет нормально в другой операционке (я даже с уверенностью говорю, что кроме XP, у вас ассоциация и прочая белиберда вообщей не пойдет в другой системе:~(. Так что если вы читаете это пособие, уютно расположившись в Win 3.1, то можете завязывать чтение (что я вам, конечно не рекомендую, так как материал полезен для упрочнения знаний о строении и работе реестра). И не думайте, что я в этой маленькой статейке расскажу о том, как сделать текстовый редактор, я просто покажу вам по 1 примеру на каждый из этих пунктов:

  1. Как ассоциировать стандартное расширение с прогой
  2. Зарегистрировать свое расширение
  3. Добавить пункт в контексте

И все это сотворить програмно с помощью нашей любимой Delphi.

Объяснять я буду, исходя из устройства Delphi 7, но в других средах этот процесс совсем не будет отличаться, так как модуль Registry действует везде.

Начинаем кодинг (или немного про реестр)

Итак начнем. Запускаем Delphi, создаем приложение, у нас появляется форма. На неё мы ложим RichEdit и изменяем его свойство align на alclient. Тем самым мы растянули его по всей форме. Также лучше стереть надпись "RichEdit1" в его свойстве Lines. Теперь создайте еще 1 форму: нажмите file->new->form. Но эта форма (буду называть её form2) у нас пока что не как не связана с главной формой (form1). Для того, что их хоть как-то связать, откройте окно редактора кода у form1 и добавьте модуль с вашей второй формой: пишете слово unit и идентификатор формы (в данной случае 2).

uses unit2; //обязательно!!!

Соединили, ну все равно, form2 нигде не будет у нас видна при запуске проги. Для этого её надо вызвать. Как вы будете её вызывать, решать вам. Можно создать главное меню сверху и оттуда, но я не буду объяснять, как это делать. Я просто взял и поместил обычную кнопку на RichEdit1 - не слишком правильно, но на виду. Теперь обрабатываем событие onclick кнопки button1 (для этого щелкаем по ней 2 раза).

procedure TForm1.Button1Click(Sender: TObject);
begin
// вызываем форму так, чтобы она оставалась в фокусе, пока мы ее не вырубим
form2.ShowModal;
end;

Все, теперь на form2 ложим несколько компонент: 2 edit'a, 2 checkbox'a, 3 button'a.

Первый Edit будет служить у нас полем ввода для расширения, которое мы хотим зарегистрировать, так что изменим его свойство name на extension. А первая кнопка будет у нас регистрировать это расширение - назовем её createext, вторая кнопка будет это расширение дизинтегрировать (какое слово умное я придумал:) - назовем её deleteext.Первый CheckBox будет служить у нас расширением .txt (я покажу вам пример только с одним расширением, так как работа с остальными расширениями идентична), т.е. если чекбокс включен - стоит крестик, то ассоциируем нашу прогу с расширением *.txt, если выключен - крестика нет, то отменяем интеграцию, прописав блокнот "прогой по умолчанию" (как в начале было:). Так что изменяем его имя на txt. Второй CheckBox будет работать совместно с edit2: в edit2 мы будем вводить пункт в контекстном меню, который нам надо зарегистрировать, а флажок будет указывать нам, создавать этот пункт или удалять (включен - создаем, выключен - удаляем:). Изменяем имя второго флажка на context, а имя второго edit'a на contextstr. Изменения имен я сделал только для удобства (чтобы не запутаться:). И наконец последняя кнопка под именем Gues будет делать... потом узнаете что:)

Итак начнем кодить, но сначала я дам вам некоторую инфу про реестр:

Как вы, наверное, знаете, реестр - это большая база данных вашей системы, в котором очень легко напортачить, а исправить содеянное порой просто невозможно (вообще, я вам сразу советую открыть реестр и держать его открытым до конца кодинга). Так вот в реестре 6 главных разделов, а мы будем работать с разделом HKEY_CLASSES_ROOT - в нем хранятся настройки, отвечающие за регистрацию различных расширений, контекстных меню, названий системных программ (корзины, например) и еще куча всего прочего. Открыв раздел HKEY_CLASSES_ROOT, мы первым дело видим список из 18 зарегистрированных текстовых расширений, которые начинаются со знака ! (!txt, например). Спустившись чуть пониже мы, может найти эквиваленты этих расширений типа .txt (перед названием стоит точка). В этих расширениях мы ссылаемя на расширения типа !txt, которые находятся в самом начале и содержат основную информацию о "программе по умолчанию" и иконке этой проги. Так вот, открываем раздел !txt, с которым мы будем работать, и что же мы видим: раздел defaulticon, в котором содержится строковой параметр с адресом иконки проги + , 0 и раздел типа shell->open->command. В разделе command тоже строковой параметр со значением адреса "программы по умолчанию", после которой стоит "%1". Значит нам нужно только изменить адрес проги и иконки и готово дело. В принципе да, но посмотрите в раздел .txt - в нем хранится строковой параметр со значением, ссылающимя на раздел !txt, т.е. параметр !txt.

Значит нам нужно, чтобы этот параметр тоже присутствовал - вдруг кто-нибудь нечаянно его удалит...

Действие 1: Ассоциация с расширением .txt

Короче приступаем к реализации функции, ассоциирующей нашу прогу и её иконку с расширением .txt. Для этого мы создадим процедуру под названием fileass,а также занесем модуль registry, отвечающий за работу с реестром.

uses registry;// это обязательно
private // заносим ее вот сюда
procedure fileass; // функция заносит все параметры ассоциации с расширением .txt в реестр или удаляет их

Она будет отвечать за интеграцию или дизинтеграцию расширения .txt. Ну впрочем, все понятно из листинга с подробными комментариями:

procedure tform9.fileass;
var reg:TRegistry; // переменная, инициализирующая реестр
begin
if txt.Checked then // если флафок включен, то
begin
// инициализируем реестр
reg := TRegistry.Create;
// устанавливаем главный раздел
reg.RootKey := HKEY_CLASSES_ROOT;
// создается ключ ".txt", если его нет
reg.OpenKey('.txt',true);
// создается параметр со значением "!txt", если его нет
reg.WriteString('', '!txt');
// закрываем этот ключ
reg.CloseKey;
// создается ключ "!txt\DefaultIcon"
reg.OpenKey('!txt\DefaultIcon',true);
// заносится значение параметра "имя приложения, 0" - пиктограмма нашей проги
reg.WriteString('', paramstr(0) + ', 0');
// выходим из ключа
reg.CloseKey;
// создается ключ "!txt\shell\open\command"
reg.OpenKey('!txt\shell\open\command', true);
// создается параметр со значением "имя файла "%1"" - адрес нашей проги
reg.WriteString('', ParamStr(0) + ' "%1"');
// закрываем ключ
reg.CloseKey;
// освобождаем реестр, но настройки сохраняем
reg.Free;
end;

if not txt.Checked then // если флажок отключен,то
begin
// инициализируем реестр
reg := TRegistry.Create;
// устанавливаем главный раздел
reg.RootKey := HKEY_CLASSES_ROOT;
// создается ключ ".txt"
reg.OpenKey('.txt',true);
// создается параметр со значением "!txt"
reg.WriteString('', '!txt');
// выходим
reg.CloseKey;
// создается ключ "!txt\DefaultIcon"
reg.OpenKey('!txt\DefaultIcon',true);
// заносится значение параметра "имя приложения, 0" - пиктограмма блокнота
reg.WriteString('', 'NOTEPAD.exe' + ', 0');
// выходим
reg.CloseKey;
// создается ключ "!txt\shell\open\command"
reg.OpenKey('!txt\shell\open\command', true);
// создается параметр со значением "имя файла %1" - адрес блокнота
reg.WriteString('', 'NOTEPAD.exe' + ' "%1"');
// закрываем ключ
reg.CloseKey;
// освобождаем реестр, но настройки сохраняем
reg.Free;
end;
end;

В принципе все... 1-я (и самая главная) функция готова. Только в адресе иконки я указал адрес программы (paramstr(0)) , потому что я уже подготовил новую иконку, которая обозначает мой текстовый эдитор. Если вы ничего не сделаете. Под расширением .txt будет подразумеваться ваша прога с иконкой Delphi. Так что укажите правильный путь в ключе Defaulticon.

Действие 2: Регистрация своего расширения

Теперь сделаем сами регистрацию расширений (за это, как мы помним, у нас отвечают компоненты extension, createext,deleteext). Для этого мы создадим процедуру newext. А за дизинтеграцию у нас будет отвечать процедура delext. Как всегда добавляем их в раздел PRIVATE и потом описываем.

Private
Procedure fileass;
Procedure newext; // интегрирует наше расширение
Procedure delext; // дизинтегрирует наше расширение

procedure tform2.newext;
var reg:tregistry; // наша переменная для работы с реестром
begin
// инициализируем её
reg:=tregistry.Create;
// устанавливаем начальный раздел
reg.RootKey:=Hkey_Classes_Root;
// создаем ключ типа ".наше расширение"
reg.OpenKey('.'+extension.Text,true);
// записываем в нем ссылку на ключ типа "!.наше расширение"
reg.WriteString('','!'+extension.Text);
// закрываем ключ
reg.CloseKey;
// создаем ключ типа "!.наше расширение\defaulticon"
reg.OpenKey('!'+extension.Text+'\defaulticon',true);
// записываем туда иконку нашей проги
reg.WriteString('',paramstr(0)+', 0');
// выходим
reg.CloseKey;
// создаем ключ типа "!.наше расширение\shell\open\command"
reg.OpenKey('!'+extension.Text+'\shell\open\command',true);
// записываем в него адрес проги
reg.WriteString('',paramstr(0)+' "1"');
// закрываем ключ
reg.CloseKey;
// убираемся, но настройки сохраняем
reg.Free;
end;

Вторая процедурка:

procedure tform2.delext;
var reg:tregistry; // инициализируем переменную для работы с реестром
begin
// создаем класс для работы с реестром
reg:=tregistry.Create;
// устанавливаем начальный раздел
reg.RootKey:=HKEY_CLASSES_ROOT;
// удаляем ключ типа ".наше расширение"
reg.DeleteKey('.'+extension.Text);
// удаляем ключ типа "!наше расширение"
reg.DeleteKey('!'+extension.Text);
// закрываемся
reg.CloseKey;
// вырубаем все, но настройки сохраняем
reg.Free;
end;

Действие 3: Добавление пункта в контекстное меню Windows

Вот и вторая часть нашего доброго дела готова. Осталась последняя, отвечающая за добавление, удаления пункта контекстного меню. За это у нас (а ну ка вспомнили:) отвечают компоненты context и contextstr. Ну я как всегда создал новую процедуру checkcontext и написал в ней...

Private
procedure fileass;
procedure newext;
procedure delext;
procedure checkcontext; // проверяет, нажат ли флажок, в случае успеха создает пункт контекста, в случае неуспеха удаляет его

procedure tform2.checkcontext;
var reg:tregistry; // инициализируем переменную для работы с реестром
begin
// если флажок включен, то
if context.Checked then
begin
// создаем класс для работы с реестром
reg:=tregistry.Create;
// устанавливаем начальный раздел
reg.RootKey:=HKEY_CLASSES_ROOT;
// создаем ключ типа "*\Shell\любое ваше слово"
reg.OpenKey('*\Shell\OpenWithMaksEditor',true);
// записываем в него строковой параметр типа "любое ваше слово"
reg.WriteString('','OpenWithMaksEditor');
// записываем в него строковой параметр типа "пункт контекста"
reg.WriteString('',contextstr.Text);
// закрываем ключ
reg.CloseKey;
// создаем ключ типа "*\Shell\OpenWithMaksEditor\command"
reg.OpenKey('*\Shell\OpenWithMaksEditor\command',true);
// записываем в него строковой параметр типа "command"
reg.WriteString('','command');
// записываем в него также строковой параметр типа"адрес проги+" %1""
reg.WriteString('',paramstr(0)+' "1%"');
// закрываем ключ
reg.CloseKey;
// вырубаем весь контекстный плагин нахрен, а настройки оставляем
reg.Free;
end else
if not context.Checked then // иначе, если флажок отключен
begin
// инициализируем переменную для работы с реестром
reg:=tregistry.Create;
// устанавливаем начальнай раздел
reg.RootKey:=HKEY_CLASSES_ROOT;
// удаление ключа типа "*\Shell\любое слово"
reg.DeleteKey('*\Shell\OpenWithMaksEditor');
// закрываем реестр
reg.CloseKey;
// уходим
reg.Free;
end;
end;

Вот и последняя процедурка готова, как видно, здесь проверяется, включен ли флажок: если включен, то пункт, введенный в context, создается, если выключен, то пункт, который был предварительно создан - удаляется. Но мы еще забыли самое главное: ведь у нас есть только процедуры: а ведь их еще надо подставить куда-нибудь, чтобы они работали. Короче, подставляем процедуру, отвечающую за создание нового расширения (newext) в компонент createext (кнопка), функцию, отвечающую за удаление расширения (delext) в компонент deleteext (кнопка). А процедуру, ассоциирующую вашу прогу с .txt (fileass) и процедуру создания, удаления пункта контекста (checkcontext) в компонент Gues (кнопка) - вот она и пригодилась, она будет закрывать форму, предварительно сделав некоторые изменения, продекларированные выше! Ну конено все функции надо прописать в событии onclick кнопок:

// реакция кнопки на клик мышью - создание расширения
procedure TForm2.createextClick(Sender: TObject);
begin
newext;
end;

// реакция кнопки на клик мышью - удаление расширения
procedure TForm2.deleteextClick(Sender: TObject);
begin
delext;
end;

// реакция кнопки на клик мышью - ассоциация с расширением .txt и создание/удаление пункта в контексте
procedure TForm2.GuesClick(Sender: TObject);
begin
fileass;
checkcontext;
close;
end;

Ну вот в принципе и все... конечно можно было просто записать коды 4 вышесказанных процедур в события onclick кнопок, но это не есть самый удобный способ...

И в заключение приведу весь код проги:

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,registry;

type
TForm2 = class(TForm)
extension: TEdit;
Gues: TButton;
txt: TCheckBox;
context: TCheckBox;
contextstr: TEdit;
createext: TButton;
deleteext: TButton;
procedure GuesClick(Sender: TObject);
procedure createextClick(Sender: TObject);
procedure deleteextClick(Sender: TObject);
private
procedure fileass;
procedure newext;
procedure delext;
procedure checkcontext;
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure tform2.fileass;
var reg:tregistry;
begin
reg:=tregistry.create;
if txt.Checked then
begin
reg := TRegistry.Create;
reg.RootKey := HKEY_CLASSES_ROOT;
// создается ключ ".my"
reg.OpenKey('.txt',true);
// создается параметр со значением "myfile"
reg.WriteString('', '!txt');
reg.CloseKey;
// создается ключ "myfile\DefaultIcon"
reg.OpenKey('!txt\DefaultIcon',true);
// заносится значение параметра "имя приложения, 0" - пиктограмма
reg.WriteString('', application.ExeName + ', 0');
reg.CloseKey;
// создается ключ "myfile\shell\open\command"
reg.OpenKey('!txt\shell\open\command', true);
// создается параметр со значением "имя файла %1"
reg.WriteString('', ParamStr(0) + ' "%1"');
reg.CloseKey;
reg.Free;
end;

if not txt.Checked then
begin
reg := TRegistry.Create;
reg.RootKey := HKEY_CLASSES_ROOT;
// создается ключ ".my"
reg.OpenKey('.txt',true);
// создается параметр со значением "myfile"
reg.WriteString('', '!txt');
reg.CloseKey;
// создается ключ "myfile\DefaultIcon"
reg.OpenKey('!txt\DefaultIcon',true);
// заносится значение параметра "имя приложения, 0" - пиктограмма
reg.WriteString('', 'NOTEPAD.exe' + ', 0');
reg.CloseKey;
// создается ключ "myfile\shell\open\command"
reg.OpenKey('!txt\shell\open\command', true);
// создается параметр со значением "имя файла %1"
reg.WriteString('', 'NOTEPAD.exe' + ' "%1"');
reg.CloseKey;
reg.Free;
end;
end;

procedure tform2.newext;
var reg:tregistry; // наша переменная для работы с реестром
begin
// инициализируем её
reg:=tregistry.Create;
// устанавливаем начальный раздел
reg.RootKey:=Hkey_Classes_Root;
// создаем ключ типа ".наше расширение"
reg.OpenKey('.'+extension.Text,true);
// записываем в нем ссылку на ключ типа "!.наше расширение"
reg.WriteString('','!'+extension.Text);
// закрываем ключ
reg.CloseKey;
// создаем ключ типа "!.наше расширение\defaulticon"
reg.OpenKey('!'+extension.Text+'\defaulticon',true);
// записываем туда иконку нашей проги
reg.WriteString('',paramstr(0)+', 0');
// выходим
reg.CloseKey;
// создаем ключ типа "!.наше расширение\shell\open\command"
reg.OpenKey('!'+extension.Text+'\shell\open\command',true);
// записываем в него адрес проги
reg.WriteString('',paramstr(0)+' "1"');
// закрываем ключ
reg.CloseKey;
// убираемся, но настройки сохраняем
reg.Free;
end;

procedure tform2.delext;
var reg:tregistry; // инициализируем переменную для работы с реестром
begin
// создаем класс для работы с реестром
reg:=tregistry.Create;
// устанавливаем начальный раздел
reg.RootKey:=HKEY_CLASSES_ROOT
// удаляем ключ типа ".наше расширение"
reg.DeleteKey('.'+extension.Text);
// удаляем ключ типа "!наше расширение"
reg.DeleteKey('!'+extension.Text);
// закрываемся
reg.CloseKey;
// вырубаем все, но настройки сохраняем
reg.Free;
end;

procedure tform2.checkcontext;
var reg:tregistry; // инициализируем переменную для работы с реестром
begin
// если флажок включен, то
if context.Checked then
begin
// создаем класс для работы с реестром
reg:=tregistry.Create;
// устанавливаем начальный раздел
reg.RootKey:=HKEY_CLASSES_ROOT;
// создаем ключ типа "*\Shell\любое ваше слово"
reg.OpenKey('*\Shell\OpenWithMaksEditor',true);
// записываем в него строковой параметр типа "любое ваше слово"
reg.WriteString('','OpenWithMaksEditor');
// записываем в него строковой параметр типа "пункт контекста"
reg.WriteString('',contextstr.Text);
// закрываем ключ
reg.CloseKey;
// создаем ключ типа "*\Shell\OpenWithMaksEditor\command"
reg.OpenKey('*\Shell\OpenWithMaksEditor\command',true);
// записываем в него строковой параметр типа "command"
reg.WriteString('','command');
// записываем в него также строковой параметр типа"адрес проги"%1""
reg.WriteString('',paramstr(0)+' "1%"');
// закрываем ключ
reg.CloseKey;
// вырубаем весь контекстный плагин нахрен, а настройки оставляем
reg.Free;
end else
if not context.Checked then // иначе, если флажок отключен
begin
// инициализируем переменную для работы с реестром
reg:=tregistry.Create;
// устанавливаем начальнай раздел
reg.RootKey:=HKEY_CLASSES_ROOT;
// удаление ключа типа "*\Shell\любое слово"
reg.DeleteKey('*\Shell\OpenWithMaksEditor');
// закрываем реестр
reg.CloseKey;
// уходим
reg.Free;
end;
end;

procedure TForm2.GuesClick(Sender: TObject);
begin
fileass;
checkcontext;
end;

procedure TForm2.createextClick(Sender: TObject);
begin
newext;
end;

procedure TForm2.deleteextClick(Sender: TObject);
begin
delext;
end;

end.

Небольшое заключение, которое надо прочитать

Я рассказал вам несколько полезных функций, но не учитывал те глюки, которые вы сразу заметите - например, я не прописывал событие oncreate и onclose формы (ну надо же сохранять настройки, отвечающие за активность флажков в Инифайлах, чтобы не было никаких изменение:). Это все я оставляю вам... на ужин...

 


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=22914