Page 1 of 1
Embedding external applications within another application?
Posted: Thu May 22, 2008 8:20 pm
by dell_jockey
I have this software that does some OpenGL stuff in a fixed-size (borderless) window. It was NOT written in PB, however, I'd like to use PB to write an external program that:
- offers a control in which that external program is displayed/running/embedded
- through networking (most likely UDP based) offers the user a remote control to take influence in the actions of that external program.
The second part is not that difficult, as it is straight network programmng, which is supported by both languages.
But the BIG question is about this embedding thing. Is there a way to let an entire application be a sub-window within the application that calls it?
I know, not quite a trivial question, but perhaps someone here knows his way around the Win32 innards well enough....
bye
dell_jockey
Posted: Thu May 22, 2008 9:00 pm
by Thalius
Am not sure what you want to achieve.
However a communication ( atleast under windows ) is possible between two programs using WM Messages - probably easer than UDP if its only used local. Besides you could for example call that exe from PB and share handles, ressources ( shared-mem ) or whatever.
Thalius
Posted: Thu May 22, 2008 9:10 pm
by Mistrel
This is entirely possible but probably not in the way you're hoping for. What you'll need to do is run the two programs in parallel and communicate between the two using IPC.
To gain control over the other application you'll need to inject a DLL that will subclass the main window so you can communicate with it. Once you have communication established you should use shared memory and a mutex instead of window messages.
What you're asking for is complex but with a little effort it can be done.
See my post here:
http://www.purebasic.fr/english/viewtopic.php?t=30617
Posted: Thu May 22, 2008 9:22 pm
by Flype
about the gui embedding you can try something like this but i'm not sure that is what you want and this seems 'dangerous' depending on how is coded the embedded app.
but there's some bad repainting here, maybe someone can show how to repaint correctly. using callback/subclassing...
Code: Select all
#APPNAME1 = "Calculator"
Define *Parent
Define *Child
*Child = FindWindow_(0, #APPNAME1)
If Not *Child
RunProgram("calc.exe") : Delay(1000)
*Child = FindWindow_(0, #APPNAME1)
If Not *Child
MessageRequester("Error", #APPNAME1 + " must be running !")
End
EndIf
EndIf
*Parent = OpenWindow(0, 0, 0, 320, 240, "Master", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)
If *Parent
SetWindowColor(0, $AAAAAA)
CreateStatusBar(0, WindowID(0))
SetParent_(*Child, WindowID(0))
;SetWindowLong_(*Child, #GWL_STYLE, GetWindowLong_(*Child, #GWL_STYLE)&~#WS_CLIPCHILDREN)
SetWindowPos_(*Child, 0, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_SHOWWINDOW)
;RedrawWindow_(*Child,0,0,0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
If IsWindow_(*Child)
SetParent_(*Child, 0)
EndIf
CloseWindow(0)
Break
Case #PB_Event_Repaint
RedrawWindow_(*Child, 0, 0, #RDW_INTERNALPAINT|#RDW_INVALIDATE)
EndSelect
ForEver
EndIf
End
Posted: Thu May 22, 2008 9:37 pm
by srod
You can't subclass a window from another process flype - not unless you take the route of a global hook as suggested by Mistrel.
However, to get your re-painting working better, use #WM_PAINT in a callback - it's far better than the PB event when moving the window etc. Also, a slight modification to the RedrawWinwdow_() flags is required.
Code: Select all
#APPNAME1 = "Calculator"
Define *Parent
Global *Child
Procedure MyWindowCallback(hWnd, uMsg, wParam, lParam)
result = #PB_ProcessPureBasicEvents
Select uMsg
Case #WM_PAINT
RedrawWindow_(*Child, 0, 0, #RDW_INVALIDATE|#RDW_ERASE|#RDW_FRAME)
EndSelect
ProcedureReturn Result
EndProcedure
*Child = FindWindow_(0, #APPNAME1)
If Not *Child
RunProgram("calc.exe") : Delay(1000)
*Child = FindWindow_(0, #APPNAME1)
If Not *Child
MessageRequester("Error", #APPNAME1 + " must be running !")
End
EndIf
EndIf
*Parent = OpenWindow(0, 0, 0, 320, 240, "Master", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)
If *Parent
SetWindowColor(0, $AAAAAA)
CreateStatusBar(0, WindowID(0))
SetParent_(*Child, WindowID(0))
SetWindowPos_(*Child, 0, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_SHOWWINDOW)
SetWindowCallback(@MyWindowCallback())
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
If IsWindow_(*Child)
SetParent_(*Child, 0)
EndIf
CloseWindow(0)
Break
EndSelect
ForEver
EndIf
End
Posted: Thu May 22, 2008 10:22 pm
by dell_jockey
Stop it, you're way over my head here...
As to the communications: that I have covered.
It's the embedding of an external program that's giving me trouble. Perhaps I should use the kiosk system that was published elsewhere on this forum, although I'd rather have a tighter coupling between the main calling program and the other application that is being 'hosted' by the main program.
Srod & Flype: I ran both of your codes and the calculator was started allright, but the OpenWindow bit doesn't get displayed. The debugger isn't providing any additional information.
Thanks for responding!
Posted: Thu May 22, 2008 10:26 pm
by dell_jockey
Thalius wrote:Am not sure what you want to achieve.
You could descibe it as an main application that can host another application (or perhaps only hosts/displays the output of that other application). Part of the main app should function as a 'presentation frame' that shows the output of that other app.
clear as mud?
Posted: Thu May 22, 2008 11:03 pm
by Flype
and the childs apps are made by you (same conceptor as the main app) or by anybody else ?
Posted: Fri May 23, 2008 11:16 am
by dell_jockey
Flype wrote:and the childs apps are made by you (same conceptor as the main app) or by anybody else ?
both can happen, but either case, these apps will normally initialise a borderless window (either 800x600 or 1024x768 24/32bit graphics) and diplay their graphics there, much in the way full-screen games do.
I'm looking for a 'framework' in which to display/host such external applications.
Since these apps indeed open a borderless window (it's not full-screen graphics), one idea might be to use the kiosk-code mentioned before to start the external app, and somehow instruct that external application to start 'screen centered' and 'always on top'. This way, I could still have the hosting software active and still have the external app visible at all times. Within this setting I should rephrase my question: how to instruct an external program to initialise itself 'screen centered' and 'always on top'. Does this spark any new ideas?