WEB форумы на jedi
[Форум] [Помощь] [Поиск] [Выйти]
Добро пожаловать, [info]User

WEB форумы на jedi [ПОИСК] [Архив до 03.2006]

Тема ПАМАЖИТЕ!! ShellExecute в DELPHI К предыдущему сообщению На следующее сообщение Программирование

Отправил olamot в 22:27 26.11.2004[Ответить]
Задача такая. В одной папке
существует два файла с одним названием, но с разным расширением.
Допустим: Файл.wav и файл.bmp
На форме есть FileListBox он отображает файлы *.wav. На клик по
файл лист боксу Прога читает Полный путь к файлу файл.wav.
Теперь она должна вызвать Фонограф и в него загрузить файл.wav
(Путь к файлу записан в переменную WavName:string)
begin
ShellExecute(Handle,'open','SndRec32.exe',Pchar(WavName),nil, SW_SHOWNORMAL);
end;
Все работает великолепно!!! НО дальше нужно вызвать любимый msPaint
и в него загрузить файл.bmp
Для этого я стер из WavName 4 последних символа (.wav)
a:=WavName;
n:=pos('.wav',a);
Delete (a,n,4);
И добавил вместо .wav требуемое .bmp, получил тот же путь
только к файл.bmp. и Обозвал это PixName Логично?
Теперь пишу вызов проги Пэйнт и загружаю в нее файл
begin
ShellExecute(Handle,'open','MsPaint.exe',Pchar(PixName),nil, SW_SHOWNORMAL);
end;
ПОЛУЧАЮ ПОЛНЫЙ ПЭ!!!!
и надпись что файл C:Program.bmp не найден! ПОЧЕМУ ПЭИНТ ИЩЕТ ЭТОТ ФАЙЛ
А НЕ ТОТ КОТОРЫЙ НУЖНО, ДА ЕЩЕ И В ДИРЕКТОРИИ, КОТОРУЮ ЕМУ НИКТО НЕ ЗАКАЗЫВАЛ!!

ЕЩЕ НЕМНОГО И Я СОЙДУ С УМА!!!
ВНИМАЕИЕ!!! Другие функции, использующие полученный путь PixName работают.


Отправил GoodMaker в 23:18 26.11.2004[Ответить]
есть еще функция WinExec() она непосредственно запускает екзешник и передает ему параметры, но это врядли поможет...
а так попробуй пуск/выполнить/mspaint.exe [путь к товему файлу]
если все нормально то ищи баг у себя в коде.
P.S. на делфи можно более простым способо расширение менять ;) поищи по функциям ExtractFileName, ExtractFileExt.. название ее ChangeFileExt... возможно именно в этом и дело...


Отправил Mighty в 23:30 26.11.2004[Ответить]
перед
ShellExecute(Handle,'open','MsPaint.exe',Pchar(PixName),nil, SW_SHOWNORMAL);
сделай ShowMessage(PixName); узнаешь значение этой переменной..может легче станет?


Отправил olamot в 23:42 26.11.2004[Ответить]
Не знаю что и думать. Другие- то компоненты понимают полученный ПУТЬ и работают корректно, только ShellExecut крутит мозги. Я ему вместо Paint подсовывал ACDsee!!! и та же лабуда- открывается ACDsee и лезет в корневую директорию. Открывает первый попавшийся BMP файл!!! чудеса %)


