Post by Walt Decker on Apr 28, 2023 15:07:53 GMT -5
I originally attempted to do this within the LB framework but I could not get the class registration to work so I put that in a dll since I would need a dll anyway.
For those who are adventurous here is a little bit of code. The attached zip contains
SEE END OF POST.
'
ADVENTURE.ZIP CONTENTS:
API_ADVTUR._BAS
API_ADVTUR_V2._BAS
LBFD_0.DLL
OPEN "user32.dll" FOR DLL AS #USER
OPEN "kernel32.dll" FOR DLL AS #KERN
OPEN "LBFD_0" FOR DLL AS #LBFD
GWL.HINSTANCE = -6
GWL.WNDPROC = -4
GLOBAL ToolHndl
Instance = 0
WinHndl = 0
ToolHndl = 0
Code.Ptr = 0
WinSizeX = DisplayWidth * 0.75
WinSizeY = DisplayHeight * 0.75
WinHndl = FN.CreateBaseWin(WinSizeX, WinSizeY, "TEST WIN")
'<======= get info to create a window class ===========>
Instance = FN.GetWindowParams(WinHndl, GWL.HINSTANCE)
Code.Ptr = FN.GetWindowParams(WinHndl, GWL.WNDPROC)
ToolHndl = FN.CreateToolWin(Instance, Code.Ptr)
RetVal = FN.WAIT(150)
WAIT
'------------------------------------
'------------------------------------
SUB BAS.CLOSE BasHndl$
'#############################################
' Destroy the forms and release DLLs
'
' NOTE: The LB IDE does not properly release
' non-API DLLs if the dll contains a function
' associated with a callback
'#############################################
GWL.HINSTANCE = -6
RetVal = 0
WinHndl = 0
Instance = 0 'application instance
WinHndl = FN.GetHndl(BasHndl$)
Instance = FN.GetWindowParams(WinHndl, GWL.HINSTANCE)
'<============ release the pop-up window from the dll ===============>
CALLDLL #LBFD, "FN_ReleaseCallBack", ToolHndl AS ULONG, RetVal AS ULONG
CLOSE #LBFD
CLOSE #BasHndl$
CALLDLL #KERN, "Sleep", 0 AS LONG, RetVal AS VOID
'<================ destroy the tool pop-up class ================>
CALLDLL #USER, "UnregisterClassA", "LB_BUTTONS" AS PTR, Instance AS ULONG, _
RetVal AS LONG
CLOSE #USER
CLOSE #KERN
END
END SUB
'------------------------------------
'------------------------------------
FUNCTION FN.WAIT(Ms)
'#############################################
' Acts as a TIMER function
' Ms = milliseconds
'#############################################
RetVal = 0
[MORE.SLEEP]
CALLDLL #KERN, "Sleep", Ms AS LONG, RetVal AS VOID
SCAN
GOTO [MORE.SLEEP]
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.CreateBaseWin(Szx, Szy, Title$)
'#############################################
' Create Base form
' Szx = width of form
' Szy = height of form
' Title = form caption
'#############################################
Cx = 0
Cy = 0
Ux = 0
Uy = 0
WinHndl = 0
RetVal = 0
Cx = DisplayWidth * 0.5
Cy = DisplayHeight * 0.5
Ux = INT(Cx - Szx * 0.5) - 1
Uy = INT(Cy - Szy * 0.5) - 1
RetVal = FN.SetLbPos(Ux, Uy)
RetVal = FN.SetLbSize(Szx, Szy)
OPEN Title$ FOR WINDOW AS #BAS
#BAS, "TRAPCLOSE BAS.CLOSE"
WinHndl = FN.GetHndl("#BAS")
FN.CreateBaseWin = WinHndl
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.CreateToolWin(Inst, CodePtr)
'########################################################
' Regiseter and create a form and controls independant
' of Liberty Basic.
'
' Inst = application instance
' CodePtr = code address of the base form
'########################################################
DATA "BUTTON 1" 'title of buttons
DATA "BUTTON 2"
DATA "BUTTON 3"
DATA "BUTTON 4"
DATA "BUTTON 5"
'<========== window and control styles ==========>
WS.POPUP = HEXDEC("&H80000000")
WS.CHILD = HEXDEC("&H40000000")
WS.VISIBLE = HEXDEC("&H10000000")
WS.CLIPSIBLINGS = HEXDEC("&H04000000")
WS.CLIPCHILDREN = HEXDEC("&H02000000")
WS.CAPTION = HEXDEC("&H00C00000")
WS.TABSTOP = HEXDEC("&H00010000")
'<========== extended styles ===============>
WS.EX.DLGMODALFRAME = HEXDEC("&H00000001")
WS.EX.TRANSPARENT = HEXDEC("&H00000020")
WS.EX.LTRREADING = HEXDEC("&H00000000")
WS.EX.APPWINDOW = HEXDEC("&H00040000")
'<=========== button styles =============>
BS.CHECKBOX = HEXDEC("&H00000002")
BS.AUTOCHECKBOX = HEXDEC("&H00000003")
BS.TEXT = HEXDEC("&H00000000")
BS.VCENTER = HEXDEC("&H00000C00")
BS.PUSHLIKE = HEXDEC("&H00001000")
BS.NOTIFY = HEXDEC("&H00004000")
'<=========== class registration styles ============>
CS.VREDRAW = HEXDEC("&H0001")
CS.HREDRAW = HEXDEC("&H0002")
CS.OWNDC = HEXDEC("&H0020")
CS.PARENTDC = HEXDEC("&H0080")
CS.DROPSHADOW = HEXDEC("&H00020000")
PALETURQUOISE = HEXDEC("&HEEEEAF") 'background form color
RegStyle = 0 'class registration style
Wnstyle = 0 'form/control style
Exstyle = 0 'form/control extened style
WinHndl = 0
Code.Ptr = 0 'callback code pointer
BtnId = 999 'button ids
Ok = 0
Ux = 0 'coordinates
Uy = 0
Ix = 0
Iy = 0
WinHndl = FN.GetHndl("#BAS")
RetVal = FN.MapPoints(WinHndl, 0, 0, 0, 0, 0)
Ux = tRect.X.struct 'client coords of upper left corner of base window
Uy = tRect.Y.struct
'<=============== set class style ==================>
RegStyle = CS.VREDRAW OR CS.HREDRAW OR CS.OWNDC OR CS.DROPSHADOW
'<=================== set form style ==================>
Wnstyle = WS.POPUP OR WS.CAPTION OR WS.VISIBLE OR WS.CLIPCHILDREN OR _
WS.CLIPSIBLINGS
Exstyle = WS.EX.CONTROLPARENT OR WS.EX.LEFT OR WS.EX.LTRREADING OR WS.EX.APPWINDOW
'<=========== register a new class ===================>
CALLDLL #LBFD, "FN_RegisterWindow", "LB_BUTTONS" AS PTR, CodePtr AS ULONG, _
Inst AS ULONG, RegStyle AS ULONG, PALETURQUOISE AS ULONG, _
Ok AS ULONG
'<=============== create a pop-up form ===================>
WinHndl = FN.CreateWindow(Exstyle, "LB_BUTTONS", "BUTTONS", Wnstyle, Ux, Uy, 105, 160, WinHndl, 0, Inst)
'<================== set styles for check box buttons ===============>
Wnstyle = WS.CHILD OR WS.TABSTOP OR WS.VISIBLE OR WS.CLIPSIBLINGS OR _
BS.AUTOCHECKBOX OR BS.PUSHLIKE OR BS.NOTIFY OR BS.VCENTER OR _
BS.TEXT
Exstyle = WS.EX.DLGMODALFRAME OR WS.EX.TRANSPARENT
'<=============== create check box button on form ===========>
Ix = 5
Iy = 5
FOR I = 1 TO 5
READ Txt$
BtnId = BtnId + 1 'give each button a different ID number
RetVal = FN.CreateWindow(Exstyle, "BUTTON", Txt$, Wnstyle, Ix, Iy, 90, 22, WinHndl, BtnId, Inst)
Iy = Iy + 20 + 5
NEXT I
'<================ get address of our, not LB's callback function ===========>
CALLBACK Code.Ptr, FN.App.CB(ULONG, ULONG, LONG, LONG), LONG
'<====== set dll callback function to access our callback function ======>
CALLDLL #LBFD, "FN_InitCallBack", WinHndl AS ULONG, Code.Ptr AS ULONG, _
Ok AS ULONG
FN.CreateToolWin = WinHndl
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.CheckHndl$(WinTag$)
WinTag$ = TRIM$(WinTag$)
IF LEFT$(WinTag$, 1) <> "#" THEN WinTag$ = "#" + WinTag$
FN.CheckHndl$ = WinTag$
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.GetHndl(WinTag$)
Hndl = 0
WinTag$ = FN.CheckHndl$(WinTag$)
ON ERROR GOTO [HNDL.ERROR]
Hndl = HWND(#WinTag$)
FN.GetHndl = Hndl
EXIT FUNCTION
[HNDL.ERROR]
PRINT "HANDLE ERROR = "; WinTag$
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.SetLbPos(Ux, Uy)
UpperLeftX = Ux
UpperLeftY = Uy
FN.SetLbPos = Ux * Uy
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.SetLbSize(Szx, Szy)
WindowWidth = Szx
WindowHeight = Szy
FN.SetLbSize = Szx * Szy
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.GetWindowParams(WinHndl, ParamIdx)
'########################################################
' API function GetWindowLong() obtains information about
' a form or control based on an index parameter.
'########################################################
RetVal = 0
CALLDLL #USER, "GetWindowLongA", WinHndl AS ULONG, ParamIdx AS LONG, _
RetVal AS ULONG
FN.GetWindowParams = RetVal
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.ClientSize(WinTag$, BYREF Bx, BYREF By)
'########################################################
' API function GetClientRect() obtains the coordinates of
' that portion of a form or control that is not caption or
' border.
'########################################################
STRUCT tRect, _
X AS LONG, _
Y AS LONG, _
X1 AS LONG, _
Y1 AS LONG
WinHndl = 0
RetVal = 0
WinHndl = FN.GetHndl(WinTag$)
CALLDLL #USER, "GetClientRect", WinHndl AS ULONG, tRect AS STRUCT, RetVal AS VOID
Bx = tRect.X.struct
By = tRect.Y.struct
FN.ClientSize = WinHndl
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.ClientRect(WinHndl)
'########################################################
' API function GetClientRect() obtains the coordinates of
' that portion of a form or control that is not caption or
' border.
'########################################################
STRUCT tRect, _
X AS LONG, _
Y AS LONG, _
X1 AS LONG, _
Y1 AS LONG
RetVal = 0
CALLDLL #USER, "GetClientRect", WinHndl AS ULONG, tRect AS STRUCT, RetVal AS VOID
FN.ClientRect = tRect.X1.struct * tRect.Y1.struct
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.WindowRect(WinTag$)
'########################################################
' API function GetWindowRect() obtains the display coordinates
' of a form or a control on a form.
'########################################################
STRUCT tRect, _
X AS LONG, _
Y AS LONG, _
X1 AS LONG, _
Y1 AS LONG
WinHndl = 0
RetVal = 0
WinHndl = FN.GetHndl(WinTag$)
CALLDLL #USER, "GetWindowRect", WinHndl AS ULONG, tRect AS STRUCT, RetVal AS VOID
FN.WindowRect = WinHndl
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.MapPoints(Wfrom, Wto, Ptx, Pty, Ptx1, Pty1)
'########################################################
' API function MapWindowPoints() translates coordinates from
' one object to another object, e.g. display coordinates to
' form coordinates.
'########################################################
STRUCT tRect, _
X AS LONG, _
Y AS LONG, _
X1 AS LONG, _
Y1 AS LONG
tRect.X.struct = Ptx
tRect.Y.struct = Pty
tRect.X1.struct = Ptx1
tRect.Y1.struct = Pty1
RetVal = 0
CALLDLL #USER, "MapWindowPoints", Wfrom AS ULONG, Wto AS ULONG, tRect AS STRUCT, _
2 AS LONG, RetVal AS LONG
FN.MapPoints = RetVal
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.App.CB(Hndl, Msg, wParam, lParam)
'#################################################
' This is like an API application CALLBACK FUNCTION
' Hndl = Numeric handle assigned by the windows os
' Msg = What happened, i.e. action by the user or application
' wParam = information concerning what happened
' lParam = more info about what happened
'
' In an API app when a button is pressed, windows sends:
' WM_KILLFOCUS
' WM_SETFOCUS
' WM_COMMAND
'
' The notification message BN_CLICKED is in the HI(WORD) of wParam and the
' button id assigned by the programmer is in the LO(WORD) of wparam. The
' handle of the button assigned by windows is in lParam
'
' Here the notification path is changed to the BN_CLICKED
' notification because this module is dealing with buttons only,
' so the Msg parameter is not WM_COMMAND but BN_CLICKED, wParam
' is the control ID number, and lParam is the handle of the
' button clicked.
'#################################################
BN.CLICKED = 0
NumChrs = 0
BtnId = 1000
Txt$ = ""
SELECT CASE Msg
CASE BN.CLICKED
SELECT CASE wParam
IF (wParam >= BtnId) AND (wParam < BtnId + 6) THEN
Txt$ = SPACE$(32)
CALLDLL #USER, "GetWindowTextA", lParam AS ULONG, Txt$ AS STRUCT, _
32 AS LONG, NumChrs AS LONG
Txt$ = LEFT$(Txt$, NumChrs)
PRINT "YOU CLICKED "; Txt$
END IF
END SELECT
END SELECT
END FUNCTION
'------------------------------------
'------------------------------------
FUNCTION FN.CreateWindow(StyleEx, ClassName$, Title$, NormStyle, Ux, Uy, Bx,By, Phndl, CtrlId, AppInst)
Hndl = 0
CALLDLL #USER, "CreateWindowExA", _
StyleEx AS ULONG, _ ' extended styles
ClassName$ AS PTR, _ ' window class name
Title$ AS PTR, _ ' window caption
NormStyle AS ULONG, _ ' window/control style
Ux AS LONG, _ ' initial x position; zero is a valid position
Uy AS LONG, _ ' initial y position; zero is a valid position
Bx AS LONG, _ ' initial x size
By AS LONG, _ ' initial y size
Phndl AS ULONG, _ ' parent/owner window handle
CtrlId AS LONG, _ ' window menu handle or ctrl id
AppInst AS LONG, _ ' program instance handle
0 AS LONG, _ ' creation parameters
Hndl AS ULONG
FN.CreateWindow = Hndl
END FUNCTION
'---------------------------------------------------------------
'---------------------------------------------------------------
'
ADVENTURE.ZIP CONTENTS:
API_ADVTUR._BAS
API_ADVTUR_V2._BAS
LBFD_0.DLL