0

I am using a PageControl on my main form to serve as a dock site for other forms.

One of these forms, fPanelSonar, has a panel that serves as container for a 3rd party application that I load as follow:

var
  i : Integer;
  ExecutePingViewer : string;
  sePingViewer,seOVREC: TShellExecuteInfo;
begin
  Timer1.Enabled := False;
  fPanelSonar.hdlPing360 := FindWindow(nil, PChar('Ping Viewer - v2.0.4'));
  if fPanelSonar.hdlPing360 = 0 then
  begin
    ExecutePingViewer:='C:\Program Files (x86)\Oceanvault\pingviewer_release\deploy\pingviewer.exe';
    FillChar(sePingViewer, SizeOf(sePingViewer), 0) ;
    sePingViewer.cbSize := SizeOf(TShellExecuteInfo) ;
    with sePingViewer do
    begin
      fMask := SEE_MASK_NOCLOSEPROCESS;
      Wnd := 0;
      lpFile := PChar(ExecutePingViewer) ;
      nShow := SW_HIDE;
    end;
    if ShellExecuteEx(@sePingViewer) then
    begin
      fPanelSonar.hdlPing360 := FindWindow(nil, PChar('Ping Viewer - v2.0.4'));
      Windows.SetParent(hdlPing360, pSonar.Handle);
      ShowWindow(hdlPing360, SW_SHOWMAXIMIZED);
    end
    else ShowMessage('Error loading Ping360!') ;
  end;

This works well and my 3rd party application is loaded as I want.

The problem is when I drop fPanelSonar into the PageControl, the 3rd party application disappears even if its process "pingviewer.exe" is still running.

Since I saved the hwnd fPanelSonar.hdlPing360 I should be able to set it back to its parent again, but it appears although this handle is invalid because it doesn't work. (Even if I undock it).

Furthermore, I can't find any other handle with once I dock/undock:

FindWindowEx(fPanelSonar.pSonar.Handle,0,nil, PChar('Ping Viewer - v2.0.4'));

I can still find the process ID with this function I found off the forum so I know its not killed. (I can also see it in window's Task Manager)

function GetPIDbyProcessName(processName:String):integer;
var
  GotProcess: Boolean;
  tempHandle: tHandle;
  procE: tProcessEntry32;
begin
  tempHandle:=CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0);
  procE.dwSize:=SizeOf(procE);
  GotProcess:=Process32First(tempHandle, procE);
  {$B-}
    if GotProcess and (procE.szExeFile <> processName) then
      repeat GotProcess := Process32Next(tempHandle, procE);
      until (not GotProcess) or (procE.szExeFile = processName);
  {$B+}

  if GotProcess then
    result := procE.th32ProcessID
  else
    result := 0; // process not found in running process list

  CloseHandle(tempHandle);
end;

I tried to find the hwd with process ID but it doens't work.

Note that if I dock fPanelSonar before I assign the pingviewer.exe parent, It does work.

At present, I can use the dock/undock events to kill the pingviewer process and load a new one but that is awfully messy...

So I am a bit confused why this is happening and how to solve it properly.

Cheers, E.

E Demers
  • 103
  • 1
  • 8
  • 2
    Did you try setting the parent for hdlPing360 to 0 before docking and set it to the new pSonar.Handle after docking? – Uwe Raabe Apr 19 '20 at 11:28
  • Hello. Of all the things I tried, I should have thought of this since I am already doing it when the user resizes the form... Thank you this works, but I would still like to understand why. – E Demers Apr 19 '20 at 11:58
  • 1
    You should use CreateProcess to create a new process. You are leaking process handles in this code. Your entire design is going to struggle when faced with VCL window recreation. You don't do nearly enough error checking in your Win32 api calls. Your second call to FindWindow is likely to fail because it executes before the other process has created the window. – David Heffernan Apr 19 '20 at 12:54

0 Answers0