Отправил Mighty в 23:54 26.11.2004[Ответить]
RTFM:
HINSTANCE ShellExecute(
....
LPCTSTR lpParameters, // pointer to string that specifies executable-file parameters
...
LPCTSTR lpParameters, - указатель - то, что в даннный момент содержится в ячейке памяти под _именем_ PixName, видимо в процессе исполнения кода указатель меняет точку входа..Совет, если обращаешся к указателям, убедись что он указывает именно на тот путь..Я обычно далаю так - при запуске программы

public
{ Public declarations }
end;

var
Form1: TForm1;
sPath:string;

procedure TForm1.FormCreate(Sender: TObject);
begin
GetDir(0,sPath);
if sPath[LENGTH(sPath)]<>'' then sPath:=sPath+'';
end;
После этого в любой точке программы я имею жестко прописанный путь к дирекиторию запуска..Ну тебе никто не мешает в начале определить таким образом путь к директорию с медиа файлами..Потом долько имя файла дописываешь и думаю проблем не будет...


Отправил olamot в 23:55 26.11.2004[Ответить]
Сделал ShowMessage(PixName); Выдает идеальный ответ. нажимаю ОК и ННННА! в оба глаза... таже хрень


Отправил GoodMaker в 23:56 26.11.2004[Ответить]
winexec пробуй


Отправил olamot в 00:56 27.11.2004[Ответить]
Применил WinExec. Картина повторяется. пока без параметров Прога грузится, как ей подвешиваю файл продолжает изумлять...
Пойду я голых баб посмотрю...
Может СканДиском проверить :/ голову


Отправил Mighty в 03:00 27.11.2004[Ответить]
1) Попробуй вместо указателя PixName прописать настоящий путь..
2) А что значит >ShowMessage(PixName); Выдает идеальный ответ.
Расшифровка идеальный интересует?


Отправил olamot в 11:03 27.11.2004[Ответить]
Я сделал такой шоумесэдж: ShowMessage ('*'+PixName+'*');
Т.е. Озвездил дополнительно края (на случай, если там чего прицепилось по краям, то видно будет- пробел или еще че)
Ответ получился такой, какой и просил: *Путь*

Если прописываю путь ЯВНО все работает.


Отправил GoodMaker в 11:18 27.11.2004[Ответить]
хватит мозги пудрить... если все верно делаешь то все должно работать... 1) Винду переустанавливай
2) Смени паинт на другой редактор


Отправил olamot в 12:32 27.11.2004[Ответить]
Уважаемые! Я написал этот код в отдельный проект (там 10 строк)
С комментариями АВТОРА (поклонился)
если кому-то интересно разрулить этот вопрос я скину на мыло.
Там самораспаковывающийся ЗИП на 220 кб.
Ну ИНТЕРЕСНО же!!
Тока внимание! Екзешник компилён на Дельфи 5.


Отправил deadman в 13:32 27.11.2004[Ответить]
Могу тебе точно сказать проблема не в ShellExecute. Попробуй выполнить mspaint с диска на котором установлена Windows (у меня c:). Например выполнив такое:
mspaint C:Program FilesBorlandDelphi7Projects111pause_gray.bmp

Я получил ответ
Файл c:Program.bmp не найден.

Из чего делаем вывод ты хочешь что-то передать mspaint но передаёшь не так. В смысле ты даёшь ему строку разделённую на две!

Попробуй так:

mspaint C:Program FilesBorlandDelphi7Projects111pause_gray.bmp

Обязательно с кавычками!!! Ошибка исчезает.


Отправил deadman в 13:49 27.11.2004[Ответить]
Соответственно и в программе используй PixName с кавычками.

Например:

ShellExecute(...., PChar(''+PixName+''), .....);

Т.е. '' - означает ' '


Отправил olamot в 13:56 27.11.2004[Ответить]
ФЕЕРИЧНО!!!!!! ПОТРЯСАЮЩЕ!!!!!!!!! ЭТОТ МЕГАЧЕЛ ГЕНИЙ!!!!
Смотрите и учитесь!!!
строку пишем так:

ShellExecute(Handle,'open','MSPaint.exe',Pchar(''+PixName+''),
nil, SW_SHOWNORMAL);

ЗАРАБОТАЛА!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
как допишу прогу- пришлю!

----------------------------------------------------------------
Но есть еще вопрос, лично к вам, Юрий :)
Как запустить окно PAINT в модальном режиме, те чтобы все, сто под ним не реагировало на мышь, пока его не закроют.


Отправил deadman в 14:03 27.11.2004[Ответить]
Спасибо конечно :) Всегда рад помочь...

Насчёт второго вопроса понял. Счас проведу полевые испытания...


Отправил deadman в 14:12 27.11.2004[Ответить]
Может Вам это будет и не нужно, но в Microsoft Developer's Reference описаны следующие команды:

