Recent

Author Topic: How can i run application in the panel ?  (Read 5694 times)

boreas

  • New Member
  • *
  • Posts: 33
How can i run application in the panel ?
« on: July 23, 2015, 09:41:29 am »
Hi,
i work a os. project. I wantto add application in my project like a plugin. I search into plugin directory and add button for all aplication that in the directory. It's ok from here. But i coudn't run application in the panel. Application can write any programming language, os is linux and windows. So how can i do that :)

Sorry for my bad english.

Zoran

  • Hero Member
  • *****
  • Posts: 1730
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: How can i run application in the panel ?
« Reply #1 on: July 23, 2015, 10:11:09 am »
If I understand what you want, you expect your panel to behave like desktop enviroment and host a graphical application? I do not believe that it is possible.
However, you can start the application and comunicate with it - see http://wiki.freepascal.org/Executing_External_Programs#TProcess

boreas

  • New Member
  • *
  • Posts: 33
Re: How can i run application in the panel ?
« Reply #2 on: July 23, 2015, 10:19:24 am »
Thank u for answer. I saw that page and i can communicate application. I can do with dll that i want but anybody dont want write to dll this is hard way. Actually if i can run external pascal script may be i can set parent to my panel ?

rvk

  • Hero Member
  • *****
  • Posts: 4677
Re: How can i run application in the panel ?
« Reply #3 on: July 23, 2015, 10:43:27 am »
If I understand what you want, you expect your panel to behave like desktop enviroment and host a graphical application? I do not believe that it is possible.
However, you can start the application and comunicate with it - see http://wiki.freepascal.org/Executing_External_Programs#TProcess
It is possible. (for Windows OS at least)

Look at the following video: https://www.youtube.com/watch?v=N6GWgxEvibE
You just have to use SetParent to attach the window-handle to another control.

You can also find an example here:
http://www.lazarusforum.de/viewtopic.php?f=10&t=3256

I tried to create an example. The only problem I had was getting the correct handle from the Calculator-window. It seems the handle TProcess returns is not the correct one. So I had to do FindWindow to find the window with the title Calculator and attach that to the panel.

Code: [Select]
uses Process, Windows;

// https://www.youtube.com/watch?v=N6GWgxEvibE
// http://www.lazarusforum.de/viewtopic.php?f=10&t=3256

procedure TForm1.Button1Click(Sender: TObject);

  function FindWindowByTitle(WindowTitle: string): Hwnd;
  var
    NextHandle: Hwnd;
    NextTitle: array[0..260] of char;
  begin
    // Get the first window
    NextHandle := GetWindow(Application.Mainform.Handle, GW_HWNDFIRST);
    while NextHandle > 0 do
    begin
      // retrieve its text
      GetWindowText(NextHandle, NextTitle, 255);
      if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
      begin
        Result := NextHandle;
        Exit;
      end
      else
        // Get the next window
        NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
    end;
    Result := 0;
  end;

  procedure Attach2Control(aWnd: Hwnd; aControl: TWinControl);
  var
    WPM: WINDOWPLACEMENT;
  begin
    Windows.SetParent(aWnd, aControl.Handle);
    SetWindowLong(aWnd, GWL_STYLE, GetWindowLong(aWnd, GWL_STYLE) and not WS_CAPTION);
    WPM.Length := SizeOf(WPM);
    GetWindowPlacement(aWnd, @WPM);
    WPM.ShowCmd := SW_ShowMaximized;
    WPM.rcNormalPosition := Classes.Rect(0, 0, aControl.Width, aControl.Height);
    SetWindowPlacement(aWnd, @WPM);
  end;

var
  xWnd: HWND;
  aProcess: TProcess;
begin

  aProcess := TProcess.Create(nil);
  aProcess.CommandLine := 'calc.exe';
  aProcess.Options := aProcess.Options - [poWaitOnExit];
  aProcess.Execute;

  Sleep(100);
  xWnd := FindWindowByTitle('Calculator');
  Attach2Control(xWnd, Panel1);

  aProcess.Free;

end;
(screenshot attached)

