Главная » Delphi » Запуск файлов из приложения

0

Для этого сначала преобразуем имя файла в как бы HTML-ссылку. Процедуру createHTMLtext мы перепишем так:

procedure createHTMLtext(stnum,stl,st:string); begin

if FileExists(ftempname) then

append(ftemphtm) else exit; (вдруг его удалили?!

stl: ='<B>1 +stnum+ ‘<A HREF="’+stl+’">,+stl+

,</A></B><I>’+st+'</I><BR>';

write(ftemphtm,stl); (строка с именем файлаI

write(ftemphtm,stText); (выводим строку с текстом)

closefile(ftemphtm);

end;

По этой процедуре у нас будет из имени формироваться "ссылка", а номер файла и последующий текст останутся просто текстом с соответствующим форматированием. Теперь внесем изменения в процедуре поиска SearchFiie. Там, где у нас формировались строки для последующей записи в ftempname (перед самым концом цикла), изменим текст на такой:

st:=’ кодировка:’+st;

stl:=IntToStr(nfile)+’. ‘; (номер найденного файла} createHTMLtext(stl,fname,st);

Отсюда, кстати, понятно, зачем я в данном случае изменил своему правилу и передавал в createHTMbtext строки через параметры, а не через глобальные переменные, как обычно— в случае чего строки легко поменять местами. А по окончании цикла мы вовсе откажемся от вызова createHTMbtext, нам ссылки выводить уже не надо, и по большому счету достаточно всего одной строки "Поиск закончен" с меткой:

st: =’ <BR><BxA name=" 1 ">Поиск закончен</А></В>’ ; stl:=”; stText: = ”;

append(ftemphtm); Iэто вместо createHTMbtextj write (ftemphtm, st) ; {вывомж строку с текстом) closefile(ftemphtm);

"Ссылки" мы имеем, а что с ними делать? Для того чтобы запустить навигацию по ссылке из компонента WebBrowser, надо использовать событие onBeforeNavigate2 (существовали ли в природе события BeforeNavigateO н BeforeNavigatel — не спрашивайте, не в курсе). Найдите это событие на закладке Events для WebBrowseri (оно самое первое по списку) и создайте обработчик. Само событие возникает при любых попытках изменить содержимое окна браузера— например, оно возникнет и при вызове метода Navigate, что мы делаем регулярно, и эти вызовы для нас явно лишние, так что придется придумывать, как их обойти. Из всего чудовищного количества параметров, которые передаются в процедуре WebBrowseriBeforeNavigate2, нас интересует только два: url и Cancel. Если второму параметру придать внутри процедуры значение True, то никаких изменений в окне браузера не произойдет. Но перед этим можно сделать что-то полезное, чем мы и воспользуемся — ведь по- настоящему у нас нет никаких ссылок в смысле сетевых адресов, а есть только имя дискового файла, которое через параметр URL и передастся. Вместо того чтобы заставлять браузер пытаться загрузить адрес файла на диске (чего он сделать не сможет, как будто между файлом в Сети и файлом на вашем диске есть принципиальная разница— а ведь помнится, кто-то самый богатый в мире твердил о полной интеграции Web-функций в систему, не так ли?), мы будем вызывать функцию sheliExecute, выполняющую то действие, которое в системе с данным файлом ассоциировано. И даже если не ассоциировано, то мы найдем выход— запустим стандартный диалог Windows "Открыть с помощью".

Чтобы процедура не выполнялась, когда мы сами вызываем метод Navigate для обновления окна браузера, можно воспользоваться тем, что мы всегда передаем ему имя нашего временного файла (один раз с добавкой метки #1).

и отфильтровать соответствующие события. По мы поступим более грамотно. В начале поиска, перед оператором Timeri. Enabled: =тrue, мы сделаем вид, что процедуры WebBrowserlBeforeNavigate2 вообще Не существует:

WebBrowserl. OnBeforeNavigat;e2 :=nil;

А по окончании цикла поиска в самом конце процедуры searchfiie запишем:

Application.ProcessMessages;

WebBrowserl.OnBe?oreNavigate2:=WebBrowserlBeforeNavigate2;

Обработку событий В системе (Application. ProcessMessages) МЫ Здесь вставили еще раз вот почему: может случиться так. что браузеру будет отдана команда Navigate (см. выше по тексту процедуры), а при смене отображаемых страничек он будет се выполнять с еще большей неторопливостью, чем обычно, и обратится к поиску процедуры BeforeNavigate2 уже тогда, когда она будет реально для него существовать (сама процедура searchFile закончится), в результате чего она выполнится, когда нам этого еще вовсе не надо.

Теперь заполним собственно обработчик OnBeforeHavigate2:

procedure TForml.WebBrowserlBe?oreNavigate2(Sender: TObject; const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData, Headers: OleVariant; var Cancel: WordBool); begin {когда браузер хочет Navigate}

if 3hellExecute(Self.Handle, ‘open’,Pchar(AnsiUppercase(URL)), nil, nil, SW_SHOWMAXIMIZED)<=32

then

begin {если <32 - ошибка, вызываем диалог "Открыть с помощью",’ st:=’shell32.dll,OpenAs_RunDLL ‘ +s t ; ShellExecute(Self.Handle, ‘open1,’rundll32.exe’, Pchar(st), nil, SW_SHOWNORMAL);

end;

Cancel:=True; (и дальше ничего не делаем} end;

Функция ShellExecute содержится в модуле ShellAPI, поэтому вам придется включить его в предложение uses. Тогда при щелчке мышью на "ссылке" с именем файла у нас запустится нужное приложение и загрузит его. Если это файлы без расширений или с незарегистрированными расширениями, то про- грвмма предложит с таким-то файлом что-нибудь сделать. Во всем этом деле есть один нюанс: исполняемые файлы мы исключили из рассмотрения, но такие, например, типы файлов, как ВА Г или JS (в сущности, тоже просто текстовые файлы) попытаются выполниться. Можно попробовать их также отфильтровать, но всего все равно не предусмотришь, так что надо будет оговорить это в Справке. Кстати, кроме всего прочего, правая кнопка мыши при щелчке на "ссылке" будет нормально работать, вызывая обычное в таких случаях меню — т. е. вы можете, например, скопировать файл в другое место через пункт Сохранить объект как или даже что-то напечатать (а вот пункт Скопировать ярлык работать не будет).

Но это не все. Что нам делать с сохраненными файлами-результатами поиска? Ведь при загрузке в обычный браузер ссылки останутся недействующими. Поэтому нам придется немного потесниться, и установить справа внизу кнопочку Загрузить результаты (Button4). Создавать сейчас меню только для одного пункта мы не будем, а позже все равно его создадим для настроек и справки, и тогда перенесем функцию кнопки в него. У компонента Label2 с установленным в True свойством AutoSize придется ограничить длину (в пункте Constraints | MaxWidth ввести значение 530 — как раз до кнопки). Кроме этого, на форму придется установить компонент OpenDialog с тем же фильтром, что и у диалога сохранения, и написать следующий обработчик события нажатия кнопки:

procedure TForml.Button4Click(Sender: TObject); begin (загрузить результаты) WebBrowser1.OnBeforeNavigate2:=nil; If OpenDialogl.Execute then

WebBrowserl.Navigate(Pchar(OpenDialogl.FileName)); Application.ProcessMessages;

WebBrowserl.OnBeforeNavigate2:=WebBrowserlBeforeNavigate2; end;

А чтобы кнопка не создавала нам проблем во время поиска, мы в начале процедуры поиска ее дезактивируем:

Button3.Enabled:=True; {активируем Отмену) Button2.Enabled:=False; (дезактивируем Поиск) Button4.Enabled:=False; (дезактивируем Результаты)

А в конце снова активируем:

Button2.Enabled:=True; (активируем Поиск) Button4.Enabled:=True; (активируем Результаты) Button3.Enabled:=False; (дезактивируем Отмену)

Излишне добавлять, что указанный метод вызова sheiiExecute годится, естественно, в любом случае, когда нужно вызвать внешнюю программу— не обязательно это делать столь заковыристым путем через браузер. Но вот работоспособность программы во всех версиях Windows я гарантировать не могу: все, что касается WebBrowser, явно должно быть как-то связано с конкретной версией Internet Explorer (у меня 6.0). Причем без больших хлопот я не могу даже проверить работоспособность всего этого, например, в Internet Explorer4 или Internet Explorers— ведь вернуться на предыдущую версию Internet Explorer нельзя без полной переустановки Windows. Остается только надеяться, что все будет "в абажуре", а если нет — при необходимости можно запретить запуск программы в чуждой ей среде.

Источник: Ревнч Ю. В.  Нестандартные приемы программирования на Delphi. — СПб.: БХВ-Петербург, 2005. — 560 е.: ил.

По теме:

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