SW_HIDE
Hides the window and activates another window.

SW_MAXIMIZE
Maximizes the specified window.

SW_MINIMIZE
Minimizes the specified window and activates the next top-level window in the Z order.

SW_RESTORE
Activates and displays the window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when restoring a minimized window.

SW_SHOW
Activates the window and displays it in its current size and position.

SW_SHOWDEFAULT
Sets the show state based on the SW_ flag specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application. An application should call ShowWindow with this flag to set the initial show state of its main window.

SW_SHOWMAXIMIZED
Activates the window and displays it as a maximized window.

SW_SHOWMINIMIZED
Activates the window and displays it as a minimized window.

SW_SHOWMINNOACTIVE
Displays the window as a minimized window. The active window remains active.

SW_SHOWNA
Displays the window in its current state. The active window remains active.

SW_SHOWNOACTIVATE
Displays a window in its most recent size and position. The active window remains active.

SW_SHOWNORMAL
Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when displaying the window for the first time.

Как можно увидеть ни в одной из комманд данной возможности нет. Где-то я такой вопрос уже слышал. Можно попробовать другими функциями. Счас пороюсь может найду...


Отправил olamot в 14:24 27.11.2004[Ответить]
Да, я именно это и имел в виду:
Среди этих команд нет того, что нужно.


Отправил deadman в 14:38 27.11.2004[Ответить]
Прочти следующее:
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1099470894&n=5

Может поможет :). Если нет поищу ещё...


Отправил olamot в 14:49 27.11.2004[Ответить]
Хммм. Я новичек и до этого момента старательно пытался обходить такие дела, как контроль над процессами. Даже думать как они устроены внешне, не хотелось. Наверно настала пора...
Видимо (прощенья, если это ересь), при запуске внешнего приложения в своем параметр Enedled ставить в false а при завершении внешнего в true.

Но будет ли запущенное приложение оставаться сверху?
Нет ли заранее ответа? если нет- полезу разбираться... это долго будет :)))

Спасибо! Если что-то найдется вешай сюда!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Отправил deadman в 14:52 27.11.2004[Ответить]
Ещё есть функция на С++. Если надо могу скинуть. Как раз делает то что Вы хотите. Запускает внешнее приложение в модальном режиме. Есть ещё кое-какие параметры. Если можете подождать то могу переписать на Pascal (Delphi)?

PS. Мощней ShelllExecute!


Отправил deadman в 15:38 27.11.2004[Ответить]
Нашёл сделанную в Delphi так что переписывать не пришлось.

function ExecAndWait(const FileName,
Params: ShortString;
const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
CmdLine := '' + Filename + ' ' + Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(StartInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end
else
begin
Application.MessageBox(' Error! ','',mb_IconExclamation)
end;
end;

Запускает внешнее приложение в модальном режиме (т.е. в Вашу программу перейти нельзя до тех пор пока не завершится запушенная программа). У неё есть один минус. Окно Вашей программы не обновляется!

PS. Посмотрите может понравится. Я пока попробую разобратся с этим минусом.


Отправил deadman в 15:39 27.11.2004[Ответить]
Использовать так

ExecAndWait( 'C:windowscalc.exe', '', SW_SHOWNORMAL)

Параметр FileName = Имя внешней программы.
Параметр Params = Параметры, необходимые для запуска внешней программы
Параметр WinState = Указывает - как будет показано окно:
Для этого параметра мы можем так же использовать следующие константы: SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_SHOWNORMAL


Отправил olamot в 15:40 27.11.2004[Ответить]
Хочу конечно! Если Вас не затруднит!
В Си-п-п я ваще не вкурю ничего, но на Паскале...
С пятитомным комментарием наверно пойму.
:) В любом случае это интересно чрезвычаино!

Странно что об этом не пишут в этих крутых книгах!
Я купил книг 15 (по цене макулатуры- по десятке за каждую)
Без понимающего человека рядом- разобраться практически невозможно. Кроме Хелло Ворлд! нихрена не напишешь!!!!

А самую хорошую из них, таки сьел мой сОбак!!!! По паскалю. За что был бит.

------------------------------------------
Мне не нужно обновлять МОЕ окно... только если из-за любви к Истине!
-----------
прочитал листинг... видимо теперь ето все надо куда-то прицепить... может даже по кусочкам, да? и куда...


Отправил deadman в 15:46 27.11.2004[Ответить]
Кидаешь в свой любой unit в Delphi. Перед тем как хочешь её использовать. Если хочешь можешь вынести в отдельный unit и внести его в uses того модуля где будешь использовать данную функцию.

Ну так что Вам подойдёт этот экземпляр или мне продолжать поиски в этих долбаных Microsoft SDK :)

