Recent

Author Topic: Any way to "embed" Windows window within Lazarus program?  (Read 6487 times)

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Any way to "embed" Windows window within Lazarus program?
« on: March 10, 2026, 03:02:52 am »
Practically I'd like to embed a separate softphone program within my Lazarus application. It's like the softphone program's parent is a TPanel of my application.

https://www.microsip.org/

This is an open source project, and seems written in c++ (as the extensions are .cpp).
« Last Edit: March 11, 2026, 08:42:04 am by egsuh »

Zvoni

  • Hero Member
  • *****
  • Posts: 3361
Re: Anyway to "embed" Windows window within Lazarus program?
« Reply #1 on: March 10, 2026, 08:04:15 am »
Practically I'd like to embed a separate softphone program within my Lazarus application. It's like the softphone program's parent is a TPanel of my application.

https://www.microsip.org/

This is an open source project, and seems written in c++ (as the extensions are .cpp).
There is your solution.
Get the Window-Handle to that "external" program (Note: Separate Process)
On Windows it would be a call to SetParent-API. No Idea for Linux
Note: You have to take care of the position of the window yourself (at least i think so)
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

PierceNg

  • Sr. Member
  • ****
  • Posts: 434
    • SamadhiWeb
Re: Anyway to "embed" Windows window within Lazarus program?
« Reply #2 on: March 10, 2026, 08:10:25 am »
The microsip home page says it is "open source portable SIP softphone based on PJSIP stack for Windows OS."

Looking up PJSIP on Github yields https://github.com/pjsip/pjproject, with the blurb "free and open source multimedia communication library written in C with high level API in C, C++, Java, C#, and Python languages. It implements standard based protocols such as SIP, SDP, RTP, STUN, TURN, and ICE."

So, one way to proceed is to build a Pascal FFI to the PJSIP library.

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Re: Anyway to "embed" Windows window within Lazarus program?
« Reply #3 on: March 10, 2026, 09:24:17 am »
Both are too difficult for me^^
But sure, I believe there is a way that I only have to make the UI using .dlls.

jamie

  • Hero Member
  • *****
  • Posts: 7663
Re: Anyway to "embed" Windows window within Lazarus program?
« Reply #4 on: March 10, 2026, 11:36:00 am »
Strange, lately i notice i can view the folder trees of projects on github but i cant view any of the files without an too many accesses error.

In any case, i think i could convert it to fpc/laz

Ill look later, maybe i can down load a zip file.

Jamie
The only true wisdom is knowing you know nothing

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Re: Anyway to "embed" Windows window within Lazarus program?
« Reply #5 on: March 11, 2026, 05:13:50 am »
@jamie,

Do  you mean the attached file? There are sources.

jamie

  • Hero Member
  • *****
  • Posts: 7663
Re: Anyway to "embed" Windows window within Lazarus program?
« Reply #6 on: March 11, 2026, 11:02:08 pm »
@jamie,

Do  you mean the attached file? There are sources.
  That looks to simple. :o

That majority is nothing more than the Dialogs and message handlers for the UI.

 Where's the real BEEF?

Jamie
The only true wisdom is knowing you know nothing

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Re: Any way to "embed" Windows window within Lazarus program?
« Reply #7 on: March 12, 2026, 04:31:44 am »
Quote
Where's the real BEEF?

I think the program is UIs over dlls.
You can download executibles (inc .dlls) at the following link. I can't attach the file (too big size).

https://www.microsip.org/download/MicroSIP-3.22.3.zip

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1225
« Last Edit: March 13, 2026, 03:34:47 am by valdir.marcos »

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Re: Any way to "embed" Windows window within Lazarus program?
« Reply #9 on: March 13, 2026, 03:43:44 am »
Quote
You can create your own RESTful dialer with Lazarus (Synapse or Indy) + Asterisk:

Thank you for your advice. Asterisk says it needs Linux, while I use Windows only. BTW I'm not a serious developer, and having a good application for my purpose is the objective.

I have asked ChatCPT to translate the C++ files to Lazarus project, and it did, but not usable right now.
I'm looking into the Lazarus codes and thinking what I can do. I attach the AI-produced output.

egsuh

  • Hero Member
  • *****
  • Posts: 1777

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Re: Any way to "embed" Windows window within Lazarus program?
« Reply #11 on: March 13, 2026, 06:54:51 am »
Quote
Where's the real BEEF?

It looks to depend on library of :

https://www.pjsip.org/

jamie

  • Hero Member
  • *****
  • Posts: 7663
Re: Any way to "embed" Windows window within Lazarus program?
« Reply #12 on: March 14, 2026, 12:55:37 am »
I clean up the GUI mess and got it to build.

You need to supply the DLL I guess if that is the option you want.

I am sure more is needed.

Jamie
The only true wisdom is knowing you know nothing

myisjwj

  • Full Member
  • ***
  • Posts: 103

egsuh

  • Hero Member
  • *****
  • Posts: 1777
Re: Any way to "embed" Windows window within Lazarus program?
« Reply #14 on: March 16, 2026, 05:38:10 am »
I have cleaned up the source codes, and made some modifications as compilation on Windows issues errors. The differences are :

1.  function EnumWindowsProc(Wnd: HWND; wInfo: Int64): BOOL; stdcall;

In the original code, wInfo is PProcessWindow type, but as this causes error, I changed it to Int64 (which is expected type by compiler), and typecasted it to PProcesswindow within the procedure.


2.  function RunAppInPanel(const AppFileName: string; ParentHandle: HWND; var WinHandle: HWND): Boolean;

