Page 1 of 1
DLL question
Posted: Sat Apr 13, 2013 1:32 pm
by Yewklid
I am learing how to write DLLs and have put togethet this very simple one.
Code: Select all
ProcedureDLL.s MyMessage()
MessageRequester(Returnstring(), "This is a PureBasic DLL !", #PB_MessageRequester_YesNo )
If Result = #PB_MessageRequester_Yes
a$ + "Yes"
Else
a$ + "No"
EndIf
ProcedureReturn a$
EndProcedure
ProcedureDLL MyWindow()
If OpenWindow(0, 0, 0, 400, 300, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EndIf
Repeat
Event = WindowEvent()
If Event
Else
Delay(1)
EndIf
Until Event = #PB_Event_CloseWindow
EndProcedure
If I call MyMessage and MyWindow from a PB programme everything is fine. If I call from another language, it only works if I call MyMessage first and then MyWindow afterwards. If I try to call MyWindow first, nothing happens.
I can only guess that MyMessage must initialise something that MyWindow needs. Does anyone have any idea what is happening here and how I fix it?
Thanks
Re: DLL question
Posted: Sat Apr 13, 2013 8:53 pm
by luis
Yewklid wrote:I am learing how to write DLLs and have put togethet this very simple one.
Are you sure this one is that one ?
Where is Returnstring()?
a$ must be global.
From which language ?
How do you import it ?
How do you call it ?
etc. etc. etc.
Calling the messagerequester should cause the initialization of the common controls, but I don't know if has any relevance here. Maybe it has ? Not sure.
But I never created PB windows inside a DLL (and even less did so calling then the DLL from another language) so I don't have any experience with that.
Re: DLL question
Posted: Sat Apr 13, 2013 10:12 pm
by Yewklid
Hi Luiz,
I should have taken out Returnstring because it is not relevant. It can be replaced by a fixed string like this:
Code: Select all
ProcedureDLL.s MyMessage()
MessageRequester("Hello", "This is a PureBasic DLL !", #PB_MessageRequester_YesNo )
If Result = #PB_MessageRequester_Yes
a$ + "Yes"
Else
a$ + "No"
EndIf
ProcedureReturn a$
EndProcedure
You are also right that MyMessage does not return the correct value because of the lack of Global variable (but I don't mind at the moment).
The main point though is that the MessageRequester window does pop up and my question is why the window in MyWindow only pops up if the other one has appeared first. Your answer about the Common Controls is the kind of issue I thought might be involved but I would love to know how to use this to solve the problem.
The other language is called Lhogho and the other simple examples I have tried in a DLL like doubling numbers and things like that have all worked fine.
I am using the proper method for loading and calling functions in a DLL in Lhogho and here is an example:
Code: Select all
make "Turtlelib libload "TurtleDLL.dll
if :Turtlelib=0
[print [TurtleLib not loaded]]
[print [TurtleLib loaded]]
to MyMessage end
external "MyMessage [s1 MyMessage] :Turtlelib
make "ans MyMessage
print :ans
The context here is that I am interested in writing a DLL to implement Turtle graphics which is something which is popular in languages for teaching youngsters to programme.
Re: DLL question
Posted: Sat Apr 13, 2013 10:28 pm
by luis
OK thanks (I admit the language info didn't help me since I don't know nothing about it

)
About the common controls, as I said I don't know if it's relevant since you are trying to create an empty window but you can try to call InitCommonControlsEx with at least the ICC_STANDARD_CLASSES bit set and see if it changes anything.
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
You could also try to create an empty window through API to see if that one works without any previous call or not.
You can steal from this snippet to waste less time ->
http://www.purebasic.fr/english/viewtop ... 76#p397876
You could also log some debug message to file to see where exactly is the point which fails.
Or use OutputDebugString()
http://technet.microsoft.com/en-us/sysi ... 96647.aspx
I don't have idea of what I'm saying here.
Re: DLL question
Posted: Sat Apr 13, 2013 11:02 pm
by Danilo
Works with PB itself.
EXE:
Code: Select all
If OpenLibrary(0,"theDll.dll")
;CallFunction(0,"MyMessage")
CallFunction(0,"MyWindow")
CloseLibrary(0)
EndIf
DLL:
Code: Select all
ProcedureDLL.s MyMessage()
MessageRequester("Hello", "This is a PureBasic DLL !", #PB_MessageRequester_YesNo )
If Result = #PB_MessageRequester_Yes
a$ + "Yes"
Else
a$ + "No"
EndIf
ProcedureReturn a$
EndProcedure
ProcedureDLL MyWindow()
If OpenWindow(0, 0, 0, 400, 300, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EndIf
Repeat
Event = WindowEvent()
If Event
Else
Delay(1)
EndIf
Until Event = #PB_Event_CloseWindow
CloseWindow(0)
EndProcedure
(Had to add CloseWindow(), otherwise the EXE process does not exit and stays in task manager)
Re: DLL question
Posted: Sat Apr 13, 2013 11:04 pm
by Yewklid
Your suggestion about the common controls is the best clue I have so far. I'll have a look at your links and try some experiments.
Many thanks
Re: DLL question
Posted: Sun Apr 14, 2013 6:14 pm
by Yewklid
Fantastic. Creating a window through the API works. Thanks.
Re: DLL question
Posted: Sun Apr 14, 2013 7:28 pm
by luis
But does it help you ? I thought you needed a PB window. If not, then fine

Re: DLL question
Posted: Mon Apr 15, 2013 8:48 am
by Yewklid
All I really need to do is be able to draw line segments to the window which has just been created. I'm guessing that can be done through the API as well although I will need to read up how to do that. That could be one way forward.
I haven't yet figured out your other suggestion. I know that it translates into a PB call of the form InitCommonControlsEx_() but I haven't figured out the " the ICC_STANDARD_CLASSES bit set'" part of it yet.
Re: DLL question
Posted: Mon Apr 15, 2013 9:34 am
by Yewklid
hmmm......I've just found one sneaky way round the problem. If I use your API code to create a window but don't actually show it then I can open a window using PB code in the normal way and use all the usual line drawing code provided by PB.
Re: DLL question
Posted: Mon Apr 15, 2013 3:47 pm
by luis
Yewklid wrote:
I haven't yet figured out your other suggestion. I know that it translates into a PB call of the form InitCommonControlsEx_() but I haven't figured out the " the ICC_STANDARD_CLASSES bit set'" part of it yet.
I believe you can do this way:
Code: Select all
Procedure.i InitCC()
Protected initcc.INITCOMMONCONTROLSEX
initcc\dwSize = SizeOf(INITCOMMONCONTROLSEX)
initcc\dwICC = #ICC_STANDARD_CLASSES ; (add others if needed using '|')
ProcedureReturn InitCommonControlsEx_(@initcc)
EndProcedure
Debug InitCC()
Try to call InitCC() before opening the PB window, if doesn't work try to add the most common flags, if still doesn't work probably this has nothing to do with your problem
If Fred read this I'm sure he could tell you what the prerequisites are to open a PB window not from a normal exe (maybe something called by PB during its initialization ?).
If it works you can try to move it inside the special AttachProcess() procedure. See DLL in the help for more info.
Re: DLL question
Posted: Mon Apr 15, 2013 10:33 pm
by Yewklid
Haven't managed to find a flag that works yet.
Re: DLL question
Posted: Mon Apr 15, 2013 11:47 pm
by luis
Yewklid wrote:If I use your API code to create a window but don't actually show it then I can open a window using PB code in the normal way and use all the usual line drawing code provided by PB.
That's weird, no idea why. But if it works... maybe you can create the window and destroy it right away ?
Re: DLL question
Posted: Tue Apr 16, 2013 8:32 am
by Yewklid
Excellent idea. I tried it and it works
Thanks for all your help in getting this sorted!