PS. Если что-то непонятно готов обьяснить хоть пятитомным комментарием :)


Отправил olamot в 15:51 27.11.2004[Ответить]
Подойдет я чувствую. Как это оформить? В виде модуля отдельного?
Как для дурака на пальцах обьясните, плз!!!!!!!!!!!!!!!!
---------------------

А! Во вижу!
Попробую... а там Мать- природа подскажет может быть %))


Отправил deadman в 16:01 27.11.2004[Ответить]
Создаешь файл какой-нибудь в каталоге со своим проектом например support.pas В него записываешь следующее:

<... start cut ...>
Unit Support;

interface

uses windows, sysutils;

function ExecAndWait(const FileName,Params: ShortString; const WinState: Word): boolean; export;

implementation

function ExecAndWait(const FileName,Params: ShortString; const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
{ Помещаем имя файла между кавычками, с соблюдением всех пробелов в именах Win9x }
CmdLine := '' + Filename + ' ' + Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(StartInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
{ Ожидаем завершения приложения }
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end
else
begin
// какая то ошибка
end;
end;
end.
<... end cut ...>

В своём модуле допустим Unit1:

Там где

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

Дописываешь support вот так:

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

PS. Здесь плохо видна структурированность функции поэтому я посчитал нужным скинуть Вам письмо с файлом support.pas


Отправил deadman в 16:28 27.11.2004[Ответить]
Тут есть одна особенность надо указывать полный путь доступа к тому exe-файлу который ты хочешь запустить. Пример

ExecAndWait('c:windows egedit.exe','', SW_SHOWNORMAL);

Обрати внимание на второй параметр (сейчас он пуст). Туда будешь записывать параметры для запускаемой программы. Пример

PixName:='c:program files1.bmp';

ExecAndWait('c:windowssystem32mspaint.exe',''+PixName+'', SW_SHOWNORMAL)

Не забывай их включать в двойные кавычки!


Отправил olamot в 16:55 27.11.2004[Ответить]
Полезу ковыряь.
(тут еще МОЯ с наездами- сделай то, сделай это)
Об успехах непременно отрапортую.


Отправил lyonchik в 17:28 27.11.2004[Ответить]
Ребята, закругляйтесь нафик! Тут вам не программерский форум, емейл же есть на такой случай. Все равно кроме вас двоих никто это не читает.


Отправил deadman в 17:35 27.11.2004[Ответить]
Извините не знал :). Оказывается ветка Программирование относится к другому :). Жаль...


Отправил lyonchik в 18:56 27.11.2004[Ответить]
Да не, все нормально, я пошутил.


Отправил Gott в 19:08 27.11.2004[Ответить]
Я читаю! И только рад что такая дискуссия развернулась. Кстати, тут упустили функцию SendMessage, а там много чего интересного :)
И вроде есть такое WM_TOPMOST или что-то в этом роде. Оно с какими-то параметрами выставляет окошко в модальном режиме поверх всех окон в системе, а не только по отношению к программе, это сообщение пославшей


Отправил deadman в 19:23 27.11.2004[Ответить]
Да есть такая функция. Счас попробую...


Отправил olamot в 20:07 27.11.2004[Ответить]
а вот и я вернулся!!!!!!!! УФ! Да здравствует ДЕД-МЕН (ужас)!
Да дискуссия у нас на славу!!!!!!!
Письмо с пасом я не получил. Но поэтому пришлося делать все ручками! От чего они стали на микрон прямее!!!
Отчего радость струится во взоре!

