Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2018.11.04;
Скачать: [xml.tar.bz2];

Вниз

Использование CreateProcess. Как показать нужную форму после   Найти похожие ветки 

 
Abcdef123   (2016-09-09 07:36) [0]

Здравствуйте, Мастера.
Ситуация такая: Проект1 из главной формы запускается новый проект2 (без синкронизации) и из главной формы вызывается третий проект3 (с синкронизацией - т.е. пока проект3 работает проект2 не должен быть закрыт). После закрытия проекта3 мне надо чтобы на экране была форма проекта2, но почему то всегда активируется форма первого проекта.
Подскажите в каком направлении двигаться? На данный момент я не знаю, то ли параметры CreateProcess не правильные устанавливаю (к примеру, пробовала параметр bInheritHandles ставить True- не помогло), или проблема вообще не в этой функции?
Для информации, я пробовала использовать ShellExecute, в этом случае работает правильно, так как там передается Application.Handle как параметр. Но ShellExecute мне не подходит по другой причине.
Прокомментируйте, пожалуйста.
Заранее благодарна,
Надежда


 
Игорь Шевченко ©   (2016-09-09 10:31) [1]

После завершения какого-то процесса системой может быть активизировано окно любого процесса, скорее всего, последнего бывшего активным перед завершенным. К параметрам CreateProcess этот механизм отношения не имеет.


 
Abcdef123   (2016-09-09 11:47) [2]

To [1] Большое спасибо за ответ. По крайней мере я теперь буду знать, что дело не в CreateProcess.
Насчет активизиции последнего окна, то что вы написали - логически я так и думала, но почему то в моей ситуации это не работает. Я даже пыталась
try
CreateProcess(....)
finally
Application.Mainform.Setfocus;  //не помогло
end
А можно как-то форсировать активацию нужного окна если известен Handle этой формы или по Application.Handle? Если да, то как?


 
Игорь Шевченко ©   (2016-09-09 13:04) [3]


> Если да, то как?


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


> Проект1 из главной формы запускается новый проект2 (без
> синкронизации) и из главной формы вызывается третий проект3
> (с синкронизацией - т.е. пока проект3 работает проект2 не
> должен быть закрыт).


У вас оба процесса проект2 и проект3 запускаются из одного Проект1 ? А то непонятно.


 
sniknik ©   (2016-09-09 13:23) [4]

> Я даже пыталась
> Application.Mainform.Setfocus;  //не помогло
эээ... а выше вроде про другой процесс было, а тут фокус форме из своего процесса-приложения.

> Если да, то как?
я делал свое событие которое посылал из одной проги в другую, а там уж ловил и "подымал" нужную форму.
иначе, (SetForegroundWindow), все как то неправильно работало, в разных "осях", на XP как задумывалось. в висте игнорировало, в семерке "мигало в таскбаре"...
в итоге эта неопределенность и привела к собственному "велосипеду" с событием.
+
с событием тоже есть "заморочки", их нужно разрешать... типа (as is)
VistaMessagesEnable([WM_SELFRESTORE, WM_SYSCOMMAND]); //разрешим "подьем" формы извне, в висте и выше. + команды системы для Aero Shake и т.д.

procedure VistaMessagesEnable(const Values: array of Cardinal);
var
 DLLHandle: THandle;
 ChangeWindowMessageFilter: function(msg: Cardinal; dwFlag : Word): BOOL; stdcall;
 i: integer;
begin
 DLLHandle:=  LoadLibrary("user32.dll");
 if DLLHandle > 0 then
   try
     //иначе как говорят не будет проходить сообщение в программу, в висте/вин7 из-за UAC (будет виста проверим)
     @ChangeWindowMessageFilter:= GetProcAddress(DLLHandle, "ChangeWindowMessageFilter");
     if @ChangeWindowMessageFilter <> nil then //в XP функции нет, поэтому статически подключить не получится, только динамически
       for i:= 0 to High(Values) do
         ChangeWindowMessageFilter(Values[i], 1);
   finally
     FreeLibrary(DLLHandle);
   end;
end;


 
Abcdef123   (2016-09-12 04:58) [5]

To [3]
> У вас оба процесса проект2 и проект3 запускаются из одного
> Проект1 ? А то непонятно.

Я прошу прощения, что написала не понятно насчет трех проектов. Идет линейно - из главной формы первого проекта вызывается второй проект, а потом из главной формы второго проекта вызывается проект 3. Связь между первым и вторым проектом необязательна (без синхронизации), то есть после открытия второго проекта можно закрыть первый проект. А вот связь между вторым и третьим должна быть синхронизирована, то есть пока открыт третий проект второй проект не должен закрываться. То есть третий проект работает "модально" в каком то смысле.
Для вызова третьего проекта во втором проекте я пишу так
   try
     Application.MainForm.Enabled := False;
     <здесь вызывается экзешник третьего проекта с помощью  СreateProcess >
   finally
     Application.MainForm.Enabled := True;  //это имеется в виду главная форма второго проекта, после того как третий проект закрыли
     Application.MainForm.SetFocus;
    //здесь попробовала применить виша советы про SetForegroundWindow - не помогло, еще пробовала применить здесь совет [5] вызвать VistaMessagesEnable - не помогло тоже.
   end;



 
