Window from DLL issue

Just starting out? Need help? Post your questions and find answers here.
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Window from DLL issue

Post by Kurti2023 »

Hi all,

below you can find a simple code snipped which will load a Window from a DLL
If you complie the code for application.exe and test.dll you will see the following
behavior:

click the "Test.." button:
- MessageRequester "Before OpenMyWindow" will be displayed
- new window "My Window" will be displayed
- close "My Window"
- no MessageRequester "After OpenMyWindow" will be displayed or executed

I have noticed that every code after the call to the DLL which opens the new window does not get executed anymore
or can be debugged.

It would be very helpful if somebody with more knowledge in this area could give me a hint what's wrong with the code.

Best regards,
Kurti

Code: Select all

;_____________________________________________________________________________________
; Application.exe

If OpenLibrary(0, "Test.dll") = 0
  MessageRequester("Application", "Test.dll failed", #PB_MessageRequester_Info)
  End
EndIf


Procedure ButtonHandlerTest()
  MessageRequester("Application", "Before OpenMyWindow", #PB_MessageRequester_Info)
  CallFunction(0, "OpenMyWindow")
  MessageRequester("Application", "After OpenMyWindow", #PB_MessageRequester_Info)
EndProcedure


Procedure CloseEvent()
  id = EventWindow()
  UnbindEvent(#PB_Event_CloseWindow, @CloseEvent(), id)
  CloseWindow(id)
  CloseLibrary(0)
EndProcedure


If OpenWindow(0, 0, 0, 400, 400, "Application", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) 
   BindEvent(#PB_Event_CloseWindow, @CloseEvent(), 0)
     
   ButtonGadget(1,10,30,150,20,"Test...")
   BindGadgetEvent(1, @ButtonHandlerTest())
     
   Repeat
     EventID=WaitWindowEvent()
   Until EventID=#PB_Event_CloseWindow
      
EndIf


; Executable = Application.exe



; __________________________________________________________________________________________
; Test.dll 

Procedure MyCloseEvent()
  id = EventWindow()
  UnbindEvent(#PB_Event_CloseWindow, @MyCloseEvent(), id)
  CloseWindow(id)
EndProcedure


ProcedureDLL OpenMyWindow()
  OpenWindow(2, 0, 0, 300, 200, "My Window", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  BindEvent(#PB_Event_CloseWindow, @MyCloseEvent(), 2)
  
  Repeat
      EventID=WaitWindowEvent()
  Until EventID=#PB_Event_CloseWindow
EndProcedure

; Executable = Test.dll
// Code Tags added (Kiffi)
jassing
Addict
Addict
Posts: 1745
Joined: Wed Feb 17, 2010 12:00 am

Re: Window from DLL issue

Post by jassing »

I didn't spend much time on this -- just quick n dirty

Code: Select all

EnableExplicit
CompilerIf #PB_Compiler_ExecutableFormat = #PB_Compiler_DLL
  ; Test.dll 
  
  Procedure OpenWindowThread(nul)
    If IsWindow(2)
      OutputDebugString_("show window")
      ShowWindow_(WindowID(2),#SW_SHOWNORMAL)
          SetForegroundWindow_(WindowID(2))
    ;SetFocus_(WindowID(2))
    ;SetActiveWindow_(WindowID(2))

    Else 
      OutputDebugString_("Open window")
      OpenWindow(2, 0, 0, 300, 200, "My Window", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
      
      Repeat
      Until WaitWindowEvent(100)=#PB_Event_CloseWindow
    EndIf 
  EndProcedure
  
  ProcedureDLL OpenMyWindow()
    CreateThread(@OpenWindowThread(),#NUL)
  EndProcedure
  
CompilerElse 
  ; Application.exe
  Define eventid  
  If OpenLibrary(0, "Test.dll") = 0
    MessageRequester("Application", "Test.dll failed", #PB_MessageRequester_Info)
    End
  EndIf
  
  If OpenWindow(0, 0, 0, 400, 400, "Application", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) 
    
    ButtonGadget(1,10,30,150,20,"Test...")
    
    Repeat
      EventID=WaitWindowEvent(100)
      Select eventid
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 1
              CallFunction(0,"OpenMyWindow")
          EndSelect
      EndSelect
      
    Until EventID=#PB_Event_CloseWindow
    
  EndIf
  
CompilerEndIf

; IDE Options = PureBasic 6.02 LTS (Windows - x64)
; ExecutableFormat = Shared dll
; Optimizer
; EnableThread
; Executable = test.dll
; EnablePurifier
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Hello jassing

thanks for the provided code.

I did a test with the code and run into a problem.
Hint: I copy and pasted your code and created the new application.exe and test.dll from it

- If you click the test button everything is OK.
- if you click the test button again (second time when application.exe is still running) the MyWindow does not show up anymore.

I tried to fix it but I'm not able to see where the problem is.

Is it possible for you to have one more look at it ?

Cheers
Kurti
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Window from DLL issue

Post by mk-soft »

The problem is that a Purebasic Windows DLL has its own window and event management and does not communicate with the main program.

Therefore, the DLL must have its own constantly running event loop and must trigger the creation of the DLL window.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Thanks for feedback on this topic.

I don't kow if I don't get it but I thought when I invoke CallFunction(0, "OpenMyWindow")
the window is created inside the Test.dll and it's own thread.. Inside the dll the events happen.

I there a possibility that you can provide some helper code which can execute a statement
after the function call to the test.dll

I mean:

Procedure ButtonHandlerTest()
CallFunction(0, "OpenMyWindow") ; with this statement I assumed that the window and event processing is handled inside the dll
Testing = 2 ; a simple statement like this will not be processed and that's my issue.
EndProcedure.

So for me it looks like that after the CallFunction there is no return to the next statement and this is my issue.

Cheers
Kurti
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Hi all,

the code is now finally working so I provide it as final example for those who also struggle.
Thanks for the previous help on this topic.

Cheers
Kurti

Code: Select all

;test.dll code start:_________________________________________________________________________________
 

Procedure CloseEvent()
  id = EventWindow()
  UnbindEvent(#PB_Event_CloseWindow, @CloseEvent(), id)
  CloseWindow(id)
EndProcedure


Procedure OpenWindowThread(nul)
  OpenWindow(2, 0, 0, 300, 200, "My Window", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  BindEvent(#PB_Event_CloseWindow, @CloseEvent(), 2)
  Repeat
    Until WaitWindowEvent(100)=#PB_Event_CloseWindow
  EndProcedure
  
  
ProcedureDLL OpenMyWindow()
  CreateThread(@OpenWindowThread(),#NUL)
EndProcedure

; test.dll code end _________________________________________________________________________________

;application.exe code start__________________________________________________________________________

If OpenLibrary(0, "Test.dll") = 0
    MessageRequester("Application", "Test.dll failed", #PB_MessageRequester_Info)
    End
  EndIf
  
  
  If OpenWindow(0, 0, 0, 400, 400, "Application", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) 
     ButtonGadget(1,10,30,150,20,"Test...")
    
    Repeat
      EventID=WaitWindowEvent(100)
      Select EventID
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 1
              MessageRequester("Application", "Before", #PB_MessageRequester_Info)
              CallFunction(0,"OpenMyWindow")
              MessageRequester("Application", "After", #PB_MessageRequester_Info)
          EndSelect
      EndSelect
    Until EventID=#PB_Event_CloseWindow
    
  EndIf

;application.exe code end__________________________________________________________________________


// Code Tags added (Kiffi)
PeDe
Enthusiast
Enthusiast
Posts: 119
Joined: Sun Nov 26, 2017 3:13 pm
Location: Vienna
Contact:

Re: Window from DLL issue

Post by PeDe »

Hello Kurti,

just a comment because I noticed it. The DLL procedure 'OpenWindowThread()' is not terminated when the window is closed. You use the #PB_Event_CloseWindow event with BindEvent(), and the CloseWindow() function closes the window without generating an event.

Peter
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Hello PeDe,

thanks for feedback.
I just looked at windows task manager and for me it looks like that the tread will be closed.

In task manager it look like this

When you only start Application.exe (the process list looks like)
Application.exe
- Application

When Application.exe is started and you click the "Test.." button (the process list looks like)
Application.exe
- Application
- My Window

When "My Window" has been cloesd (the process list looks like)
Application.exe
- Application

When Application.exe gets closed (no processes in task manager)

Do you experience something different or can you provide some code which should be improved ?

Cheers
Kurti

Hint: I was not able to post an image in this online reply tool so I have written above thread list.
PeDe
Enthusiast
Enthusiast
Posts: 119
Joined: Sun Nov 26, 2017 3:13 pm
Location: Vienna
Contact:

Re: Window from DLL issue

Post by PeDe »

Hello Kurti,

I used OutputDebugString_(), and with DebugView++ recorded the outputs.
When the DLL window is closed, the thread continues to run.

Code: Select all

1	13:39:17.244	1372	WindowFromDLL.exe	-> Main Before CallFunction()
2	13:39:17.244	1372	WindowFromDLL.exe	-> DLL OpenMyWindow()
3	13:39:17.244	1372	WindowFromDLL.exe	<- DLL OpenMyWindow()
4	13:39:17.244	1372	WindowFromDLL.exe	<- Main After CallFunction()
5	13:39:17.245	1372	WindowFromDLL.exe	-> DLL OpenWindow()
6	13:39:17.255	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
7	13:39:17.255	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
...
23	13:39:17.849	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
24	13:39:17.858	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
25	13:39:17.928	1372	WindowFromDLL.exe	-> DLL CloseEvent()
26	13:39:17.934	1372	WindowFromDLL.exe	<- DLL CloseEvent()
27	13:39:17.934	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
28	13:39:17.934	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
29	13:39:18.434	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
30	13:39:18.934	1372	WindowFromDLL.exe	- DLL WaitWindowEvent
...
One can send the event after the UnbindEvent() itself. Then the event loop and the thread will be terminated. Or you can send your own message or event.

Code: Select all

Procedure CloseEvent()
  OutputDebugString_("-> DLL CloseEvent()")
  id = EventWindow()
  UnbindEvent(#PB_Event_CloseWindow, @CloseEvent(), id)
  ;CloseWindow(id)
  PostEvent(#PB_Event_CloseWindow, id, 0)
  OutputDebugString_("<- DLL CloseEvent()")
EndProcedure


Procedure OpenWindowThread(nul)
  OutputDebugString_("-> DLL OpenWindow()")
  OpenWindow(2, 0, 0, 300, 200, "My Window", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  BindEvent(#PB_Event_CloseWindow, @CloseEvent(), 2)
  Repeat
  	OutputDebugString_("- DLL WaitWindowEvent")
    Until WaitWindowEvent(500)=#PB_Event_CloseWindow
  OutputDebugString_("<- DLL OpenWindow()")
 EndProcedure
  
  
ProcedureDLL OpenMyWindow()
  OutputDebugString_("-> DLL OpenMyWindow()")
  CreateThread(@OpenWindowThread(),#NUL)
  OutputDebugString_("<- DLL OpenMyWindow()")
EndProcedure

Code: Select all

1	13:42:16.540	4092	WindowFromDLL.exe	-> Main Before CallFunction()
2	13:42:16.541	4092	WindowFromDLL.exe	-> DLL OpenMyWindow()
3	13:42:16.541	4092	WindowFromDLL.exe	<- DLL OpenMyWindow()
4	13:42:16.541	4092	WindowFromDLL.exe	<- Main After CallFunction()
5	13:42:16.541	4092	WindowFromDLL.exe	-> DLL OpenWindow()
6	13:42:16.552	4092	WindowFromDLL.exe	- DLL WaitWindowEvent
7	13:42:16.552	4092	WindowFromDLL.exe	- DLL WaitWindowEvent
...
45	13:42:17.383	4092	WindowFromDLL.exe	- DLL WaitWindowEvent
46	13:42:17.403	4092	WindowFromDLL.exe	- DLL WaitWindowEvent
47	13:42:17.552	4092	WindowFromDLL.exe	-> DLL CloseEvent()
48	13:42:17.552	4092	WindowFromDLL.exe	<- DLL CloseEvent()
49	13:42:17.552	4092	WindowFromDLL.exe	- DLL WaitWindowEvent
50	13:42:17.552	4092	WindowFromDLL.exe	<- DLL OpenWindow()
Peter
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Hello Peter,

yes you are right about the tread issue with my last "final" sample code.
I mixed up the processes (Windows TaskManager) and the Threads (Process Explorer from sysinternals.com will show the treads)

The dll thread keeps alive and does not close.

Thanks for your detailed feedback.

I currently have amodified my solution which closes the thread, I will take a closer look at your example and update this discussion.

I will be traveling the next 2 days, so I post an update here soon.

Great and thanks a lot
Kurti.
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Hello all,

here is the final code which avoids the thread issue of the DLL.

If you want to verify I used Process Explorer.
If you select the process and you can right click on the process you can select properties,
Inside Properties dialog you can find the threads register tab.

Code below will create Application.exe and PlugIn.dll

Was quite a challenge to get it properly working.

Code for PlugIn.dll:

Code: Select all

; PlugIn.pb
 Enumeration #PB_Event_FirstCustomValue
    #EventThreadStop
  EndEnumeration
    
  Procedure ThreadHandler(*Value)
    OpenWindow(2, 0, 0, 300, 200, "AddIn Window", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
     
    Repeat
      Event = WaitWindowEvent()  
    Until Event()=#PB_Event_CloseWindow
    
    CloseWindow(2) 
    PostEvent(#EventThreadStop)
    
  EndProcedure


  ProcedureDLL LoadAddIn() 
    ThreadID = CreateThread(@ThreadHandler(), 40)
  
    Repeat
      Event = WaitWindowEvent()
    Until Event = #EventThreadStop
  
  EndProcedure
code for Application.pb

Code: Select all

If OpenLibrary(0, "AddIn.dll") = 0
  MessageRequester("Application", "AddIn.dll failed", #PB_MessageRequester_Info)
  End
EndIf
  
If OpenWindow(0, 0, 0, 400, 400, "Application", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) 
   ButtonGadget(1,10,30,150,20,"Load AddIn...")
    
   Repeat
     EventID = 0
     EventID=WaitWindowEvent(100)
     Select EventID
       Case #PB_Event_Gadget
         Select EventGadget()
           Case 1
             DisableGadget(1, #True)
             CallFunction(0,"LoadAddIn")
             DisableGadget(1, #False)
         EndSelect
       Case #PB_Event_CloseWindow
         CloseWindow(0) 
     EndSelect
   Until EventID=#PB_Event_CloseWindow
  
   CloseLibrary(0)
   
 EndIf
Hope it helps other people.

Best regards
Kurti

// Code Tags added (Kiffi)
User avatar
HeX0R
Addict
Addict
Posts: 980
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: Window from DLL issue

Post by HeX0R »

There is no thread needed!
Workflow is as simple as this:
- the event loop (only one!) runs in the host application
- DLL can create windows and Gadgets, but should use #PB_Any for dynamic ones
- All DLL Window/Gadget-handling has to go through Bindevents

I wanted to create a small example, but then I stumbled accross a bug in PB6.xx Linux.
I'm following this approach above since years
But never tested on that thing with an apple
Kurti2023
New User
New User
Posts: 8
Joined: Sun May 28, 2023 4:15 pm

Re: Window from DLL issue

Post by Kurti2023 »

Hello HeX0R,

thanks for the comment, you are right.

Here the changed code only for the AddIn.pb the Application.pb is untouched.

I post this code just for those people who would like to see the non threaded AddIn.

I'm still in my learning phase of PureBasic but anyway now we have a threaded and non threaded AddIn example code.

Not bad :), thanks for all the feedback,

Kurti

; Plugin.pb start___________________________________________________________________________________________

Code: Select all

Procedure CloseEvent()
  id = EventWindow()
  UnbindEvent(#PB_Event_CloseWindow, @CloseEvent(), id)
EndProcedure
  
 
ProcedureDLL LoadAddIn() 
    
    OpenWindow(#PB_Any, 0, 0, 300, 200, "AddIn Window", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
    BindEvent(#PB_Event_CloseWindow, @CloseEvent(), #PB_Any) 
    
    Repeat
      Event = WaitWindowEvent()  
    Until Event()=#PB_Event_CloseWindow
    
     CloseWindow(#PB_Any)
EndProcedure
; plugin.pb end_____________________________________________________________________________________________
User avatar
HeX0R
Addict
Addict
Posts: 980
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: Window from DLL issue

Post by HeX0R »

That's not correct, I said the event loop stays in the host application!
Post Reply