Но ложку дегтю я притащил. Функция фунциклирует изрядно!
Но не без прикола.
Я на радостях начал щелкать по якобы замороженному родительскому окну (довольно улыбаясь) А оно взяло и все мои случайные щелчки по кнопкам запомнило!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Короче закрываю я мультимедию свою и наблюдаю бардак страшной силы- открыватся окна- двери картинки и музыка...
ы!

---------------------------------
вот чую я надо многопоточность-б осваивать...
Не хотелось репу туманить... там, как я понял, у прог свой форум.
Все друг- другу сообщения посылают... да?
но пока надо этот способ ДОБИТЬ! чтоб работал, а не глазки строил


Отправил Gott в 20:18 27.11.2004[Ответить]
И еще, есть функция CreateWndParapmEx или что-то в этом роде, просто на работе у меня дельфей нет проверить щаз не могу, пардон. Возможно есть и что-то подобное для уже существующих окон, типа SetWndParam :) это я к примеру


Отправил deadman в 21:51 27.11.2004[Ответить]
Всё очень просто нужно очистить очередь сообщений после того как отработает вызванная тобой программа. Например:

<... start cut ...>

PixName:='C:Program FilesBorlandDelphi7Projects1pause_gray.bmp';

ExecAndWait('c:windowssystem32mspaint.exe',''+PixName+'', SW_SHOWNORMAL);

EmptyKeyQueue;
EmptyMouseQueue;

<... end cut ...>

Где последние неизвестные процедуры это:

<... start cut ...>
procedure EmptyKeyQueue;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST,
PM_REMOVE or PM_NOYIELD) do;
end;

procedure EmptyMouseQueue;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
PM_REMOVE or PM_NOYIELD) do;
end;
<... end cut ...>

Закидываешь их в твой файл support.pas Не забудь в uses в файле support.pas внести запись messages. В итоге твой модуль будет выглядеть так:

<... start cut ...>

Unit Support;

interface

uses windows, sysutils, messages;

function ExecAndWait(const FileName,Params: ShortString; const WinState: Word): boolean; export;
procedure EmptyKeyQueue;
procedure EmptyMouseQueue;

implementation

procedure EmptyKeyQueue;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST,
PM_REMOVE or PM_NOYIELD) do;
end;

procedure EmptyMouseQueue;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
PM_REMOVE or PM_NOYIELD) do;
end;

function ExecAndWait(const FileName,Params: ShortString; const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
{ Помещаем имя файла между кавычками, с соблюдением всех пробелов в именах Win9x }
CmdLine := '' + Filename + ' ' + Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(StartInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
{ Ожидаем завершения приложения }
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end
else
begin
// какая то ошибка
end;
end;

end.

<... end cut ...>

Эти две неизвестные функции очишают очередь сообщений клавиатуры и мышки.

PS. После внесения всех изменений всё стало работать нормально. Если есть ещё какие то вопросы готов ответить. Извиняюсь за задержку с ответом, друг пришёл :) о своей автомобильной жизни рассказывал :)...

PS. support.pas скинул ещё раз на Ваш e-mail.


Отправил olamot в 22:45 27.11.2004[Ответить]
Еще раз спасибо!
Все было просто великолепно.
Узнал сегодня нового- просто ЗДОРОВЕННУЮ такую кучу!

Полезный день :)))

---------------
И на последок- если модальное окно подвигать, на его месте остается белое такое пятно, которое потом не восстанавливается, пока не закроешь.
Или это причуды моей видяхи?


Отправил deadman в 22:49 27.11.2004[Ответить]
Я как раз про это и говорил ранее, что окно не обновляется. Всё решаемо ;). К сожаленью не сегодня, пора идти спать.

PS. Надеюсь завтра этот вопрос и разрешим :)


Отправил olamot в 22:58 27.11.2004[Ответить]
Ясно терь... про активность.
Что ж! Утро вечера мудренее.
Правда я работаю завтра... приду часов в 19...

Всем споки!


