R
First, we'll figure out the errors in the author's code:ShellExecute(Handle,'open','C:\Windows\system32\calc.exe',nil,nil,SW_SHOW);
Well, you' the app, but after that, you're gonna have to break your head to find the final HWND, and you don't even know the pid process.sleep(100);
Waiting for a calculator? And if the computer's so loaded, and the calculator's gonna open for more than 0.1 seconds? Specially now, the calculator is on a loaded car account, it's been over four seconds:hw:=FindWindow(nil,'');
Are you trying to find HWND, pointing as a parameter an empty line? And it's the headline of the window, and I have a calculator as his proud row "Calculator."SetParent(Form1);
What's this about? No, the idea is understandable, but this is an attempt. ♪ ♪What you need to do is do your job:You have to start the process and get it ProcessID, for example, through CreateProcess.Now you need to know the HWND value of your calculator. Yeah, you can find it through FindWindow, but suddenly the user had a calculator set up before that?And now you can use it, but not SetParent(Form1), but you can use Winapi.Windows.SetParent(winhandle,Handle) It would be most difficult to challenge the external application through the procedure, and it would be useful on several occasions:procedure StartMyCommand(command:string); // command - наша командная строка, например, 'C:\Windows\system32\calc.exe'
var
isGood: LongBool;
StartUpInfo: TStartUpInfo;
ProcessInfo: TProcessInformation;
cmd:PChar;
begin
cmd:=PChar(command); // превращаем командную строку в PChar
FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0); // подготавливаем переменные для запуска
with StartUpInfo do
begin
cb := SizeOf(TStartUpInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
wShowWindow := SW_SHOWNORMAL;
end;
isGood := CreateProcess(cmd, '', nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo); // выполняем запуск приложения
if isGood then // проверка на успешный запуск
with ProcessInfo do begin
WaitForInputIdle(hProcess, INFINITE); // ждем завершения инициализации, вот так надо правильно, а не ваш Sleep(100)
CloseHandle(hThread); // закрываем дескриптор процесса, он нам не нужен
CloseHandle(hProcess); // закрываем дескриптор потока, тоже не нужен больше
EnumWindows(@EnumWindowsProc, LPARAM(dwProcessID)); // запускаем перебор окон, близких к вершине просмотра, нам понадобится определить callback-фунцию EnumWindowsProc для сервисных функций
end
else
begin
// тут уж сами ошибки обрабатывайте
end;
end;
Determine the variable that will give us the HWND windows we need and the EnumWindowsProc function for its outlet (remember that the definition of the variable and this function should be in the programme text before our StartMyCommand procedure):var
WinHandle: HWND;
function EnumWindowsProc(hWnd:HWND; lPar:LPARAM):boolean;
var
bContinue:boolean;
dwProcessID:integer;
begin
bContinue:=true;
GetWindowThreadProcessId(hWnd, @dwProcessID);
// перебираем процессы и, как только процессID совпадает с желаемым, определяем нужное нам окно
if (dwProcessID = DWORD(lPar)) then
begin
bContinue := FALSE;
WinHandle:=hWnd;
end;
Result:=bContinue;
end;
That's it. HWND We got it, exhibition. Parent♪ you can play with ♪ MoveWindow and SetWindowRgnif you need to. But try to figure this out yourself, MSDN.P.S. You could've done something small because you wrote in a notebook instead of IDE.