View Full Version : How to use win api functions in thinBasic ?
Hi all,
I am playing with some win32 api functions. I would like to know how to do it in thinBasic. Is there any tutorials or dedicated posts related to it ? I want to know how to handle data types like HMODULE, HRESULT etc. Thanks in advance.
ErosOlmi
06-09-2018, 16:17
Well, we can talk or write for ages :D
Here a summary of all Windows types: https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types
For 32Bit process:
in general types are almost all 32bit DWORD (or LONG) pointer to some data structure or to some memory buffer representing a sequence o bytes to be interpreted.
Very rarely or a WIN32API function accepts something different from a DWORD (or LONG) representing a pointer to something.
If you cab be more precise with a specific example, I can help step by step.
Ciao
Eros
ErosOlmi
06-09-2018, 16:38
On how to do in thinBasic:
first DECLARE the Windows API as a Sub or a Function.
Then you can use as script function
Take the following example: you want to know the computer and the user name currently logged. Windows has one function for each of the info:
GetUserName (API name is GetUserNameA and the A stands for is the ASCII version)
declared at https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getusernamea
GetComputerName (API name is GetComputerNameA and the A stands for is the ASCII version)
declared at https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getcomputernamea
Here thinBasic code that is not much different from the code you woulod have written in FreeBasic or PowerBasic or many other languages:
first declare you API functions in the correct way
then use them in the correct way
Hope this helps.
Ciao
Eros
uses "Console"
'---Declare needed Windows API functions
DECLARE FUNCTION GetUserName LIB "AdvApi32.dll" ALIAS "GetUserNameA" (byval lpBuffer AS dword, byref nSize AS DWORD) AS LONG
DECLARE FUNCTION GetComputerName LIB "Kernel32.dll" ALIAS "GetComputerNameA" (byval lpBuffer AS dword, ByRef nSize AS DWORD) AS LONG
dim lLen as dword = 100 '---a DWORD in which we store the len of the buffer
Dim sComputer as asciiz * lLen '---String buffer for computer name
Dim sName as asciiz * lLen '---String buffer for user name
'---Call the function passing the pointer to the string buffer and the pointer to the DWORD contaiing the value of the string lenght
GetComputerName (strptr(sComputer), lLen)
'---Call the function passing the pointer to the string buffer and the pointer to the DWORD contaiing the value of the string lenght
GetUserName (strptr(sName), lLen)
'---Show the values
printl "Computer name is:", sComputer
printl "User name is:", sName
printl "---Press a key to end---"
WaitKey
ErosOlmi
06-09-2018, 16:51
Another way to declare the 2 above windows API functions is to declare the string buffer as
byref lpBuffer AS asciiz
ByRef always means to pass a PTR (a pointer) to something, in this case to an ASCIIZ string buffer
In this way it is not needed to call the function as
GetComputerName (StrPtr(sComputer), lLen)
but only
GetComputerName (sComputer, lLen)
because thinBasic understand you want to pass BYREF an ASCIIZ variable and it will pass the pointer to that variable for you.
Example:
uses "Console"
'---Declare needed Windows API functions
DECLARE FUNCTION GetUserName LIB "AdvApi32.dll" ALIAS "GetUserNameA" (byref lpBuffer AS asciiz, byref nSize AS DWORD) AS LONG
DECLARE FUNCTION GetComputerName LIB "Kernel32.dll" ALIAS "GetComputerNameA" (byref lpBuffer AS Asciiz, ByRef nSize AS DWORD) AS LONG
dim lLen as dword = 100 '---a DWORD in which we store the len of the buffer
Dim sComputer as asciiz * lLen '---String buffer for computer name
Dim sName as asciiz * lLen '---String buffer for user name
'---Call the function passing the pointer to the string buffer and the pointer to the DWORD contaiing the value of the string lenght
GetComputerName (sComputer, lLen)
'---Call the function passing the pointer to the string buffer and the pointer to the DWORD contaiing the value of the string lenght
GetUserName (sName, lLen)
'---Show the values
printl "Computer name is:", sComputer
printl "User name is:", sName
printl "---Press a key to end---"
WaitKey
@Eros,
Thanks for the reply. I was planning to do some gui programming on thinBasic with CreateWindowEx and other related functions. But soon i realized that i need to study about the equivalent data types in thinBasic. So i decided to start with the MessageBox function. This is the code i have started with.
'---Load Console Module
Uses "console"
Declare Function MessageBoxW Lib "User32.dll" Alias "MessageBox"( _
Byval hWnd As Long, _
ByRef lpTxt as String, _
ByRef lpCaption as String, _
Byval uType as UInt32) As Int
MessageBox(0, "Simple Msg from API", "Win32 Rocks", %MB_OK)
PrintL "Press a key to end program"
'---Wait for a key press
'WaitKey
Unfortunately this code is not working. It says that an unknown keyword is in line no. 9.
ErosOlmi
06-09-2018, 20:00
Handling or passing strings is the most complex understanding in general because every system, every programming language, every programming paradigm manage strings in different ways.
So you cannot just define a parameter ... As String to be able to pass what the called function expects.
Above example of DECLARE I think is from FreeBasic where ... As String is because strings in FreeBasic are like ASCIIZ strings so in thinBasic it would be ... ASCIIZ
in thinBasic dynamic Strings are OLE strings or BSTR strings and are not a simple sequence of bytes but a more complex one: a pointer to a buffer, https://msdn.microsoft.com/en-us/library/cc230304.aspx
But you was almost there.
Below 2 of the possible Message box functions window is publishing:
MessageBoxA is the ascii or ansi version: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messageboxa
MessageBoxW is the unicode or wide version: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messageboxw
Reading MSDN documentation:
MessageBoxA accept a LPCSTR string that in thinBasic is a pointer to an ASCIIZ string. thinBasic understan that is a pointer because parameter is defined BYREF (omitting passing type in a DECLARE means BYREF)
MessageBoxW accept a LPCWSTR string that in thinBasic is a pointer to an ASCIIZ string transformed into an unicode string using UCODE$
'---LPCSTR is a ansi (ascii) string pointer.
'---LPCWSTR is a wide (unicode) asciiz string pointer. UCODE$ is used to transform an ascii string into an unicode string
Alias AsciiZ as LPCSTR
Alias AsciiZ as LPCWSTR
DECLARE FUNCTION MessageBoxW LIB "User32.dll" ALIAS "MessageBoxW" (
BYVAL hWnd AS DWORD,
lpText AS LPCWSTR,
lpCaption AS LPCWSTR,
BYVAL dwType AS DWORD) AS LONG
DECLARE FUNCTION MessageBoxA LIB "User32.dll" ALIAS "MessageBoxA" (
BYVAL hWnd AS DWORD,
lpText AS LPCSTR,
lpCaption AS LPCSTR, _
BYVAL dwType AS DWORD) AS LONG
MessageBoxA(0, "Simple Ansi Msg from API", "Win32 Rocks", %MB_OK)
MessageBoxW(0, ucode$("Simple Wide Msg from API "), ucode$("Win32 Rocks"), %MB_OK)
Not easy at first.
You need to practice a bit and understand most important data types used by MSDN documentation and how to trasform in thinBasic (or other programming languages) types.
https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types
In future thinBasic versions I will add unicode strings so interfacing will be a bit easier
In future thinBasic versions I will add unicode strings so interfacing will be a bit easier
@Eros,
Thanks. That will be very handy. Now, thinBasic's AsciiZ is not displaying my native language correctly. I am ready to wait for a better thinBasic with complete unicode support. In the meantime, i can practice thinBasic more and more. :)