Отправил deadman в 13:25 28.11.2004[Ответить]
Вот решение данной проблемы. Новая функция ExecAndWait. Все входные параметры теже самые, только появился новый параметр UpdateForm - форма которую необходимо обновлять после запуска внешнего приложения. Сам код функции:

function ExecAndWait(UpdateForm: TForm; const FileName,Params: ShortString; const WinState: Word): boolean; export;
var
PI: TProcessInformation;
SI: TStartupInfo;
Reason: DWORD;
Msg: TMsg;
CmdLine: ShortString;
begin

// заполняем структуру
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(SI);
SI.dwFlags := STARTF_USESHOWWINDOW;
SI.wShowWindow := WinState;

// готовим коммандную строку для запуска
CmdLine := '' + Filename + ' ' + Params;

Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),SI,PI);

// ошибка при создании процесса
// код ошибки можно получить с помощью GetLastError
if not Result then exit;

repeat

// Ожидаем завершения дочернего процесса или сообщения
// перерисовки WM_PAINT
Reason := MsgWaitForMultipleObjects(1, PI.hProcess, FALSE,
INFINITE, QS_PAINT);

if Reason = WAIT_OBJECT_0 + 1 then begin

// В очереди сообщений появился WM_PAINT - Windows
// требует обновить окно программы.
// Удаляем сообщение из очереди
PeekMessage(Msg, UpdateForm.Handle, WM_PAINT, WM_PAINT, PM_REMOVE);
// И перерисовываем окно
UpdateForm.Update;
end;

// Повторяем цикл, пока не завершится дочерний процесс
until Reason = WAIT_OBJECT_0;
// Удаляем из очереди накопившиеся там сообщения
while PeekMessage(Msg, UpdateForm.Handle, 0, 0, PM_REMOVE) do;
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;

Пример использования:

procedure TForm1.Button1Click(Sender: TObject);
var
PixName: string;
begin
PixName:='C:Program FilesBorlandDelphi71pause_gray.bmp';
ExecAndWait(Form1,'c:windowssystem32mspaint.exe',''+PixName+'',SW_SHOWNORMAL);
end;

Как видно из примера теперь уже нет необходимости использовать процедуры EmptyKeyQueue и EmptyMouseQueue. Сообщения после завершения внешней программы удаляются автоматически.
В этой функции (ExeAndWait) есть ещё один интересный параметр: INFINITE. Вот строчка с его использованием:

Reason := MsgWaitForMultipleObjects(1, PI.hProcess, FALSE, INFINITE, QS_PAINT);

Он позволяет установить время (в миллисекундах) после которого вызванная программа будет считаться зависшей и будет убиватся.
У функции CreateProcess есть один небольшой недостаток. Она не умеет как ShellExecute искать запускаемые программы в Path. А также не умеет запускать программы по связанным с ним расширениями. Но зато обеспечивает полный контроль над запускаемым процессом. Насчёт этой проблемы скоро выложу ответ.


Отправил deadman в 13:39 28.11.2004[Ответить]
И ещё забыл если добавишь эту функцию (ExecAndWait) в support.pas. Не забудь изменить uses этого модуля так:

uses windows, sysutils, messages, forms;

Т.е. добавить forms.


Отправил olamot в 18:29 28.11.2004[Ответить]
Не жрамши прямо сюда!
Читаем.... эге... ясненько, понятненько...
Сохраняю всю страницу.

Спасибо. Гадом буду- не забуду. :)

Разбираться в Ваших наворотах буду позже.

P.S. письмо так и не пришло. наверно что- то не так записано
olamot@@@rambler.ru

три собаки- от пауков


Отправил deadman в 20:36 28.11.2004[Ответить]
Как и обещал выкладываю решение для определения пути для запуска программы:

function GetProgramPath(FileName: string): string;
var
Reg: TRegistry;
i, j: Integer;
Extension: string;
ExtDescription: string;
FileDescription: string;
OpenWith: string;
ParamString: string;