If you leave the windowplacement and SetWindowLong lines out, and just only leave the SetParent-line you can even keep the title-bar as in screenshot #2.
Code: [Select]
    Windows.SetParent(aWnd, aControl.Handle);
    //SetWindowLong(aWnd, GWL_STYLE, GetWindowLong(aWnd, GWL_STYLE) and not WS_CAPTION);
    //WPM.Length := SizeOf(WPM);
    //GetWindowPlacement(aWnd, @WPM);
    //WPM.ShowCmd := SW_ShowMaximized;
    //WPM.rcNormalPosition := Classes.Rect(0, 0, aControl.Width, aControl.Height);
    //SetWindowPlacement(aWnd, @WPM);
(But then it could be that your application is "out of sight" so you need to maximize your panel to see it and drag it back in sight)


boreas

  • New Member
  • *
  • Posts: 33
Re: How can i run application in the panel ?
« Reply #4 on: July 23, 2015, 10:56:20 am »
Ok. Perffect example :) I'll try that. But my guess its not work on linux  only windows.  True ?

rvk

  • Hero Member
  • *****
  • Posts: 4677
Re: How can i run application in the panel ?
« Reply #5 on: July 23, 2015, 10:58:28 am »
But my guess its not work on linux  only windows.  True ?
Well, Windows.SetParent is, of course, a Windows API call.

But maybe there is something similar for Linux.
(I'm not an expert on Linux, yet :))

Maybe something like gdk_window_reparent_ ??
« Last Edit: July 23, 2015, 11:04:05 am by rvk »

boreas

  • New Member
  • *
  • Posts: 33
Re: How can i run application in the panel ?
« Reply #6 on: July 23, 2015, 11:03:24 am »
Thnk u so much. Again :) If i found resolve for linux, i ll share here :)

rvk

  • Hero Member
  • *****
  • Posts: 4677
Re: How can i run application in the panel ?
« Reply #7 on: July 23, 2015, 11:03:54 am »
Maybe SetParent even works on Linux???
It's implemented in TQtWidgetSet.SetParent.

boreas

  • New Member
  • *
  • Posts: 33
Re: How can i run application in the panel ?
« Reply #8 on: July 23, 2015, 11:14:03 am »
I think it's change according to widget set. QT,gtk, wx or tk. But maybe i do block windows manager, maybe i can enter between xwindow and application. I will try that.

Moombas

  • New Member
  • *
  • Posts: 38
Re: How can i run application in the panel ?
« Reply #9 on: May 13, 2022, 03:11:40 pm »
Hi,
is there a way to do that still?
Tryied the code above but didn't worked. The program (even tried with calc.exe) is just opened and not put into the panel. Also i would prefer to do it via shellexecute instead of process because maybe i need to provide some parameters.