Abcdef123   (2016-09-12 05:04) [6]

To [4] Насчет вашего совета, я пробовала применить, пожалуйста, посмотрите мое сообщение выше. Возможно я не там примерила вызов вашей процедуры VistaMessagesEnable?
Кстати, я работаю в D2007 и у меня не находит флаг WM_SELFRESTORE, я заменила на WM_MDIRESTORE (это все что я нашла по смыслу интуитивно). Может поэтому не сработало?


 
sniknik ©   (2016-09-12 08:55) [7]

> еще пробовала применить здесь совет [5] вызвать VistaMessagesEnable - не помогло тоже.
разрешение покататься на машине <> езда на машине... где у меня вообще про замену вызова SetForegroundWindow на VistaMessagesEnable? логика меняется, в принципе.
> событие которое посылал из одной проги в другую, а там уж ловил и "подымал" нужную форму.
где у тебя обработчик события?

> Возможно я не там примерила вызов вашей процедуры VistaMessagesEnable?
впечатление, что вообще не читал "совета".

> не находит флаг WM_SELFRESTORE
это мое событие "самовостановления", юзерское, про которое в [5] словами.

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


 
Игорь Шевченко ©   (2016-09-12 11:28) [8]


> А вот связь между вторым и третьим должна быть синхронизирована,
>  то есть пока открыт третий проект второй проект не должен
> закрываться. То есть третий проект работает "модально" в
> каком то смысле.


Хотелось бы увидеть как вы вызываете и обеспечиваете "модальность" одного процесса по отношению к другому. Тот код, который приведен в [5] этого не показывает.

Но дело еще в том, что в Windows процессы друг от друга независимы, поэтому сдается мне, что ваше требование о "модальности" несколько искусственно и идет вразрез с той самой идеологией.
О задаче подробнее расскажите, может, есть более гуманные способы ?


 
Leonid Troyanovsky ©   (2016-09-12 19:03) [9]


> Abcdef123   (12.09.16 04:58) [5]

> закрыть первый проект. А вот связь между вторым и третьим
> должна быть синхронизирована, то есть пока открыт третий
> проект второй проект не должен закрываться. То есть третий
> проект работает "модально" в каком то смысле.

Для того, чтобы понять что можно, а что нельзя читаем msdn.

Соберем воедино restrictions для SetForegroundWindow & AllowSetForegroundWindow :

A process can set the foreground window only if one of the following conditions is true:

The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
The foreground process is not a Modern Application or the Start Screen (from SWF restriction)
No menus are active.

Что, IMHO, читать надо так:
"Нет активных меню, а одно из следующих условий истинно: .."

Используя оную таблицу легко разобрать любые цепочки
взаимодействий приложений.

Ну, а для того, чтобы сделать результат гарантированным следует
поискать более "гуманные способы". Например, объединить три
проекта в один, и разворачивать его в требуемой последовательности.

--
Regards, LVT.


 
Abcdef123   (2016-09-13 12:28) [10]

To [8]
> Хотелось бы увидеть как вы вызываете и обеспечиваете "модальность"
> одного процесса по отношению к другому.

Вызываю так:
ExecuteProcess(AExeFile + " "+AExtraParams,SW_SHOWNORMAL,0,true);
где сама фунция ExecuteProcess вот:
function ExecuteProcess(FileName: string; Visibility: Integer; BitMask: Integer; Synch: Boolean): Longword;
var
 zAppName: array[0..512] of Char;
 zCurDir: array[0..255] of Char;
 WorkDir: string;
 StartupInfo: TStartupInfo;
 ProcessInfo: TProcessInformation;
 Closed: Boolean;