procedure SplitStr(SplitChar: String; var Str, Str1: String);
var
i: Integer;
begin
i := Pos(SplitChar, Str);
if i <> 0 then
begin
Str1 := Copy(Str, i + 1, Length(Str) - i + 1);
SetLength(Str, i - 1);
end
else ParamString := '';
end;

begin
Reg := TRegistry.Create;
try
with Reg do
begin

Extension:=ExtractFileExt(FileName);

RootKey := HKEY_CLASSES_ROOT;
OpenKey(Extension, False);
ExtDescription := ReadString('');
OpenKey('' + ExtDescription, False);
FileDescription := ReadString('');

if (FileDescription = '') and (ExtDescription = '') then
begin
Result := '';
Exit;
end;

OpenKey('' + ExtDescription + 'ShellOpenCommand', False);
OpenWith := ReadString('');

i := Pos('', OpenWith);
if i = 1 then
begin
OpenWith := Copy(OpenWith, 2, Length(OpenWith) - 1);
i := Pos('', OpenWith);
ParamString := Copy(OpenWith, i + 2, Length(OpenWith) - i - 1);
j := Pos('', ParamString);
while j <> 0 do
begin
Delete(ParamString, j, 1);
j := Pos('', ParamString);
end;
OpenWith := Copy(OpenWith, 0, i - 1);
end
else SplitStr(' ', OpenWith, ParamString)
end;
Result := OpenWith;
except
Result := '';
end;
Reg.Free;
end;

Пример использования:

Path:=GetProgramPath('c:1.wav');

В таком случае у меня в переменной Path содержится:

c:Program FilesWinampwinamp.exe

Остаётся только запустить данную программу :).

PS. Если будут вопросы пиши...
PS. Данное решение основано на TShellExt (автор мне не известен). Поэтому я считаю это только своей надстройкой.


Отправил deadman в 20:42 28.11.2004[Ответить]
Новый файл support.pas (теперь со всеми функциями) отослал ещё раз на Ваш e-mail.


Отправил olamot в 21:19 28.11.2004[Ответить]
YYYYYYYYYYYYYYYES!!!!!
Лунная походка и неприличное телодвижение в конце- У!

Я уже прикрутил Фуню руками. Терпения не хватило ждать.
(Не без труда правда.)
Работает!!!!! Да, да, Господа!
(правда, чёрть её знает, как?)

? (там стоит при запуске фунции ...Form1... в параметрах)
Я поставил имя своей формы, из которой запускаю ее, ОК?
Ну, работает, значит- ОК все же... :))

--------------------------
Есть один терпимый глюк- основная форма белеет, если например
по альт- таб что-то вызвать снизу и всю ее закрыть,
Эффект не самоликвидируется пока не кликнешь по форме.
Отнесем это к рудиментам и не будем париться на этот счет.
Но сообчить счел своей обязанностью :)))
--------------------------
Извините- ВАЖНОЕ дополнение
Глюк является следствием песпорядочного быстрого тыкания мышью вокруг и таскания запущенной проги по экрану.
В штатном режиме все Ок.


Отправил deadman в 21:36 28.11.2004[Ответить]
Да всё правильно.

PS. Счас попробую воспроизвести этот баг.


Отправил deadman в 21:44 28.11.2004[Ответить]
У меня баг воспроизводится не хочет :). Попробуйте заменить все встречающиеся UpdateForm.Handle на 0.

PS. Жду результатов...


Отправил olamot в 21:49 28.11.2004[Ответить]
У меня машина очень старая П1-133.
Уже отказывает кое какое железо. Видяха порой не врубается при старте... звуковуха со своими приколами (третья уже- остальные погорели) Сидюк второй уже накрылся.

:))

--------------------
Ну как, Юрий, обьявим тему закрытой?
Типа- Всем спасибо за внимание и посильное участие.

Если честно- это был мой первый опыт общения на борде.
Эффектно!


Отправил deadman в 21:56 28.11.2004[Ответить]
Тогда могу предложить только решение beta-тестировать Вашу программу :) Т.к. уже тщетно в течении нескольких минут тыкаю куда только можно (у меня Athlon XP 2000+). Всё конечно может быть. Готов проверить Вашу версию...