Ps.: Yes i know that the thread is very old but it's exactly the topic i look for.
I found a way now which works (tested on W10):

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Rec: TShellExecuteInfo;
  4.   fNotepadHandle : HWND;
  5.   WPM: WINDOWPLACEMENT;
  6. const
  7.   AVerb = 'open';
  8.   AParams = '';
  9.   AFileName = 'Notepad.exe';
  10.   ADir = '';
  11. begin
  12.   FillChar(Rec, SizeOf(Rec), #0);
  13.  
  14.   Rec.cbSize       := SizeOf(Rec);
  15.   Rec.fMask        := SEE_MASK_NOCLOSEPROCESS;
  16.   Rec.lpVerb       := PChar( AVerb );
  17.   Rec.lpFile       := PChar( AfileName );
  18.   Rec.lpParameters := PChar( AParams );
  19.   Rec.lpDirectory  := PChar( Adir );
  20.   Rec.nShow        := SW_HIDE;
  21.  
  22.   ShellExecuteExA(@Rec);
  23.   WaitForInputIdle(Rec.hProcess, 5000);
  24.  
  25.   fNotepadHandle := Windows.FindWindow( 'Notepad', nil );
  26.   Windows.SetParent( fNotepadHandle, Panel1.Handle );
  27.   SetWindowLong(fNotepadHandle, GWL_STYLE, GetWindowLong(fNotepadHandle, GWL_STYLE) and not WS_CAPTION);
  28.   WPM.Length := SizeOf(WPM);
  29.   GetWindowPlacement(fNotepadHandle, @WPM);
  30.   WPM.ShowCmd := SW_ShowMaximized;
  31.   WPM.rcNormalPosition := Classes.Rect(0, 0, Panel1.Width, Panel1.Height);
  32.   SetWindowPlacement(fNotepadHandle, @WPM);
  33.  
  34.   Resize;
  35.   ShowWindow(fNotepadHandle, SW_SHOW);
  36. end;
« Last Edit: May 16, 2022, 02:14:42 pm by Moombas »
The path is the destination but you should never lose sight of the destination on the way.

Moombas

  • New Member
  • *
  • Posts: 38
Re: How can i run application in the panel ?
« Reply #10 on: May 17, 2022, 08:13:57 am »
Even it works with Notepad for example, some other applications seem not be able to be catched.
Someone here who can explain me why this could be possible?
The path is the destination but you should never lose sight of the destination on the way.

rvk

  • Hero Member
  • *****
  • Posts: 4677
Re: How can i run application in the panel ?
« Reply #11 on: May 17, 2022, 08:22:38 am »
Even it works with Notepad for example, some other applications seem not be able to be catched.
Someone here who can explain me why this could be possible?
Could be that that application creates multiple windows of which you only catch the (hidden) main one. Hard to tell without knowing the application.

Try to use a Window spy program (like the one which comes with AutoHotkey) to see if you can find more windows and examine their properties.

Moombas

  • New Member
  • *
  • Posts: 38
Re: How can i run application in the panel ?
« Reply #12 on: May 17, 2022, 10:13:09 am »
Hi rvk,

i tried with WinBox which is a management tool for Mikrotik routers.
I can see the program in the taskmanager assigned to my test program but it's not visible in the panel.

You can find it here: https://mikrotik.com/download
« Last Edit: May 17, 2022, 10:23:36 am by Moombas »
The path is the destination but you should never lose sight of the destination on the way.

rvk

  • Hero Member
  • *****
  • Posts: 4677
Re: How can i run application in the panel ?
« Reply #13 on: May 17, 2022, 02:42:57 pm »
Maybe it's some timing issue because the code below works fine.
(note I used the classname of the window, not the window-name)

Without the showmessage delay I get a flickering window and it disappears.
A myDelay of 1000 ms works too BTW.
So, the WaitForInputIdle() is too soon for this program.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Rec: TShellExecuteInfo;
  4.   fHandle: HWND;
  5. const
  6.   AVerb = 'open';
  7.   AParams = '';
  8.   AFileName = ' path to exe \winbox64.exe';
  9.   ADir = '';
  10.   wndClass = 'routeros_connect';
  11. begin
  12.  
  13.   fHandle := FindWindow(pChar(wndClass), nil);
  14.   if fHandle <> 0 then
  15.   begin
  16.     ShowMessage('We found a window already, kill it first');
  17.     exit;
  18.   end;
  19.  
  20.   FillChar(Rec, SizeOf(Rec), #0);
  21.   Rec.cbSize := SizeOf(Rec);
  22.   Rec.fMask := SEE_MASK_NOCLOSEPROCESS;
  23.   Rec.lpVerb := PChar(AVerb);
  24.   Rec.lpFile := PChar(AfileName);
  25.   Rec.lpParameters := PChar(AParams);
  26.   Rec.lpDirectory := PChar(Adir);
  27.   Rec.nShow := SW_HIDE;
  28.  
  29.   if not ShellExecuteExA(@Rec) then;
  30.   WaitForInputIdle(Rec.hProcess, 5000);
  31.  
  32.   ShowMessage('Wait 1 second and press Ok');
  33.   // myDelay(1000); // works too
  34.  
  35.   fHandle := FindWindow(pChar(wndClass), nil);
  36.   if fHandle <> 0 then
  37.   begin
  38.     Windows.SetParent(fHandle, Panel1.Handle);
  39.     SendMessage(fHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); // you can change this back to your own code
  40.   end
  41.   else
  42.     ShowMessage('Window not found');
  43.  
  44. end;

Moombas

  • New Member
  • *
  • Posts: 38
Re: How can i run application in the panel ?
« Reply #14 on: May 18, 2022, 08:14:42 am »
Thanks, the delay did it.  8-)
How did you get the classname? I was searching for that but maybe i searched for the wrong thing
The path is the destination but you should never lose sight of the destination on the way.

 

TinyPortal © 2005-2018