Recent

Author Topic: Forms inside libraries in a cross-platform way  (Read 9741 times)

lagprogramming

  • Sr. Member
  • ****
  • Posts: 409
Forms inside libraries in a cross-platform way
« on: November 02, 2015, 07:53:32 pm »
   I'm looking for an unusual way to store applications(TForms with other interactive components) within libraries(*.dll and *.so like files).

1. I'd like the libraries to be able to be easily cross-compiled and easily delivered to other users. This means that 3rd party items should be avoided as much as possible. Involving qt or gtk are out of the question. The only remaining possibilities that I know of are customdrawing, fpgui and msegui. If there is a possibility to completely ignore X/GDI, that's even better. This means that the entire form render would have to be done in a memory buffer by "software" mode.

2. For now, I don't know exactly how the interface should look like, but for sure the library(that contains the forms) should provide a way to receive some inputs like mouse and keyboard and to "export" an image of the combined forms. By "image" I mean something like a bitmap file. This means that what I'm looking for can be done 100% in pascal. Probably using a message like system would be enough, but those messages should be consistent between platforms. This means that a CALLER application should not care about OS-CPU platform, the values should be consistent(the same).

   The purpose is to design an application, build the application and store it in a library. The library should act like an add-on to a CALLER application. The CALLER application should call few subroutines(like using a small interface) and send to the called application mouse/keyboard events and after that, read the image(bitmap like) of the rendered application.
   PIECE OF CAKE ISN'T IT!?  :o   

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Forms inside libraries in a cross-platform way
« Reply #1 on: November 02, 2015, 08:45:18 pm »
You really should have a conversation with fredvs   ;)

I believe he made some post regarding his endeavors here on the forums (sorry, i'm lazy atm).

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12771
  • FPC developer.
Re: Forms inside libraries in a cross-platform way
« Reply #2 on: November 02, 2015, 09:16:24 pm »
If you wouldn't run into the typical packages problems, I say simply create an abstraction of the GUI that you would allow the plugins, put that in a DLL/.so, and have the plugins use that instead of going directly to 3rd party libs like fpgui, MSE etc.


taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms inside libraries in a cross-platform way
« Reply #3 on: November 02, 2015, 09:19:03 pm »
   PIECE OF CAKE ISN'T IT!?  :o   
Easier than you might think. Since all the application will be on the dll, so and not parts of it that means that no graphics, forms, classes, etc needs to be  shared between the dll and the application the loader will simple load the dll call a default procedure which will establish an application loop and only return the control to the application after the user exited. That means that the loader will not have any short of application loop it self at all.

You need a bit of magic to attach the dlls main loop as the application loop but nothing difficult to do. You need to read up on how the linux/windows application establish their application loops nothing more than 2 days work and an other day to find out how that is used inside a lazarus application and you will be sharing dll applications in no time.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

lagprogramming

  • Sr. Member
  • ****
  • Posts: 409
Re: Forms inside libraries in a cross-platform way
« Reply #4 on: November 03, 2015, 12:43:01 pm »
   One requirement is for the application stored inside the library to be able to output the rendered image. The rendered image might contain more than a form. For example, a messagebox may be considered a different form, tooltips(hints) might be considered new forms, too. Z-order of the Tforms complicate things even further. The only solution I see would be to use a widgetset that supports exporting the virtual screen(monitor). The virtual screen would be the screen that contains the entire image(gui) of the library saved application.
   If I didn't uselessly complicated things, I wonder which of fpgui, msegui and lcl-customdrawing has at least a partial support for this kind of rendering. If I've complicated things, is there an easier solution?

balazsszekely

  • Guest
Re: Forms inside libraries in a cross-platform way
« Reply #5 on: November 03, 2015, 01:28:04 pm »
This is some kind of plugin system?

x2nie

  • Hero Member
  • *****
  • Posts: 515
  • Impossible=I don't know the way
    • impossible is nothing - www.x2nie.com
Re: Forms inside libraries in a cross-platform way
« Reply #6 on: November 03, 2015, 03:43:26 pm »
Hope it help: http://wiki.freepascal.org/Creating_LCL_Control_From_Libraries


I've tried that demos several years ago.. it works.


anyway, few days ago I download a newer one, which is add feature: able to set big string property, let say 2GB string length. this one is here http://breakoutbox.de/pascal/pascal.html search titled: "DLLConnect" and download the zip. both is similar (although identical).
When you were logged in, you can see attachments.
Lazarus Github @ UbuntuCinnamon-v22.04.1 + LinuxMintDebianEdition5

lagprogramming

  • Sr. Member
  • ****
  • Posts: 409
Re: Forms inside libraries in a cross-platform way
« Reply #7 on: November 03, 2015, 04:41:32 pm »
   Yes, a plugin like system that should be able to work like in the following example.

   A developer would build a gui application by storing the forms inside a library. This library would contain the CALLED application.
   Another developer builds the CALLER application by dropping a TImage descendant on a form.

   When put together in end-user's computer, the CALLER will execute a library subroutine like "getbitmapimage()" and after that will render the bitmap into the TImage descendant. The library involved is the CALLED application.
   When moving and clicking the mouse over the TImage descendant, the CALLER will execute something like "sendmessage()" subroutine that is found in the library. If mouse was clicked over a TComboBox then the updated image(using "getbitmapimage()") will show the combobox with a dropped down list.
   Freeing the TImage descendant would start by sending a terminate signal to the CALLED application(again by executing "sendmessage()"). There should be a way to see if the CALLED application is still running because it can terminate by itself when using "Exit" menus or halted by exceptions...but this is rather advanced for now.
   There wouldn't be many messages types involved. If such a message system would be implemented, then the message codes/values would have to be the same across CPU-OS platforms.

   If things are not clear enough I can explain again in a different manner, or give additional informations.
   I'm not sure that this is the best approach, but the idea is to be able to read an image stream(like a 32bit bitmap) of the CALLED application and send input messages like mouse and keyboard. The library should not create new windows in the OS, just update a bitmap like image. The update would be upon request(if that's possible, in order to avoid useless automatic updates) and the image would be shown in a TImage like descendant.

   The above example is not exactly how I'd like to use this system but it's getting very close.

balazsszekely

  • Guest
Re: Forms inside libraries in a cross-platform way
« Reply #8 on: November 03, 2015, 08:54:48 pm »
@lagprogramming

Still not clear what are you after, however the following example(see attachment) I believe will fits your needs. The test application will load a dll(so) which contains a form. On the form you can find a TPanel, TImage and a few TButtons.  After the dll form is loaded it becomes embedded in the test application's main form. At this point you can do different operations between the test application and the dll/so.
I tested both on windows and linux. With small modification it should work under OSX too. After you build the library don't forget to copy into the test project directory, because the test project uses relative paths.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms inside libraries in a cross-platform way
« Reply #9 on: November 03, 2015, 08:54:55 pm »
   Yes, a plugin like system that should be able to work like in the following example.

   A developer would build a gui application by storing the forms inside a library. This library would contain the CALLED application.
   Another developer builds the CALLER application by dropping a TImage descendant on a form.

   When put together in end-user's computer, the CALLER will execute a library subroutine like "getbitmapimage()" and after that will render the bitmap into the TImage descendant. The library involved is the CALLED application.
   When moving and clicking the mouse over the TImage descendant, the CALLER will execute something like "sendmessage()" subroutine that is found in the library. If mouse was clicked over a TComboBox then the updated image(using "getbitmapimage()") will show the combobox with a dropped down list.
   Freeing the TImage descendant would start by sending a terminate signal to the CALLED application(again by executing "sendmessage()"). There should be a way to see if the CALLED application is still running because it can terminate by itself when using "Exit" menus or halted by exceptions...but this is rather advanced for now.
   There wouldn't be many messages types involved. If such a message system would be implemented, then the message codes/values would have to be the same across CPU-OS platforms.

   If things are not clear enough I can explain again in a different manner, or give additional informations.
   I'm not sure that this is the best approach, but the idea is to be able to read an image stream(like a 32bit bitmap) of the CALLED application and send input messages like mouse and keyboard. The library should not create new windows in the OS, just update a bitmap like image. The update would be upon request(if that's possible, in order to avoid useless automatic updates) and the image would be shown in a TImage like descendant.

   The above example is not exactly how I'd like to use this system but it's getting very close.
Are you trying to build a cross compiler plugin system? Eg the caller build with fpc 3 the plugin with fpc 2.2.0 or gcc and have them work together? What you describe is not a plugin system its a remote desktop system which there are a couple open source out there you can use and if I remember correctly there is one written in delphi somewhere on the github too, but I did not pay much attention when reading about it so I do not remember anything else.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

lagprogramming

  • Sr. Member
  • ****
  • Posts: 409
Re: Forms inside libraries in a cross-platform way
« Reply #10 on: November 04, 2015, 01:23:27 pm »
Are you trying to build a cross compiler plugin system? Eg the caller build with fpc 3 the plugin with fpc 2.2.0 or gcc and have them work together?
   I'd like to know if I can combine two experiments. One of them is a 3D virtual environment. Add-ons would have to be shown inside this 3D virtual environment. The add-ons are stored in library files and should be able to be built using any compiler. I think the dificult part lies at widgetset level. The first implemented add-on of this kind, would be the maintainer part of Flavouring Control System, which is another experiment. All of them are closed source.


   @GetMem
   I've looked at the attachement, I need the opposite of that.  :) The TImage will be the plugin container. The only way the plugin container will show the plugins is by loading their rendered bitmaps from pointers. The pointer will be returned by the plugin upon container's request.
   If a handle would be passed to the plugin by the container, the plugin should not use the handle to create visible components.
   How to interact with the plugin!? You send the "On..." events(or the messages) of the TImage(plugin container) to the plugin(TForm windows) using a dedicated procedure. For example, when you move the mouse over the TImage(the plugin container) you will use:

Code: Pascal  [Select][+][-]
  1. procedure TfPluginForm.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  2. //It's just a sketch for presentation purpose, I would avoid the "On..." events.
  3. begin
  4.   //Send the mouse move message to the plugin
  5.   plugin.sendmessage('mousemove',Shift,X,Y);
  6.  
  7.   {Ask the plugin to update the bitmap stream.
  8.    The way the plugin fills the bitmap stream should be of no concern to the plugin container.
  9.    No visible components should appear during this process.}
  10.   plugin.render;
  11.  
  12.   {Show the plugin rendered image.
  13.    The bitmap might contain buttons, comboboxes, new windows, whatever the plugin drawn and saved in that bitmap buffer.}
  14.   Image1.loadfrombuffer(plugin.outputimage);
  15. end;


   This is an analogy.
   The plugin container is like a 3d-shooter genre game, something like Doom or Heretic. The plugin makes some walls interactive.
   On various walls, instead of ordinary brick textures a user might also see screens of running applications. These running applications are the plugins of the game. These applications are real, they run in that computer, but their visual output lies on walls as textures, not on user's screen directly. Not only that the image seen by the user in the 3d environment is consistent with what the user would normally see if the application would have been executed in a 2D desktop environment, but also moving and firing "guns" over the wall would be the equivalent of mouse clicks for those applications. Pressing keyboard buttons when the "player" is close to a wall that has such a plugin, will make the container send those keyboard events to the plugin.
   As you see, the container must use textures. These textures must be updated by reading a bitmap image from the library(plugin). Mouse and keyboard events must be sent to the plugin by using procedures that are stored inside the library. The visual output of the plugin must be in a bitmap buffer that's read by the plugin container, not outputed directly on the screen by the plugin.

   Did the above analogy made things clearer or I've managed to add additional noise over the subject? :)

balazsszekely

  • Guest
Re: Forms inside libraries in a cross-platform way
« Reply #11 on: November 04, 2015, 02:05:32 pm »
@lagprogramming
Yes, now it's much clearer what are you after. If you take a look at my example, you can see how I passed a window handle from the application to the library(this will work in cross platform way). Since all bmp has a handle(HBITMAP) you can do the same, just in the opposite direction. You call an exported function from inside the library, which will create the bmp, process it according to the coordinates and other param(s). The function will return the handle of bmp, which then can be displayed in the plugin container. Ok, this is a non-trivial operation but it's not particularly difficult either. Since the plugin has a form you can also use messages, between the windows(PostMessage for example) to pass the handle of the bitmap. I would stay with options one though.

nomorelogic

  • Full Member
  • ***
  • Posts: 196
Re: Forms inside libraries in a cross-platform way
« Reply #12 on: November 12, 2015, 07:58:09 pm »
@lagprogramming

Still not clear what are you after, however the following example(see attachment) I believe will fits your needs. The test application will load a dll(so) which contains a form. On the form you can find a TPanel, TImage and a few TButtons.  After the dll form is loaded it becomes embedded in the test application's main form. At this point you can do different operations between the test application and the dll/so.
I tested both on windows and linux. With small modification it should work under OSX too. After you build the library don't forget to copy into the test project directory, because the test project uses relative paths.

Hi, I'm working on similar plugin but I'm making a mistake that can not understand

in the (attached) exe application I can access to a form created by a library but I can't show it.
uncommenting ref.Show I get an exception
can someone explain me why?

thanks in advantage

Code: Pascal  [Select][+][-]
  1. procedure TfmMain.btStartClick(Sender: TObject);
  2. begin
  3.    ref:=GetTestPluginInstance;
  4.    ref.caption:=ref.caption + ' modified';
  5.    meLog.Lines.Add('showing ' + ref.Caption);
  6.    // ref.Show;  // <- this raise the exception
  7. end;
  8.  


marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12771
  • FPC developer.
Re: Forms inside libraries in a cross-platform way
« Reply #13 on: November 12, 2015, 08:00:22 pm »
Did you read the link in the 3rd post?

balazsszekely

  • Guest
Re: Forms inside libraries in a cross-platform way
« Reply #14 on: November 12, 2015, 10:04:31 pm »
Quote
@nomorelogic
can someone explain me why?

Code: Pascal  [Select][+][-]
  1. function GetTestPluginInstance: TForm; {$IFDEF UNIX}cdecl;{$ELSE}stdcall;{$ENDIF}
  2. begin
  3.   Application.Initialize; //<-- insert this line
  4.   result := TForm.Create(nil);
  5.   result.Caption := 'Test Instance';
  6. end;  

 

TinyPortal © 2005-2018