Jump to content
dkounal

Show a FMX form inside a dll from a VCL application

Recommended Posts

Hi,

I have a dll with a FMX form inside. Four procedures are exported to create and destroy the form. No other interaction exists.

var xform:Txform;

function CreatexForm: HWnd; stdcall;
begin 
try 
	if not Assigned(xform) then xform:=Txform.Create(nil);
	Result:=xform.GetHWnd; 
except 
	Result:=INVALID_HANDLE_VALUE; 
end; 
end;

procedure ShowxForm; stdcall;
begin 
	if Assigned(xform) then xform.Show; 
end;

procedure HidexForm; stdcall;
begin 
	if Assigned(xform) then xform.Hide; 
end;

procedure DestroyxForm; stdcall;
begin 
	if Assigned(xform) then FreeAndNil(xform); 
end;

I want to use it from a VCL application that loads the DLL, show the form before closing.

The testing VCL application just load DLL, calls CreatexFrom and ShowxForm to show the FMX form from the DLL.

I click the system close button in the shown FMX form from the DLL

Then I call DestroyxForm, and FreeLibrary and the DLL unloads without problems.

I am getting an Exception just when VCL forms that called the DLL closes.

 

I have searched about the subject but I found only results that deal with FMX forms from DLL inside VCL controls or forms. That it is not my case.

Any ideas? Tank you in advance

Share this post


Link to post

This is way more complicated than you might hope. Your VCL app will run a message loop that is designed for VCL. It's not going to be able to service your FMX form. I don't expect there is a simple solution.

 

btw, INVALID_HANDLE_VALUE is for HANDLE types, i.e. THandle in Delphi. For an invalid HWND use NULL, which is 0 in Delphi.

  • Like 1

Share this post


Link to post
1 minute ago, David Heffernan said:

This is way more complicated than you might hope. Your VCL app will run a message loop that is designed for VCL. It's not going to be able to service your FMX form. I don't expect there is a simple solution.

 

btw, INVALID_HANDLE_VALUE is for HANDLE types, i.e. THandle in Delphi. For an invalid HWND use NULL, which is 0 in Delphi.

Thank you for your response.

I have read not enthusiastic comments about having VCL and FMX together. I have tested the Firemonkey-container but I have usually strange internal compiler errors and I do not feel safe.

The FMX form is a user customized form that should be able to run in all environments but for windows I have a VCL app that I do not want to change.

I should probably forget FMX and try something else for these forms.

Share this post


Link to post

If I have the FMX form to run as a separate process, in an separate executable, is it possible to embed it in a vcl control (ex tpanel) by using its window's handle?

Share this post


Link to post
31 minutes ago, dkounal said:

If I have the FMX form to run as a separate process, in an separate executable, is it possible to embed it in a vcl control (ex tpanel) by using its window's handle?

It works with the following code I found:

procedure TForm1.ShowAppEmbedded(WindowHandle: THandle; Container: TWinControl);
var WindowStyle : Integer; FAppThreadID: Cardinal;
begin
  /// Set running app window styles.
  WindowStyle := GetWindowLong(WindowHandle, GWL_STYLE);
  WindowStyle := WindowStyle
                 - WS_CAPTION
                 - WS_BORDER
                 - WS_OVERLAPPED
                 - WS_THICKFRAME;
  SetWindowLong(WindowHandle,GWL_STYLE,WindowStyle);

  /// Attach container app input thread to the running app input thread, so that
  ///  the running app receives user input.
  FAppThreadID := GetWindowThreadProcessId(WindowHandle, nil);
  AttachThreadInput(GetCurrentThreadId, FAppThreadID, True);

  /// Changing parent of the running app to our provided container control
  winapi.Windows.SetParent(WindowHandle,Container.Handle);
  SendMessage(Container.Handle, WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
  UpdateWindow(WindowHandle);

  /// This prevents the parent control to redraw on the area of its child windows (the running app)
  SetWindowLong(Container.Handle, GWL_STYLE, GetWindowLong(Container.Handle,GWL_STYLE) or WS_CLIPCHILDREN);
  /// Make the running app to fill all the client area of the container
  SetWindowPos(WindowHandle,0,0,0,Container.ClientWidth,Container.ClientHeight,SWP_NOZORDER);

  SetForegroundWindow(WindowHandle);
end;

 

Share this post


Link to post

I believe Remobjects Hydra can help you with this. If you go to https://hydra.remobjects.com/hydra/tour.aspx,

you can see there is a section

 

"Combining VCL and Firemonkey"

....

Hydra provides a solution for this problem by allowing developers to integrate FireMonkey UI seamlessly with their existing VCL applications, or conversely add existing VCL user interfaces into new FireMonkey apps.

...

  • Like 1

Share this post


Link to post
14 minutes ago, Dave Novo said:

I believe Remobjects Hydra can help you with this. If you go to https://hydra.remobjects.com/hydra/tour.aspx,

you can see there is a section

 

"Combining VCL and Firemonkey"

....

Hydra provides a solution for this problem by allowing developers to integrate FireMonkey UI seamlessly with their existing VCL applications, or conversely add existing VCL user interfaces into new FireMonkey apps.

...

As my project is just minimal for the moment I will try the separate process.

RemObjects's hydra is really interesting, I will give it a try

Thank you

Share this post


Link to post
3 hours ago, dkounal said:

I should probably forget FMX and try something else for these forms.

Seems like a sound idea to me

Share this post


Link to post

@dkounalI have done this kind of code: In a DLL, a single FMX form showing and animating a 3D model. The DLL is loaded by a VCL application and parented to a TPanel. Everything works nice and easy except one thing: When the VCL application closes, it hangs if the FMX DLL is unloaded (FreeLibrary). I simple didn't unload the DLL which is not a problem since the DLL is an Add-on that has the same life time as the main VCL application. Anyway Window unload the DLL by itself.

 

Share this post


Link to post
2 hours ago, Remy Lebeau said:

Thank you, I did not know it.

2 hours ago, FPiette said:

@dkounalI have done this kind of code: In a DLL, a single FMX form showing and animating a 3D model. The DLL is loaded by a VCL application and parented to a TPanel. Everything works nice and easy except one thing: When the VCL application closes, it hangs if the FMX DLL is unloaded (FreeLibrary). I simple didn't unload the DLL which is not a problem since the DLL is an Add-on that has the same life time as the main VCL application. Anyway Window unload the DLL by itself.

 

To be honest I started from your code as it is here.

The problem is that even without unloading the DLL the exception happens.

It happens inside the Thtmleditor component, when it frees a TGPRegion and I believe it has to do with GDI+

It is mentioned here and here but I am not so experienced to deal with it.

 

Share this post


Link to post

@dkounalAll I can says is that my code works for what I am doing with it. In the link @Remy Lebeaugave, it is stated that it is legal but full of traps. What I do is very simple in the relationship between the VCL exe and the FMX dll but probably doing more complex things require more code.

 

The question you have to ask yourself is "Why in the first place do I need FMX?". In my case, FMX offer 3D model rendering and animation incredibly easy. I did a quick test and it worked fine. The VCL part was required because I already had huge VCL code for the everything else in the application.

  • Like 1

Share this post


Link to post
4 hours ago, FPiette said:

@dkounalAll I can says is that my code works for what I am doing with it. In the link @Remy Lebeaugave, it is stated that it is legal but full of traps. What I do is very simple in the relationship between the VCL exe and the FMX dll but probably doing more complex things require more code.

 

The question you have to ask yourself is "Why in the first place do I need FMX?". In my case, FMX offer 3D model rendering and animation incredibly easy. I did a quick test and it worked fine. The VCL part was required because I already had huge VCL code for the everything else in the application.

I have a working application in VCL that it does not worth to transform it to FMX. And I need custom interactive forms with controls inside created once by the user and being available to run in both VCL and mobile apps.

Until now, I am a bit afraid to invest in FMX. This was a first attempt in windows.

Share this post


Link to post
35 minutes ago, dkounal said:

Until now, I am a bit afraid to invest in FMX. This was a first attempt in windows.

IMO it is not a good idea to start learning FMX by a project mixing VCL and FMX!

If you need to run on Windows and mobile, the choice with Delphi and native application is FMX framework.

Another possibility is to create a frontend web application (UI) and a backend application. In that architecture, you can write the backend with VCL and the frontend (UI written in HTML, CSS and JavaScript) will run in a browser on both Windows and Mobile. This will require a lot of effort to port your current application to that architecture. Embarcadero RadServer is designed for that kind of architecture.

 

  • Like 1

Share this post


Link to post
53 minutes ago, FPiette said:

IMO it is not a good idea to start learning FMX by a project mixing VCL and FMX!

If you need to run on Windows and mobile, the choice with Delphi and native application is FMX framework.

Another possibility is to create a frontend web application (UI) and a backend application. In that architecture, you can write the backend with VCL and the frontend (UI written in HTML, CSS and JavaScript) will run in a browser on both Windows and Mobile. This will require a lot of effort to port your current application to that architecture. Embarcadero RadServer is designed for that kind of architecture.

 

The new editor is in FMX, the existing application will take time to change and needs just this FMX form type. Until now it works with the exception when finishing. I am testing it.

For the moment I am moving part of the code in a web service using XData.

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×