How to design an app with "dynamic external objects"?

Everything else that doesn't fall into one of the other PB categories.
Marco2007
Enthusiast
Enthusiast
Posts: 648
Joined: Tue Jun 12, 2007 10:30 am
Location: not there...

How to design an app with "dynamic external objects"?

Post by Marco2007 »

Hi,

has anyone a good idea, how to design an app with this requirements:
- one finished exe (the main window - with general stuff)
- From time to time I will add differents "objects" with different "methodes" (maybe in different windows with different Gadgets), which need to do something with the main exe...

Is there simple way?

Til now, I added always new stuff into the main code, compiled it and exchanged the exe.
I don`t want to do this anymore.

I hope, you know, what I mean....

br and thx
PureBasic for Windows
Zach
Addict
Addict
Posts: 1678
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: How to design an app with "dynamic external objects"?

Post by Zach »

DLL-based plugin system ?
User avatar
Programie
User
User
Posts: 30
Joined: Thu Aug 09, 2007 11:26 am
Location: Gernsbach (Germany)
Contact:

Re: How to design an app with "dynamic external objects"?

Post by Programie »

I'm currently doing the same what you want to do: Making an application extendable dynamically.
But: A lot of stuff is different from a normal application with static content. At the German PureBasic forums I've asked about the events of gadgets, because they where not handled like I want it should handle it... However the code may be useful for you: http://forums.purebasic.com/german/view ... =3&t=23748


The code from the post above with some bug fixes:

Main application:

Code: Select all

Enumeration
   #Window
   #Menu
   #MDI
   #Dll
EndEnumeration

If OpenWindow(#Window,100,100,600,400,"Main App",#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
   If CreateMenu(#Menu,WindowID(#Window))
      MenuTitle("MDI")
   EndIf
   MDIGadget(#MDI,0,0,0,0,0,0,#PB_MDI_AutoSize)
   Window=AddGadgetItem(#MDI,#PB_Any,"Child DLL")
   If OpenLibrary(#Dll,"Child.dll")
      CallFunction(#Dll,"AddObjects",WindowID(Window))
      Repeat
         Select WaitWindowEvent()
            Case #PB_Event_Gadget
               MessageRequester("Gadget Event","Gadget: "+Str(EventGadget()))
            Case #PB_Event_CloseWindow
               If EventWindow()=#Window
                  Quit=#True
               EndIf
         EndSelect
      Until Quit
      CallFunction(#Dll,"Unload")
      CloseWindow(Window)
      CloseLibrary(Dll)
   EndIf
EndIf
DLL (Child.dll):

Code: Select all

Global ThreadID
Global Unload.b

Procedure ChildWindow(ChildWindowID)
   OpenWindow(0,0,0,0,0,"",#PB_Window_Invisible)
   UseGadgetList(ChildWindowID)
   ButtonGadget(#PB_Any,10,10,100,30,"Button 1")
   ContainerGadget(#PB_Any,10,50,120,50,#PB_Container_Flat)
      ButtonGadget(#PB_Any,10,10,100,30,"Button 2")
   CloseGadgetList()
   Repeat
      Select WaitWindowEvent(5)
         Case #PB_Event_Gadget
            MessageRequester("Child Gadget Event","Gadget: "+Str(EventGadget()))
      EndSelect
   Until Unload
EndProcedure

ProcedureDLL AddObjects(ChildWindowID)
   ThreadID=CreateThread(@ChildWindow(),ChildWindowID)
EndProcedure

ProcedureDLL Unload()
   Unload=#True
   WaitThread(ThreadID,3000)
   If IsThread(ThreadID)
      KillThread(ThreadID)
   EndIf
EndProcedure
The code has one known bug: If you click on the first button which is handled by the main application, the event only occurs if you move the mouse away from the button. The second button is handled by the DLL because the gadget is in another gadget (ContainerGadget).
ImageImageImageImage
User avatar
skywalk
Addict
Addict
Posts: 4318
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: How to design an app with "dynamic external objects"?

Post by skywalk »

Isn't this the same problem as creating a dynamic menu? Like a MRU list?
For a dynamic menu, I have to add the new menu elements and then recreate the entire menu on the target window.
The menu specifics are stored in a structured array.

For a dynamic GUI, I do the same.
The structured gadget array is obviously more complex, but not too much.
Have a look at the native gadget creation commands. There are many common properties.
Store the static GUI contents in an external file or DataSection(according to gadget type: W-window, ED-Editor,BU-Button,etc.) and then append the new dynamic contents to the gad(). Hide the target window and repopulate according to the gadgets in gad(). And you must use #PB_Any. You will have to add Open and CloseGadgetList's depending on your gadget nesting.

Code: Select all

; snippet...
With gad(i)
  \id = OpenWindow(#PB_Any,    \x, \y, \wd, \ht, \Txt,  \Flags|#PB_Window_Invisible)
  \id = ButtonGadget(#PB_Any,  \X, \Y, \Wd, \Ht, \Txt,  \Flags)
  \id = CalendarGadget(#PB_Any,\X, \Y, \Wd, \Ht, #Null, \Flags)
  \id = EditorGadget(#PB_Any,  \x, \y, \Wd, \Ht,        \Flags)
  \id = ListViewGadget(#PB_Any,\x, \y, \Wd, \Ht,        \Flags)
  ;...and so on...
EndWith
This only populates the GUI. It does not create the Event handlers.
Think how the Visual Designers work?
They create the same dynamic GUI based on user point and click, but output #Enumerations for the gadgets created.
If you create the GUI dynamically, then you have the gad(i)\id's already in an array to process in your Events sections.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Programie
User
User
Posts: 30
Joined: Thu Aug 09, 2007 11:26 am
Location: Gernsbach (Germany)
Contact:

Re: How to design an app with "dynamic external objects"?

Post by Programie »

skywalk wrote:This only populates the GUI. It does not create the Event handlers.
Think how the Visual Designers work?
They create the same dynamic GUI based on user point and click, but output #Enumerations for the gadgets created.
If you create the GUI dynamically, then you have the gad(i)\id's already in an array to process in your Events sections.
And... the Visual Design doesn't handle events. ;)
Just gadgets without events makes no sense. :mrgreen:
ImageImageImageImage
User avatar
skywalk
Addict
Addict
Posts: 4318
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: How to design an app with "dynamic external objects"?

Post by skywalk »

Programie wrote:Just gadgets without events makes no sense.
Well of course. You still have to create the Event code, but you have all the new recipients of messages in the gad() array. :?:
The response to those messages cannot totally be automated. That is the heart of your code.

Code: Select all

; snippet...
Case #PB_Event_Gadget   
    evG = EventGadget()
    evT = EventType()      
    If evG = gad(i)\id    ; 'i' can be substituted for custom enumerations based on your desired algorithm.
     ; i = #Window_GadgetType_Description = #MainW_PANEL_ADDRESS 
     ; Panel selected/changed on Main Window
     ; Do something...
    EndIf
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Zach
Addict
Addict
Posts: 1678
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: How to design an app with "dynamic external objects"?

Post by Zach »

I could be going way off the rails here.

But what about using XML based configuration files? Or some other format that could be easily and quickly parsed (you'd still have to write a parser).
If the GUI elements and events were configured in this way, you might end up with a nearly-realtime dynamic system? Perhaps throwing scripts into the mix if necesarry.

I don't know how complex the application you are writing is, or what its intended to do but it was just a thought that came to me.

The idea being, if your app is parsing said files at run time, you could have it re-parsing the files not every cycle, but every so often.. Or alternatively (or in addition to re-parse checks) setup a GUI command/Hotkey command that will instruct the program to re-parse its config files on demand. Perhaps start it off with a check against file size (open the files, parse them, then close them); so it checks that the file has changed size and proceeds to open the file again and parse it to update what the program is doing. So then the GUI could be re-drawn if needed and new events would be listened for, etc.. That mainly works for something like a GUI, but I'm not sure how well that would work for adding actual functionality (i.e code) which is where scripts could also come in I guess. An embeddable language like Python or LUA, etc. might come in handy there.

But that may be an oversimplification of a complex implementation to actually attempt...

XML + DLL files may be a better approach versus scripting though. If you skeleton the GUI and events with XML, that leaves the door open for you to write in the appropriate calls to the new DLL functions from your GUI elements. Then either manually trigger a re-parse, or wait for a re-parse check to pick up the changes.

Anyway just an idea I had. Maybe it will give you a better idea?
Post Reply