begin
 Closed := True;
 StrPCopy(zAppName, FileName);
 GetDir(0, WorkDir);
 StrPCopy(zCurDir, WorkDir);
 FillChar(StartupInfo, SizeOf(StartupInfo), #0);
 StartupInfo.cb := SizeOf(StartupInfo);
 StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
 StartupInfo.wShowWindow := Visibility;
 if not CreateProcess(nil,
   zAppName,
   nil,
   nil,
   False,
   CREATE_NEW_CONSOLE or
   NORMAL_PRIORITY_CLASS,
   nil,
   nil,
   StartupInfo,
   ProcessInfo)
   then Result := WAIT_FAILED
 else
 begin
   if (Synch = True) then
     begin
       Closed:= False;
       repeat
         case WaitForSingleObject(
           ProcessInfo.hProcess, 100) of
             WAIT_OBJECT_0 : Closed:= True;
             WAIT_FAILED : RaiseLastWin32Error;
         end;
         Application.ProcessMessages;
       until (Closed);
       GetExitCodeProcess(ProcessInfo.hProcess, Result);
       CloseHandle(ProcessInfo.hProcess);
       CloseHandle(ProcessInfo.hThread);
     end
   else
     begin
       Result := 0;
     end;
 end;
end;


А насчет
> "модальности" несколько искусственно

я согласна с вами.
> О задаче подробнее расскажите, может, есть более гуманные
> способы
Если коротко о причине, то в зависимости от клиента нам надо "собирать" отдельные фукциональности (проекты) в один проект, в то же время, некоторые пользователи хотят всё. Вот в данном примере, нам нужна возможность запускать третий проект как чать второго проекта. В что же время, чтоб оставалась возможность предоставить третий проект кому то как отдельную единичную задачу.


 
Игорь Шевченко ©   (2016-09-13 17:02) [11]


> Если коротко о причине


Коротко не надо, расскажите длинно. Может, вам проще проекты в виде DLL/BPL оформить и управлять сущностями в одном приложении.

Когда вы запускаете программу из-под отладчика в среде, то вы ожидаете, что по завершении программы фокус вернется к среде. Однако и это не всегда происходит, так что, мне кажется, с мечтой о модальности и управлением фокусом между процессами лучше проститься сразу.


 
sniknik ©   (2016-09-14 07:58) [12]

repeat
 case WaitForSingleObject(ProcessInfo.hProcess, 100) of
   WAIT_OBJECT_0 : Closed:= True;
   WAIT_FAILED : RaiseLastWin32Error;
 end;
 Application.ProcessMessages; //вот причина почему твоя "псевдомодальность" не работает, убери это
until (Closed);

ну и в конце этой процедуры, ставь фокус, если он еще будет нужен.

ты как то определись с логикой, и пиши либо линейно либо событийно... во втором случае ProcessMessages = ошибка, т.к. это попытка совместить несовместимое.


 
Abcdef123   (2016-09-15 05:04) [13]

To [11]
> Коротко не надо, расскажите длинно. Может, вам проще проекты
> в виде DLL/BPL оформить и управлять сущностями в одном приложении.
>

Честно признаться, про это направление "DLL/BPL" имею только теоретическое представление. Так что даже не знаю, в этом случае подходит ли. Конечно, очень бы хотелось узнать ваше мнение по этому направлению, даже если это не мой случай. (в будущем пригодится тогда). Если у вас будет возможность написать, буду очень признательна.
Итак, если подробнее, то схема такая:
Первый проект по смыслу никак не связан со вторым и третьим. Просто из главного меню по клику запускается второй проект
Проект второй и третий имеют смысловую связь и работают с одними и теми же данными (таблицами).
Второй проект это всего лишь главная форма с главным меню, из которого вызываются проекты третьего типа, а также всякого рода отчеты.
Проекты третьего типа все типичны, созданы по одному макету (даже названия файлов одинаковое) - это форма ввода данных, из этой формы можно запустить листинг отчет (по кнопке) и дата модуль. Не знаю, важно или нет, для информации- этот же отчет (я имею в виду файл -форму ввода) используется и во втором проекте.
Вот, пожалуй, и всё.


 
Abcdef123   (2016-09-15 05:46) [14]

To [12] Спасибо, большое. Это действительно помогло. Правда поведение "псевдомодальности" изменилось (раньше форма проекта 2 была не доступна, в смысле никакой реакции, если кликнуть, а сейчас если кликнуть, то форма становится "серой" и в заголовке формы добаваляетс (Not Responding). В принципе, всё правильно, просто пользователей может это "напугать" с непривычки.
Поскольку проектом уже пользуются, я остановлюсь на этом варианте!
А если поступит ответ на [11]->[13], то, возможно в следующей версии перепишу всё.
Преогромное всем спасибо за отзывы, комментарии и советы!!! И за большое терпение отдельное огромное спасибо sniknik и Игорь Шевченко!



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2018.11.04;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.002 c
2-1474009068
user
2016-09-16 09:57
2018.11.04
Заполнение форму html


15-1475184602
Юрий
2016-09-30 00:30
2018.11.04
С днем рождения ! 30 сентября 2016 пятница


2-1473395811
Abcdef123
2016-09-09 07:36
2018.11.04
Использование CreateProcess. Как показать нужную форму после


2-1473404951
валя
2016-09-09 10:09
2018.11.04
Указатели


2-1473936376
lewka
2016-09-15 13:46
2018.11.04
передача нажатия клавиши стороннему приложению





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский