hi all dear powerbasic users,
I am quite new here using powerbasic and want to learn more about this language. I know yet thinbasic / freebasic languages a little and have a lot of good ideas to create new things (main part: graphics).
I would like to understand how to work with creating own dll's and try to build perhaps own little applications with powerbasic and add some days new functions to this one. but I don't know how I should going on. So I tried to test code from powerbasic archive (dll creating with "modal dialogue").
I found modal dialogue / input test. but the code is very old and perhaps somebody has updated this code into the current pb 9.1 version I am working with or can do this for me, would be very nice ;)
old code:
'
' Example DLL to display a modal dialog and return a value to the calling
' application.
'
' Requires PB/DLL v1.10 or later to compile.
'
$COMPILE DLL
$INCLUDE "WIN32API.INC"
DECLARE FUNCTION InputDlgProc(BYVAL hDlg AS INTEGER, _
BYVAL wMsg AS INTEGER, _
BYVAL wParam AS INTEGER, _
BYVAL lParam AS LONG) AS INTEGER
GLOBAL DlgAddr AS DWORD
GLOBAL hCurInstance AS WORD
GLOBAL gText AS ASCIIZ * 255
GLOBAL gCaption AS ASCIIZ * 255
GLOBAL gDefault AS ASCIIZ * 255
FUNCTION LIBMAIN (BYVAL hInstance AS LONG, _
BYVAL wDataSeg AS DWORD, _
BYVAL wHeapSize AS DWORD, _
lpszCmdLine AS ASCIIZ) EXPORT AS INTEGER ' ??? mistake here?
'Save the instance handle of the DLL
hCurInstance = hInstance
'Remember! We have to return a "one" to indicate successful
' initialization
LIBMAIN = 1 'success!
END FUNCTION
FUNCTION InputBox(TEXT AS ASCIIZ PTR, _
Caption AS ASCIIZ PTR, _
DEFAULT AS ASCIIZ PTR) EXPORT AS INTEGER
' Get the address of the dialog callback
DlgAddr = MakeProcInstance(CODEPTR(InputDlgProc), hCurInstance)
' If pointers are non-null, set default values for dialog
IF TEXT THEN
gText = @TEXT
ELSE
gText = "Enter Text"
END IF
IF Caption THEN
gCaption = @Caption
ELSE
gCaption = "INPUT BOX"
END IF
IF DEFAULT THEN
gDefault = @DEFAULT
ELSE
gDefault = ""
END IF
' Pop up the modal dialog and get return value
FUNCTION = DialogBox(hCurInstance, "INPUTBOX", 0, DlgAddr)
' If default buffer was passed, return the input text
IF DEFAULT THEN
@DEFAULT = gDefault
END IF
END FUNCTION
' **
' ** Generic routine to center any window given its handle.
' **
SUB CenterWindow(BYVAL hWnd AS WORD)
DIM WndRect AS RECT
DIM x AS INTEGER
DIM y AS INTEGER
GetWindowRect hWnd, WndRect
x = (GetSystemMetrics(%SM_CXSCREEN)-(WndRect.nRight-WndRect.nLeft))\2
y = (GetSystemMetrics(%SM_CYSCREEN)-(WndRect.nBottom-WndRect.nTop+GetSystemMetrics(%SM_CYCAPTION)))\2
SetWindowPos hWnd, %NULL, x, y, 0, 0, %SWP_NOSIZE OR %SWP_NOZORDER
END SUB
FUNCTION InputDlgProc(BYVAL hDlg AS INTEGER, _
BYVAL wMsg AS INTEGER, _
BYVAL wParam AS INTEGER, _
BYVAL lParam AS LONG) EXPORT AS INTEGER
' See INPUTBOX.RC script for details on the dialog itself
SELECT CASE wMsg
CASE %WM_INITDIALOG
'Center the window
CenterWindow hDlg
'Assign the initial values to the dialog
SetWindowText GetDlgItem(hDlg, 101), gText
SetWindowText GetDlgItem(hDlg, 102), gDefault
SetWindowText hDlg, gCaption
FUNCTION = 1
EXIT FUNCTION
CASE %WM_COMMAND
SELECT CASE wParam
CASE 103, %IDOK
'When the "OK" button is pressed, get the edit box value
' and end the dialog
GetWindowText GetDlgItem(hDlg, 102), gDefault, 255
EndDialog hDlg, 1
FUNCTION = 1
EXIT FUNCTION
'When the "CANCEL" button is pressed, or escape is pressed, or
' the dialog is closed, end the dialog
CASE 104, %IDCANCEL
EndDialog hDlg, 0
FUNCTION = 1
EXIT FUNCTION
END SELECT
END SELECT
END FUNCTION
Testexample:
'
' Example of calling a DLL which has a modal dialog resource
'
' Modal Dialog is a generic input box
'
$COMPILE EXE
DECLARE FUNCTION MessageBox LIB "USER" (BYVAL hWnd AS WORD, lpText AS ASCIIZ, lpCaption AS ASCIIZ, BYVAL wTYPE AS WORD) AS INTEGER
DECLARE FUNCTION InputBox LIB "INPUTBOX" (Question AS ASCIIZ,
Caption AS ASCIIZ,
DEFAULT AS ASCIIZ) AS INTEGER
FUNCTION WINMAIN (BYVAL hCurInstance AS INTEGER, _
BYVAL hPrevInstance AS INTEGER, _
lpCmdLine AS ASCIIZ, _
BYVAL nCmdShow AS INTEGER) AS INTEGER
DIM Answer AS ASCIIZ * 255
'Set default answer value
Answer = "Dave Navarro"
'Call the DLL with the modal dialog
IF InputBox("Enter Complete User Name", "User Name Dialog", Answer) THEN
'Display the result
MessageBox 0, "You entered: " + Answer, "Input Box DLL Test", 0
ELSE
MessageBox 0, "Cancel was pressed!", "Input Box DLL Test", 0
END IF
END FUNCTION
hope somebody can help, so it's my first step to get closer to powerbasic. thanks in advance. wish all a good evening from centre of germany.
don't know where to place the code and my question so I do it here. Hope to have also some fun here at this board while learning new things :)
best regards, frank
Hi Frank!
Welcome! I didn't try to run the code but doesn't it compile for you? If you copied code from an earlier version of PowerBASIC, there has been a recent change that pointer parameters have to be passed Byval.
Fred
Frank,
I fixed multiple errors in the dll. This at least compiles to a dll. You'll have to investigate for changes.
'
' Example DLL to display a modal dialog and return a value to the calling
' application.
'
' Requires PB/DLL v1.10 or later to compile.
'
$COMPILE DLL
$INCLUDE "WIN32API.INC"
DECLARE FUNCTION InputDlgProc(BYVAL hDlg AS INTEGER, _
BYVAL wMsg AS INTEGER, _
BYVAL wParam AS INTEGER, _
BYVAL lParam AS LONG) AS INTEGER
GLOBAL DlgAddr AS DWORD
GLOBAL hCurInstance AS WORD
GLOBAL gText AS ASCIIZ * 255
GLOBAL gCaption AS ASCIIZ * 255
GLOBAL gDefault AS ASCIIZ * 255
Function LibMain(ByVal hInstance As Long,ByVal fwdReason As Long,ByVal lpvReserved As Long) Export As Long
'FUNCTION DLLMAIN (BYVAL hInstance AS LONG, BYVAL wDataSeg AS DWORD, BYVAL wHeapSize AS DWORD, Byval lpszCmdLine AS ASCIIZ) EXPORT AS INTEGER ' ??? mistake here?
'Save the instance handle of the DLL
hCurInstance = hInstance
'Remember! We have to return a "one" to indicate successful
' initialization
LIBMAIN = 1 'success!
END FUNCTION
FUNCTION InputBox(Byval TEXT AS ASCIIZ PTR, Byval Caption AS ASCIIZ PTR, Byval pDEFAULT AS ASCIIZ PTR) EXPORT AS INTEGER
' Get the address of the dialog callback
DlgAddr = CODEPTR(InputDlgProc)
' If pointers are non-null, set default values for dialog
IF TEXT THEN
gText = @TEXT
ELSE
gText = "Enter Text"
END IF
IF Caption THEN
gCaption = @Caption
ELSE
gCaption = "INPUT BOX"
END IF
IF pDEFAULT THEN
gDefault = @pDEFAULT
ELSE
gDefault = ""
END IF
' Pop up the modal dialog and get return value
FUNCTION = DialogBox(hCurInstance, "INPUTBOX", 0, DlgAddr)
' If default buffer was passed, return the input text
IF pDEFAULT THEN
@pDEFAULT = gDefault
END IF
END FUNCTION
' **
' ** Generic routine to center any window given its handle.
' **
SUB CenterWindow(BYVAL hWnd AS WORD)
DIM WndRect AS RECT
DIM x AS INTEGER
DIM y AS INTEGER
GetWindowRect hWnd, WndRect
x = (GetSystemMetrics(%SM_CXSCREEN)-(WndRect.nRight-WndRect.nLeft))\2
y = (GetSystemMetrics(%SM_CYSCREEN)-(WndRect.nBottom-WndRect.nTop+GetSystemMetrics(%SM_CYCAPTION)))\2
SetWindowPos hWnd, %NULL, x, y, 0, 0, %SWP_NOSIZE OR %SWP_NOZORDER
END SUB
FUNCTION InputDlgProc(BYVAL hDlg AS INTEGER, _
BYVAL wMsg AS INTEGER, _
BYVAL wParam AS INTEGER, _
BYVAL lParam AS LONG) EXPORT AS INTEGER
' See INPUTBOX.RC script for details on the dialog itself
SELECT CASE wMsg
CASE %WM_INITDIALOG
'Center the window
CenterWindow hDlg
'Assign the initial values to the dialog
SetWindowText GetDlgItem(hDlg, 101), gText
SetWindowText GetDlgItem(hDlg, 102), gDefault
SetWindowText hDlg, gCaption
FUNCTION = 1
EXIT FUNCTION
CASE %WM_COMMAND
SELECT CASE wParam
CASE 103, %IDOK
'When the "OK" button is pressed, get the edit box value
' and end the dialog
GetWindowText GetDlgItem(hDlg, 102), gDefault, 255
EndDialog hDlg, 1
FUNCTION = 1
EXIT FUNCTION
'When the "CANCEL" button is pressed, or escape is pressed, or
' the dialog is closed, end the dialog
CASE 104, %IDCANCEL
EndDialog hDlg, 0
FUNCTION = 1
EXIT FUNCTION
END SELECT
END SELECT
END FUNCTION
Added later:
I changed the Dll entry point function;
I added byval to pointer parameters in several instances;
I eliminated the MakeProcInstance() call. According to 1999 documentation, that was was obsolete (so it was obsolete in 1999 already).
That code is prehistoric. It is for a 16-bit compiler. Besides, it is incomplete: it lacks a resource file for the dialog box template. Also, the declares are incorrect.
Yes, the DialogBox() Api call requires in its 2nd parameter a pointer to a Dialog Box template in a rc file. You've really, really, dug up some ancient code Frank. If you are just trying to learn PowerBASIC I'd recommend you find more recent code.
PS - added later. I've almost got the code to run. If you can come up with that rc file I'll see what I can do.
hi frederick, josé,
yes, very old code, but that's not my mistake ;) would be better to update the old file from powerbasic.com website ( http://www.powerbasic.com/support/downloads/demos.htm ). I have searched for an example with dll and have got at first this InputDll example for modal dialogue. So I am starting with a lot of trouble causing, but it's funny.
rc file I have found I try to add below.
my results coming up to this end and the Inputbox$ line doesn't like me any more.
'
' Example of calling a DLL which has a modal dialog resource
'
' Frankos '-- Modal Dialog is a generic input box
'
$COMPILE EXE
#DIM ALL
DECLARE FUNCTION MessageBox LIB "USER" (BYVAL hWnd AS WORD, lpText AS ASCIIZ, lpCaption AS ASCIIZ, BYVAL wTYPE AS WORD) AS INTEGER
DECLARE FUNCTION InputBox LIB "Inputbox"(BYVAL TEXT AS ASCIIZ PTR, BYVAL Caption AS ASCIIZ PTR, BYVAL pDEFAULT AS ASCIIZ PTR, BYVAL answer AS ASCIIZ PTR) AS INTEGER
FUNCTION WINMAIN(BYVAL hInstance AS DWORD,BYVAL fwdReason AS LONG,BYVAL lpvReserved AS LONG, BYVAL hCurInstance AS DWORD) AS LONG
DIM answer AS ASCIIZ PTR* 255
'Set default answer value
MSGBOX "franko d'artagnon", answer
'Call the DLL with the modal dialog
'if answer = InputBOX$ ("Enter Complete User Name",, "User Name Dialog") then
'Display the result
MSGBOX "You entered: ", answer, "Input Box DLL Test"
'ELSE
MSGBOX "Cancel was pressed!",, "Input Box DLL Test"
'END IF
FUNCTION = 1
END FUNCTION
thanks a lot for trying / helping to fix this strange code from "lord of the rings" times :)
I have tried it over one hour. frederick you are right: better to use new code examples, right now!
if anybody has a running and current code about this theme or a link with dll handling would be also great.
best regards, Frank
Hi Frank!
That example is almost unimaginable on several different levels. First off, its using the Windows Api to create a Dialog Box! For almost as long as I can remember PowerBASIC has had something called DDT that is its own Api for creating dialog boxes.
Second, PowerBASIC has its own InputBox function as part of the compiler! Its not necessary to create one - let alone in a DLL!
Give me a bit and I'll get it working though if the rc file is OK. I had to change piles of lines of code.
Fred
I have translated the code. Download the attached file.
As it was 16-bit code, it was using integers instead of longs and WORD instead of DWORD for the instance handle... and several other things...
Things have changed a bit since PB/DLL 1 :)
'
' Example DLL to display a modal dialog and return a value to the calling
' application.
#COMPILE DLL
#INCLUDE "WIN32API.INC"
#RESOURCE "MyInputBox.pbr"
GLOBAL hCurInstance AS DWORD
GLOBAL gText AS ASCIIZ * 255
GLOBAL gCaption AS ASCIIZ * 255
GLOBAL gDefault AS ASCIIZ * 255
'-------------------------------------------------------------------------------
' Main DLL entry point called by Windows...
'
FUNCTION LIBMAIN (BYVAL hInstance AS LONG, _
BYVAL fwdReason AS LONG, _
BYVAL lpvReserved AS LONG) AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
'Indicates that the DLL is being loaded by another process (a DLL
'or EXE is loading the DLL). DLLs can use this opportunity to
'initialize any instance or global data, such as arrays.
hCurInstance = hInstance
FUNCTION = 1 'success!
'FUNCTION = 0 'failure! This will prevent the EXE from running.
CASE %DLL_PROCESS_DETACH
'Indicates that the DLL is being unloaded or detached from the
'calling application. DLLs can take this opportunity to clean
'up all resources for all threads attached and known to the DLL.
FUNCTION = 1 'success!
'FUNCTION = 0 'failure!
CASE %DLL_THREAD_ATTACH
'Indicates that the DLL is being loaded by a new thread in the
'calling application. DLLs can use this opportunity to
'initialize any thread local storage (TLS).
FUNCTION = 1 'success!
'FUNCTION = 0 'failure!
CASE %DLL_THREAD_DETACH
'Indicates that the thread is exiting cleanly. If the DLL has
'allocated any thread local storage, it should be released.
FUNCTION = 1 'success!
'FUNCTION = 0 'failure!
END SELECT
END FUNCTION
FUNCTION MyInputBox ALIAS "MyInputBox" ( _
BYVAL strText AS STRING, _
BYVAL strCaption AS STRING, _
BYREF szDefault AS ASCIIZ) EXPORT AS LONG
' If pointers are non-null, set default values for dialog
IF strText <> "" THEN
gText = strText
ELSE
gText = "Enter Text"
END IF
IF strCaption <> "" THEN
gCaption = strCaption
ELSE
gCaption = "INPUT BOX"
END IF
IF VARPTR(szDefault) THEN
gDefault = szDefault
ELSE
gDefault = ""
END IF
' Pop up the modal dialog and get return value
FUNCTION = DialogBoxParam(hCurInstance, "INPUTBOX", 0, CODEPTR(InputDlgProc), 0)
' If default buffer was passed, return the input text
IF VARPTR(szDefault) THEN
szDefault = gDefault
END IF
END FUNCTION
' **
' ** Generic routine to center any window given its handle.
' **
SUB CenterWindow(BYVAL hWnd AS WORD)
DIM WndRect AS RECT
DIM x AS INTEGER
DIM y AS INTEGER
GetWindowRect hWnd, WndRect
x = (GetSystemMetrics(%SM_CXSCREEN)-(WndRect.nRight-WndRect.nLeft))\2
y = (GetSystemMetrics(%SM_CYSCREEN)-(WndRect.nBottom-WndRect.nTop+GetSystemMetrics(%SM_CYCAPTION)))\2
SetWindowPos hWnd, %NULL, x, y, 0, 0, %SWP_NOSIZE OR %SWP_NOZORDER
END SUB
FUNCTION InputDlgProc(BYVAL hDlg AS INTEGER, _
BYVAL wMsg AS INTEGER, _
BYVAL wParam AS INTEGER, _
BYVAL lParam AS LONG) EXPORT AS LONG
' See INPUTBOX.RC script for details on the dialog itself
SELECT CASE wMsg
CASE %WM_INITDIALOG
'Center the window
CenterWindow hDlg
'Assign the initial values to the dialog
SetWindowText GetDlgItem(hDlg, 101), gText
SetWindowText GetDlgItem(hDlg, 102), gDefault
SetWindowText hDlg, gCaption
FUNCTION = 1
EXIT FUNCTION
CASE %WM_COMMAND
SELECT CASE wParam
CASE 103, %IDOK
'When the "OK" button is pressed, get the edit box value
' and end the dialog
GetWindowText GetDlgItem(hDlg, 102), gDefault, 255
EndDialog hDlg, 1
FUNCTION = 1
EXIT FUNCTION
'When the "CANCEL" button is pressed, or escape is pressed, or
' the dialog is closed, end the dialog
CASE 104, %IDCANCEL
EndDialog hDlg, 0
FUNCTION = 1
EXIT FUNCTION
END SELECT
END SELECT
END FUNCTION
Way to go Jose! I just got home and was going to work on it again with the rc file in hand and thought I'd better check to see if you finished it.
Fred
thank you both young boys :D
works fine for me too! next time I will try to find more new coding examples. this kind of old and ancient pb things more confuse me than I can learn from with ;) have a nice day, bye, thanks, frank
ps: how to build an resource file *.pbr ? that's new for me!
Quote
ps: how to build an resource file *.pbr ? that's new for me!
Load the .rc file in the PB editor and click Compile.
ok. I am here also to ask question. And because I am curious and would like to learn more about DLL and creating new functions here my problem: (I have sometimes fun to blame myself ;) ) !
I have trouble simple to calculate "add" ??? the multiply functions does run as well as I wish.
test_lionbasic.bas code
#COMPILER PBWIN 9
#COMPILE EXE
'--------------------------------------------------------------------
DECLARE FUNCTION MyFunction1 LIB "Lionbasic_DLL.DLL" _
ALIAS "MyFunction1" (BYVAL Param1 AS LONG) AS LONG
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION MySub1 LIB "Lionbasic_DLL.DLL" _
ALIAS "MySub1" (BYVAL Param2 AS LONG) AS LONG
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION LionBasic_Test LIB "Lionbasic_DLL.DLL" _
ALIAS "LionBasic_Test" (BYVAL Param3 AS LONG) AS LONG
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION Colorix LIB "Lionbasic_DLL.DLL" _
ALIAS "LionBasic_Test" (BYVAL k AS DOUBLE) AS DOUBLE
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION AddOne LIB "Lionbasic_DLL.DLL" _
ALIAS "LionBasic_Test" (BYVAL x AS DOUBLE) AS DOUBLE
'--------------------------------------------------------------------
FUNCTION PBMAIN () AS LONG
LOCAL lRes AS LONG
LOCAL myResult AS LONG
LOCAL c AS LONG
LOCAL z AS LONG
LOCAL v AS LONG
LOCAL r AS LONG
lRes = MyFunction1(lRes)
c = MySub1(c)
z = LionBasic_test(z)
v = Colorix(v)
r = Addone(r)
MSGBOX "SuperHeroes.exe feedback result from first LIONBASIC.DLL:" + STR$(lRes), %MB_OKCANCEL, " ~Lionbasic TestScript " + DATE$
MSGBOX "Not only SuperHeroes can calculate :) " + STR$(c), %MB_OK, " ~Lionbasic TestScript " + TIME$
MSGBOX "Does Spiderman goes daily shopping with his girlfriend Anne? " + STR$(z), %MB_ICONQUESTION, " ~Lionbasic TestScript " + TIME$
MSGBOX "ColorWoman shows you no string: " + STR$(v), %MB_ICONQUESTION, " ~Lionbasic ColorX TestScript " + STR$(v)
MSGBOX "calculate 2009 + 1: " + STR$(r), %MB_ICONQUESTION, " ~Lionbasic Addone Calc "
END FUNCTION
would be nice to get any answer, how to make "add" in the right way. it's important for me to grasp the general handling of functions and strings! I have got horrible results.
nice friday, servus, frank
You have a couple of declarations with a wrong alias. They must be:
DECLARE FUNCTION Colorix LIB "Lionbasic_DLL.DLL" _
ALIAS "Colorix" (BYVAL k AS DOUBLE) AS DOUBLE
DECLARE FUNCTION AddOne LIB "Lionbasic_DLL.DLL" _
ALIAS "AddOne" (BYVAL x AS DOUBLE) AS DOUBLE
Otherwise, you are calling LionBasic_Test (the function with the name of the alias is what is being called, not Colorix or AddOne).
! :)
I see, I see. and one other thing I have found. I have a big cold, so my eyes aren't bright and clear.
here I found another little thing in my lionbasic.dll code side.
code part 1)
FUNCTION AddOne ALIAS "AddOne" (BYVAL x AS DOUBLE, BYVAL y AS DOUBLE) EXPORT AS DOUBLE
x = 2009
y = x + 1
MSGBOX "add one please: " + STR$(y) ' correct result: 2010 ! :)
END FUNCTION
this one works good finally.
but...
on "testlionbasic.bas" side I have one question again about the result of typing in second "addone":
code part 2):
'--------------------------------------------------------------------
DECLARE FUNCTION AddOne LIB "Lionbasic_DLL.DLL" _
ALIAS "AddOne" (BYVAL x AS DOUBLE, BYVAL y AS DOUBLE) AS DOUBLE
'--------------------------------------------------------------------
that's also correct by definition except the second "add" result I am producing with following lines:
code part 3)
FUNCTION PBMAIN () AS LONG
...
LOCAL r AS LONG
r = Addone(r,1)
MSGBOX "calculate silly things: " + STR$(r,1), %MB_ICONQUESTION, " ~Lionbasic Addone Calc "
the result of second "add one" is: 1E+6 ! very funny. why ?
I am beating this little beast :D
best regards, thank you josé in advance, frank
ps: whole project as zip file above
You're corrupting the memory because your declares in the test program doesn't match the ones in the DLL.
DECLARE FUNCTION MySub1 LIB "Lionbasic_DLL.DLL" _
ALIAS "MySub1" (BYVAL Param2 AS LONG) AS LONG
must be:
DECLARE SUB MySub1 LIB "Lionbasic_DLL.DLL" ALIAS "MySub1" (BYVAL Param2 AS LONG, BYVAL a AS LONG, BYVAL b AS LONG, BYVAL c AS LONG)
and
DECLARE FUNCTION LionBasic_Test LIB "Lionbasic_DLL.DLL" _
ALIAS "LionBasic_Test" (BYVAL Param3 AS LONG) AS LONG
must be:
DECLARE SUB LionBasic_Test LIB "Lionbasic_DLL.DLL" ALIAS "LionBasic_Test" (BYVAL Param3 AS LONG, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL z AS LONG)
right you are :)
simple mistake by wrong copying given some strange results, I am not really healthy, sorry. but now it's nearly all ok here for my first strike. thank you. your support helps even I have just a little little knowledge about things I can realize with powerbasic! I will use it at a later moment for thinbasic too (!) ;)
I have done in my last example little string output, so this chapter is ready for myself to take off for learning.
#COMPILER PBWIN 9
#COMPILE EXE
'--------------------------------------------------------------------
DECLARE FUNCTION MyFunction1 LIB "Lionbasic_DLL.DLL" _
ALIAS "MyFunction1" (BYVAL Param1 AS LONG) AS LONG
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION MySub1 LIB "Lionbasic_DLL.DLL" _
ALIAS "MySub1" (BYVAL Param2 AS LONG, BYVAL a AS LONG, BYVAL b AS LONG, BYVAL c AS LONG) AS DOUBLE
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION LionBasic_Test LIB "Lionbasic_DLL.DLL" _
ALIAS "LionBasic_Test" (BYVAL Param3 AS LONG, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL z AS LONG) AS DOUBLE
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION Colorix LIB "Lionbasic_DLL.DLL" _
ALIAS "Colorix" (BYVAL k AS DOUBLE) AS DOUBLE
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION AddOne LIB "Lionbasic_DLL.DLL" _
ALIAS "AddOne" (BYVAL x AS DOUBLE, BYVAL y AS DOUBLE) AS DOUBLE
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION StringTest LIB "Lionbasic_DLL.DLL" _
ALIAS "StringTest" (BYVAL a AS STRING, BYVAL t AS DOUBLE) AS STRING
'--------------------------------------------------------------------
'--------------------------------------------------------------------
DECLARE FUNCTION windowME LIB "Lionbasic_DLL.DLL" _
ALIAS "windowME" (BYVAL hdlg AS DWORD) AS LONG
'--------------------------------------------------------------------
FUNCTION PBMAIN () AS LONG
LOCAL lRes AS LONG
LOCAL myResult AS LONG
LOCAL d AS LONG
LOCAL z AS LONG
LOCAL v AS LONG
LOCAL r AS LONG
LOCAL q AS LONG
LOCAL str AS STRING
LOCAL windows AS LONG
lRes = MyFunction1(lRes)
d = MySub1(d,1,2,3)
q = LionBasic_test(q,1,2,3)
v = Colorix(v)
r = Addone(r,1)
str = stringTest(str,1)
windows = windowME(windows)
MSGBOX "SuperHeroes.exe feedback result from first LIONBASIC.DLL:" + STR$(lRes), %MB_OKCANCEL, " ~Lionbasic TestScript " + DATE$
MSGBOX "Not only SuperHeroes can calculate :) " + STR$(d), %MB_OK, " ~Lionbasic TestScript " + TIME$
MSGBOX "Does Spiderman goes daily shopping with his girlfriend Anne? " + STR$(q), %MB_ICONQUESTION, " ~Lionbasic TestScript " + TIME$
MSGBOX "ColorWoman shows you no string: " + STR$(v), %MB_ICONQUESTION, " ~Lionbasic ColorX TestScript " + STR$(v)
'MSGBOX "calculate silly things: " + STR$(r), %MB_ICONQUESTION, " ~Lionbasic Addone Calc "
MSGBOX "Tell me more secrets!: " & str, %MB_ICONQUESTION, " ~Lionbasic String Test "
MSGBOX "Window_TestClipping: " + STR$(windows), %MB_ICONQUESTION, " ~Lionbasic WinApi Test: " + DATE$
END FUNCTION
only one problem will remain with this "addone" line:
MSGBOX "calculate silly things: " + STR$(r), %MB_ICONQUESTION, " ~Lionbasic Addone Calc "
I will check it next day. more to come. thanks for help.
last edit: - have made a little experiment and have included a "dialogue box" with "three buttons" (not yet any call back functions possible), with a usual function! :)
don't know if this one can be valid too for a callback function for a separately function, I will try it tomorrow. must *laugh*. I am surprised. so this work increases for making a lot of fun!
good evening, servus and cheerio, frank
good evening.
I have a problem to make a callback function in my LionbasicDLL.bas. I have this general question why it's not possible to make a callback function in this way ? the compiler gives several error messages, for example block statement are not allowed. I have tried to code this way, it's not perfect. I cannot make any callback function into this two function I have planned:
code part of *dll.bas:
'---------------------------------------
FUNCTION windowME ALIAS "windowME" (BYVAL hdlg AS DWORD) EXPORT AS LONG
DIALOG NEW PIXELS , 0, " LionBasic Graphics_ButtonTest ",420,420,240,240, %WS_OVERLAPPEDWINDOW TO hDlg
CONTROL ADD BUTTON , hDlg , 100," Don't push me ", 60,30,100,38
CONTROL ADD BUTTON , hDlg , 120," Batman's not here! ", 60,80,100,38
CONTROL ADD BUTTON , hDlg , 140," thinbasic+powerbasic! ", 50,128,120,48
CONTROL ADD BUTTON , hDlg , 180," Graphics Power! ", 50,180,120,48
CONTROL ADD BUTTON, hDlg , 2, "Cancel", 5, 12, 50, 28
CONTROL SET COLOR hDlg, id&, RGB(100,250,100),RGB(200,0,100)
CONTROL ADD LABEL, hDlg, id&, "only for test purpose", 60, 4, 120, 12, , , _
DIALOG SHOW MODAL hDlg '-- CALL DlgProc TO Result& doesn't work here !
FUNCTION = hDlg
END FUNCTION
'---------------------------------------
FUNCTION callbackme ALIAS "callbackme" (BYVAL dlgProc AS DWORD) EXPORT AS LONG
DIM s AS LONG
DIM cbmsga AS LONG '-- CBMSG doesn't work at all
DIM CBHNDLs AS LONG '-- CBHNDL doesn't work at all
IF s ISTRUE THEN
MSGBOX "hello",%MB_OK,"save our souls"
IF CBMSGa = %WM_COMMAND THEN DIALOG END CBHNDLs
END IF
FUNCTION = CBMSGa
'FUNCTION = CBHNDLs
END FUNCTION
'------------------------------------------
I know it's perhaps a unusual way, but I have tried it.
this cannot work, but why ?
DIALOG SHOW MODAL hDlg '-- CALL DlgProc TO Result& doesn't work here !
DIM cbmsga AS LONG '-- CBMSG doesn't work at all
DIM CBHNDLs AS LONG '-- CBHNDL doesn't work at all
perhaps somebody can give a serious hint or advice. thanks in advance. I will solve this problem ;)
I want to close the dialogue by clicking one of the four buttons.
=> I am looking for a window procedure for the custom dialogue control.
best regards, frank
ps: test example attached
Quote
this cannot work, but why ?
1. CALL DlgProc must point to an existing callback function and you seem to think that it is a parameter to your (non callback) callbackme function.
2. The callback function must not be exported, since only Windows can call it.
3. All the code in your callbackme function is wrong. Use something like this:
CALLBACK FUNCTION DlgProc() AS LONG
SELECT CASE CB.MSG
CASE %WM_COMMAND
' -------------------------------------------------------------------
' Messages from controls and menu items are handled here.
' -------------------------------------------------------------------
SELECT CASE CB.CTL
CASE %IDCANCEL
IF CB.CTLMSG = %BN_CLICKED THEN DIALOG END CB.HNDL, 0
' CASE ...
' CASE ...
END SELECT
END SELECT
END FUNCTION
4. Decide if you're going to use DDT or the SDK style programming. Using both at this stage, depending on the code you find, can only confuse you because they work differently.
hi rosé, do you heard my laughing ? ;D
Quote3. All the code in your callbackme function is wrong. Use something like this:
that's my personal reason for make it better and learn more about these things! I have a lot of humour ;)
1) thank you very mucho, because it's the first time I see such things!
I have fixed prompted my little dialogue box. It's just for testing and coming up one more step forward!
now it's possible to close the button (left top side little close button: "close").
2)
Quote4. Decide if you're going to use DDT or the SDK style programming. Using both at this stage, depending on the code you find, can only confuse you because they work differently.
!!! good to know !!!
DDT and SDK style or petzolds api they are working in a quite different way, I am thinking too. the usual dialogue boxes aren't very exciting for my purpose and ideas. but I have started with ddt example, doesn't matter. I like more the petzold look-a-like style. I will nerve you again if I am ready with the sdk or petzold api style with forthcoming DLL programming. so long.
best regards into the night to all here at the forum, frank
hello.
I am looking for a very short way to create a own styled "sdk window" by using DLL power. I don't know how to do this complicated way, but I will search for a solution or somebody can help.
I have only managed this "graphic window" easiest way:
1) "xWinDLL".bas example:
#COMPILER PBWIN 9
#COMPILE DLL
%USEMACROS = 1
#INCLUDE "Win32API.inc"
GLOBAL ghInstance AS DWORD
'-------------------------------------------------------------------------------
' Main DLL entry point called by Windows...
'
FUNCTION LIBMAIN (BYVAL hInstance AS LONG, _
BYVAL fwdReason AS LONG, _
BYVAL lpvReserved AS LONG) AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
ghInstance = hInstance
FUNCTION = 1 'success!
CASE %DLL_PROCESS_DETACH
FUNCTION = 1 'success!
'FUNCTION = 0 'failure!
CASE %DLL_THREAD_ATTACH
FUNCTION = 1 'success!
CASE %DLL_THREAD_DETACH
FUNCTION = 1 'success!
END SELECT
END FUNCTION
FUNCTION Screen1 ALIAS "Screen1" (BYVAL X AS INTEGER, BYVAL Y AS INTEGER) EXPORT AS LONG
' Create and show a Graphic window on screen
LOCAL hWin AS DWORD
LOCAL k AS LONG
LOCAL j AS LONG
GRAPHIC WINDOW "BoxY", 300, 300, 220, 220 TO hWin
GRAPHIC ATTACH hWin, 0
FOR k& = 0 TO 255
GRAPHIC LINE (0, k&) - (255, k&), RGB(255, 10, k&+50)
NEXT
FOR j& = 0 TO 255
GRAPHIC LINE (j&, 0) - (j&, 255), RGB(j&, 100, 250)
NEXT
GRAPHIC WIDTH 1
GRAPHIC STYLE 4
GRAPHIC BOX (40, 40) - (120, 120), 20, %BLUE, 6
SLEEP 5000
FUNCTION = hWin
END FUNCTION
'
and here the
2) "test_xWinDLL.bas":
#COMPILER PBWIN 9
#COMPILE EXE
DECLARE FUNCTION Screen1 LIB "xWinDLL.dll" _
ALIAS "Screen1" (BYVAL X AS INTEGER, BYVAL Y AS INTEGER) AS LONG
FUNCTION PBMAIN () AS LONG
LOCAL lRes AS LONG
LOCAL a AS LONG
LOCAL b AS LONG
LOCAL z AS LONG
LOCAL t AS LONG
b = 100000
z = Screen1(z,t)
MSGBOX "yes we have won this gold price: " + STR$(b), %MB_ICONINFORMATION, "hello Maria! she can calculate!"
END FUNCTION
works perfect. you will see a little graphic window with blue and red color effect.
I am sure this little code is useful and shows how powerful this kind of dll creation can be.
now it would be great to see or showing by an existing example how to manage a complicated sdk window dll. I am curious to see such thing ! I am doing more experiments and will get this interesting stuff !
best regards, frank
The main window (dialog is not good terminology when speaking of SDK, same as script is not good terminology when speaking of a program written with a compiler), should reside in the application. Now, if you want to put the popup windows (or dialogs, if you prefer it), in a DLL, there is nothing difficult or mysterious: just do it!
Here is my previous example that created a popup window when you clicked the "Ok" button with the code for the popup placed in a DLL. Just load it in the editor and compile it to create the DLL (save the source file as PopupDlg,bas):
#COMPILE DLL
#INCLUDE "windows.inc"
' ========================================================================================
' Popup dialog - Calling example: ShowPopupDialog hWnd
' ========================================================================================
FUNCTION ShowPopupDialog ALIAS "ShowPopupDialog" (BYVAL hParent AS DWORD) EXPORT AS LONG
LOCAL hWndPopup AS LONG
LOCAL hCtl AS LONG
LOCAL hFont AS LONG
LOCAL rc AS RECT
LOCAL wcex AS WNDCLASSEX
LOCAL szClassName AS ASCIIZ * 80
LOCAL szCaption AS ASCIIZ * 255
hFont = GetStockObject(%ANSI_VAR_FONT)
szClassName = "MyPopupClassName"
wcex.cbSize = SIZEOF(wcex)
wcex.style = %CS_HREDRAW OR %CS_VREDRAW
wcex.lpfnWndProc = CODEPTR(PopupDlgProc)
wcex.cbClsExtra = 0
wcex.cbWndExtra = 0
wcex.hInstance = GetModuleHandle("")
wcex.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW)
wcex.hbrBackground = %COLOR_3DFACE + 1
wcex.lpszMenuName = %NULL
wcex.lpszClassName = VARPTR(szClassName)
wcex.hIcon = 0
wcex.hIconSm = 0
RegisterClassEx wcex
GetWindowRect hParent, rc ' For centering child in parent
rc.nRight = rc.nRight - rc.nLeft ' Parent's width
rc.nBottom = rc.nBottom - rc.nTop ' Parent's height
szCaption = "Popup dialog"
hWndPopup = CreateWindowEx(%WS_EX_DLGMODALFRAME OR %WS_EX_CONTROLPARENT, _
szClassName, szCaption, %WS_CAPTION OR %WS_POPUPWINDOW OR %WS_VISIBLE, _
rc.nLeft + (rc.nRight - 290) / 2, _
rc.nTop + (rc.nBottom - 180) / 2, _
290, 180, hParent, 0, GetModuleHandle(""), BYVAL %NULL)
hCtl = CreateWindowEx(0, "BUTTON", "&Close", %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_FLAT, _
200, 118, 75, 23, hWndPopup, %IDCANCEL, GetModuleHandle(""), BYVAL %NULL)
IF hFont THEN SendMessage hCtl, %WM_SETFONT, hFont, 0
ShowWindow hWndPopup, %SW_SHOW
UpdateWindow hWndPopup
' Message handler loop
LOCAL uMsg AS tagMsg
WHILE GetMessage(uMsg, %NULL, 0, 0)
IF ISFALSE IsDialogMessage(hWndPopup, uMsg) THEN
TranslateMessage uMsg
DispatchMessage uMsg
END IF
WEND
FUNCTION = uMsg.wParam
END FUNCTION
' ========================================================================================
' ========================================================================================
' Popup dialog procedure
' ========================================================================================
FUNCTION PopupDlgProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
SELECT CASE wMsg
CASE %WM_CREATE
EnableWindow GetWindow(hWnd, %GW_OWNER), %FALSE ' To make the popup dialog modal
CASE %WM_COMMAND
SELECT CASE LO(WORD, wParam)
CASE %IDCANCEL
IF HI(WORD, wParam) = %BN_CLICKED THEN
SendMessage hWnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
END SELECT
CASE %WM_CLOSE
EnableWindow GetWindow(hWnd, %GW_OWNER), %TRUE ' Maintains parent's zorder
CASE %WM_DESTROY
PostQuitMessage 0 ' This function closes the main window
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
And this is the application that creates the main window and creates the popup:
#COMPILE EXE
#DIM ALL
#INCLUDE "windows.inc"
DECLARE FUNCTION ShowPopupDialog LIB "PopupDlg.DLL" ALIAS "ShowPopupDialog" (BYVAL hParent AS DWORD) AS LONG
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG
LOCAL hWndMain AS DWORD
LOCAL hCtl AS DWORD
LOCAL hFont AS DWORD
LOCAL wcex AS WNDCLASSEX
LOCAL szClassName AS ASCIIZ * 80
LOCAL rc AS RECT
LOCAL szCaption AS ASCIIZ * 255
LOCAL nLeft AS LONG
LOCAL nTop AS LONG
LOCAL nWidth AS LONG
LOCAL nHeight AS LONG
hFont = GetStockObject(%ANSI_VAR_FONT)
' Register the window class
szClassName = "MyClassName"
wcex.cbSize = SIZEOF(wcex)
wcex.style = %CS_HREDRAW OR %CS_VREDRAW
wcex.lpfnWndProc = CODEPTR(WndProc)
wcex.cbClsExtra = 0
wcex.cbWndExtra = 0
wcex.hInstance = hInstance
wcex.hCursor = LoadCursor (%NULL, BYVAL %IDC_ARROW)
wcex.hbrBackground = %COLOR_3DFACE + 1
wcex.lpszMenuName = %NULL
wcex.lpszClassName = VARPTR(szClassName)
wcex.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Sample, if resource icon: LoadIcon(hInst, "APPICON")
wcex.hIconSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Remember to set small icon too..
RegisterClassEx wcex
' Window caption
szCaption = "SDK Main Window"
' Retrieve the size of the working area
SystemParametersInfo %SPI_GETWORKAREA, 0, BYVAL VARPTR(rc), 0
' Calculate the position and size of the window
nWidth = (((rc.nRight - rc.nLeft)) + 2) * 0.75 ' 75% of the client screen width
nHeight = (((rc.nBottom - rc.nTop)) + 2) * 0.70 ' 70% of the client screen height
nLeft = ((rc.nRight - rc.nLeft) \ 2) - nWidth \ 2
nTop = ((rc.nBottom - rc.nTop) \ 2) - (nHeight \ 2)
' Create a window using the registered class
hWndMain = CreateWindowEx(%WS_EX_CONTROLPARENT, _ ' extended style
szClassName, _ ' window class name
szCaption, _ ' window caption
%WS_OVERLAPPEDWINDOW OR _
%WS_CLIPCHILDREN, _ ' window styles
nLeft, _ ' initial x position
nTop, _ ' initial y position
nWidth, _ ' initial x size
nHeight, _ ' initial y size
%NULL, _ ' parent window handle
0, _ ' window menu handle
hInstance, _ ' program instance handle
BYVAL %NULL) ' creation parameters
hCtl = CreateWindowEx(0, "BUTTON", "&Ok", %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_FLAT, _
0, 0, 0, 0, hWndMain, %IDOK, hInstance, BYVAL %NULL)
IF hFont THEN SendMessage hCtl, %WM_SETFONT, hFont, 0
hCtl = CreateWindowEx(0, "BUTTON", "&Close", %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_FLAT, _
0, 0, 0, 0, hWndMain, %IDCANCEL, hInstance, BYVAL %NULL)
IF hFont THEN SendMessage hCtl, %WM_SETFONT, hFont, 0
' Show the window
ShowWindow hWndMain, nCmdShow
UpdateWindow hWndMain
' Message handler loop
LOCAL uMsg AS tagMsg
WHILE GetMessage(uMsg, %NULL, 0, 0)
IF ISFALSE IsDialogMessage(hWndMain, uMsg) THEN
TranslateMessage uMsg
DispatchMessage uMsg
END IF
WEND
FUNCTION = uMsg.wParam
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
LOCAL rc AS RECT
SELECT CASE wMsg
CASE %WM_CREATE
' -------------------------------------------------------
' A good place to initiate things, declare variables,
' create controls and read/set settings from a file, etc.
' -------------------------------------------------------
CASE %WM_SIZE
' ----------------------------------------------------------------------
' If you have a Toolbar and/or a Statusbar, send the following messages:
' SendMessage hStatusbar, wMsg, wParam, lParam
' SendMessage hToolbar, wMsg, wParam, lParam
' ----------------------------------------------------------------------
' Resize the two sample buttons of the dialog
IF wParam <> %SIZE_MINIMIZED THEN
GetClientRect hWnd, rc
MoveWindow GetDlgItem(hWnd, %IDOK), (rc.nRight - rc.nLeft) - 185, (rc.nBottom - rc.nTop) - 35, 75, 23, %TRUE
MoveWindow GetDlgItem(hWnd, %IDCANCEL), (rc.nRight - rc.nLeft) - 95, (rc.nBottom - rc.nTop) - 35, 75, 23, %TRUE
END IF
CASE %WM_COMMAND
' -------------------------------------------------------
' Messages from controls and menu items are handled here.
' -------------------------------------------------------
SELECT CASE LO(WORD, wParam)
CASE %IDOK
IF HI(WORD, wParam) = %BN_CLICKED THEN
ShowPopupDialog(hwnd)
END IF
CASE %IDCANCEL
IF HI(WORD, wParam) = %BN_CLICKED THEN
SendMessage hWnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
END SELECT
CASE %WM_CTLCOLORBTN, %WM_CTLCOLOREDIT, %WM_CTLCOLORLISTBOX, %WM_CTLCOLORSTATIC
' --------------------------------------------------------
' wParam is the handle of the control's display context (hDC)
' lParam is the handle of the control
' Example of how to set the colors of an specific control:
' --------------------------------------------------------
' IF lParam = GetDlgItem(hWnd, CtlId) THEN
' SetBkColor wParam, GetSysColor(%COLOR_INFOBK)
' SetTextColor wParam, GetSysColor(%COLOR_INFOTEXT)
' FUNCTION = GetSysColorBrush(%COLOR_INFOBK)
' EXIT FUNCTION
' END IF
' --------------------------------------------------------
CASE %WM_SYSCOMMAND
' Capture this message and send a WM_CLOSE message
IF (wParam AND &HFFF0) = %SC_CLOSE THEN
SendMessage hWnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
CASE %WM_CLOSE
' --------------------------------------------------------
' The WM_CLOSE message is processed BEFORE the WM_DESTROY
' message and it can be used to confirm program exit or
' tasks like deallocating memory or similar tasks.
' --------------------------------------------------------
CASE %WM_DESTROY
' ---------------------------------------------------------------------------
' Is sent when program ends - a good place to delete any created objects and
' store settings in file for next run, etc. Must send PostQuitMessage to end
' properly in SDK-style dialogs. The PostQuitMessage function sends a WM_QUIT
' message to the program's (thread's) message queue, and then WM_QUIT causes
' the GetMessage function to return zero in WINMAIN's message loop.
' ---------------------------------------------------------------------------
PostQuitMessage 0 ' This function closes the main window
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
The attached file contains the source code, the DLL and the EXE.
hello jose.
QuoteNow, if you want to put the popup windows (or dialogs, if you prefer it), in a DLL, there is nothing difficult or mysterious: just do it!
It's just so easy ? thank you! Thought too complicated about winmain and popup dialogues and wanted to declare everything separately. I will create for next time new pb DLL example. And do it :)
best regards, frank