In the local variable definitions, the original code of var si : STARTUPINFO; which I changed to STARTUPINFOA, which is expected type from compiler.
 
    var
        si: STARTUPINFOA;  // changed from StartupInfo to StartupInfoA
        pi: TProcessInformation;
    begin
       Result := False;
       FillChar(si, SizeOf(si), 0);     // No change, but this might be affected.


That's all I have changed, except separating Form unit.

The program runs well, EXCEPT the notepad and my application run separately. Notepad is not within panel of my program.

Hope someone could explain.


Code: Pascal  [Select][+][-]
  1. unit uembedapp;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows, SysUtils, Variants, Classes;
  9.  
  10. type
  11.   // Store form information
  12.   PProcessWindow = ^TProcessWindow;
  13.   TProcessWindow = record
  14.     ProcessID: Cardinal;
  15.     FoundWindow: hWnd;
  16.   end;
  17.   function RunAppInPanel(const AppFileName: string; ParentHandle: HWND; var WinHandle: HWND): Boolean;
  18.  
  19. var
  20.   hWin: HWND = 0;
  21.  
  22. implementation
  23.  
  24.   // enumerating windows proc
  25.  
  26. function EnumWindowsProc(Wnd: HWND; wInfo: Int64): BOOL; stdcall;
  27. var
  28.   WndProcessID: Cardinal;
  29.   P: pointer;
  30.   ProcWndInfo : PProcessWindow;
  31. begin
  32.   // typecasting wInfo to PProcessWindow ty;e
  33.   P := Pointer(wInfo);
  34.   ProcWndInfo := PProcessWindow(P);
  35.  
  36.   GetWindowThreadProcessId(Wnd, @WndProcessID);
  37.   if WndProcessID = ProcWndInfo^.ProcessID then begin
  38.     ProcWndInfo^.FoundWindow := Wnd;
  39.     Result := False; // if already exists, stop EnumWindows
  40.   end
  41.   else
  42.     Result := True; // continue searching
  43. end;
  44.  
  45. // Search handle from ProcessID
  46.  
  47. function GetProcessWindow(ProcessID: Cardinal): HWND;
  48. var
  49.   ProcWndInfo: TProcessWindow;
  50. begin
  51.   ProcWndInfo.ProcessID := ProcessID;
  52.   ProcWndInfo.FoundWindow := 0;
  53.   EnumWindows(@EnumWindowsProc, Integer(@ProcWndInfo)); // 查找窗体
  54.   Result := ProcWndInfo.FoundWindow;
  55. end;
  56.  
  57.  
  58. function RunAppInPanel(const AppFileName: string; ParentHandle: HWND; var WinHandle: HWND): Boolean;
  59. var
  60.   si: STARTUPINFOA;  // changed from StartupInfo to StartupInfoA
  61.   pi: TProcessInformation;
  62. begin
  63.   Result := False;
  64.  
  65.   // Start process
  66.   FillChar(si, SizeOf(si), 0); // so, this might be affected.
  67.   si.cb := SizeOf(si);
  68.   si.wShowWindow := SW_SHOW;
  69.   if not CreateProcess(nil, PChar(AppFileName), nil, nil, true,
  70.     CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, si, pi) then Exit;
  71.  
  72.   // Wait for process to start
  73.   WaitForInputIdle(pi.hProcess, 10000);
  74.  
  75.   // Get process Handle
  76.   WinHandle := GetProcessWindow(pi.dwProcessID);
  77.   if WinHandle > 0 then begin
  78.     Windows.SetParent(WinHandle, ParentHandle);
  79.     SetWindowPos(WinHandle, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
  80.     SetWindowLong(WinHandle, GWL_STYLE, GetWindowLong(WinHandle, GWL_STYLE)
  81.       and (not WS_CAPTION) and (not WS_BORDER) and (not WS_THICKFRAME));
  82.  
  83.     Result := True;
  84.   end;
  85.  
  86.   CloseHandle(pi.hProcess);
  87.   CloseHandle(pi.hThread);
  88. end;
  89.  
  90. end.
  91.  
  92.  
  93. //------------------- Form unit
  94.  
  95. unit uMainform;
  96.  
  97. {$mode objfpc}{$H+}
  98.  
  99. interface
  100.  
  101. uses
  102.   Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  103.   ButtonPanel;
  104.  
  105. type
  106.  
  107.   { TMainForm }
  108.  
  109.   TMainForm = class(TForm)
  110.     ButtonPanel1: TButtonPanel;
  111.     pnlApp: TPanel;
  112.     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  113.     procedure FormCreate(Sender: TObject);
  114.     procedure FormResize(Sender: TObject);
  115.   private
  116.  
  117.   public
  118.  
  119.   end;
  120.  
  121. var
  122.   MainForm: TMainForm;
  123.  
  124. implementation
  125.  
  126. uses
  127.   uembedapp;
  128.  
  129. {$R *.lfm}
  130.  
  131. { TMainForm }
  132.  
  133. procedure TMainForm.FormCreate(Sender: TObject);
  134. const
  135.   App = 'C:\Windows\Notepad.exe';
  136. begin
  137.   pnlApp.Align := alClient;
  138.   if not RunAppInPanel(App, pnlApp.Handle, hWin) then ShowMessage('App not found');
  139. end;
  140.  
  141. procedure TMainForm.FormResize(Sender: TObject);
  142. begin
  143.   if hWin <> 0 then MoveWindow(hWin, 0, 0, pnlApp.ClientWidth, pnlApp.ClientHeight, True);
  144. end;
  145.  
  146. procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  147. begin
  148.   if hWin > 0 then PostMessage(hWin, WM_CLOSE, 0, 0);
  149. end;
  150.  
  151. end.
  152.  

 

TinyPortal © 2005-2018