It is required to open a calculator on the form in the Delphi, the calculator should be dragged along with the parent form and also closed when it is closed. Is it possible to implement this?

procedure TForm1.Button1Click(Sender: TObject); var HW:hwnd; begin ShellExecute(Handle,'open','C:\Windows\system32\calc.exe',nil,nil,SW_SHOW); sleep(100); hw:=FindWindow(nil,''); SetParent(Form1); end; 
  • one
    The answer to your question is yes. Please ask more specific questions describing the problem. How to ask a good question? - kot-da-vinci

1 answer 1

First we analyze errors in the code of the author of the question:

 ShellExecute(Handle,'open','C:\Windows\system32\calc.exe',nil,nil,SW_SHOW); 

Well, you run the application, but after that you will have to wrestle with how to find the window handle (HWND), and you do not even know the pid process.

 sleep(100); 

Waiting for the calculator to start? And if the computer is terribly loaded, and the calculator will open not 0.1 seconds, but longer? Especially now I launched a calculator on a loaded car account, it turned out more than 4 seconds :)

 hw:=FindWindow(nil,''); 

Are you trying to find HWND by specifying an empty string as a parameter? But this is the title of the window, my calculator has in its capacity a proud string "Calculator".

 SetParent(Form1); 

And this is what? No, the idea is clear, but here is an attempt to implement ...

What is needed to complete your task:

  1. you must start the process and get its ProcessID, for example, through CreateProcess
  2. Now you need to know the HWND value of your calculator. Yes, it can be found through FindWindow, but what if the user had already started a calculator?
  3. But now you can use it, but not SetParent (Form1), but Winapi.Windows.SetParent (winhandle, Handle)

The easiest way to place a call to an external application through a procedure is suddenly useful:

 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; 

We define a variable that will return the HWND of the window we need and the EnumWindowsProc function to catch it (remember that the definition of the variable and this function must be in the program 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 all. HWND we got, set the Parent , you can play MoveWindow with MoveWindow and SetWindowRgn , if necessary of course. But try to figure it out yourself, MSDN will help you.

PS Could nakosyachit something on the little things, because he wrote in his notebook, and not in the IDE.