User Tools

Site Tools


Using callback functions

by Richard Russell, December 2008

A few Windows API functions require the use of a callback routine, that is a function which you provide that is called by Windows during execution of the API call. The normal SYS statement does not provide this capability, but it is available by means of the CALLBACK library provided with BBC BASIC for Windows.

The library should be installed, as usual, by including this code at the beginning of your program, for example in an initialisation routine:

        INSTALL @lib$+"CALLBACK"

To use the library, replace the conventional method of calling a Windows API function:

        SYS "FunctionName", parameters TO result%

with the following code (requires CALLBACK.BBC version 3.4 or later):

        SYS FN_syscalls("FunctionName"), parameters TO !FN_systo(result%)

Note particularly the exclamation mark before FN_systo!

When using the CALLBACK library you must be careful how you pass string parameters. In the event that one or more of the parameters needs to be a string, add a NUL-termination (requires BBC BASIC for Windows version 5.93a or later):

        parameter$ += CHR$(0) : REM Add NUL termination
        SYS FN_syscalls("FunctionName"), parameter$ TO !FN_systo(result%)

In the event that you need to call the API function by address rather than by name use the following code:

        SYS FN_syscalln(FunctionAddress%), parameters TO !FN_systo(result%)

You must include the TO clause even if you don't need the value returned by the API function. In that case simply assign the value to a dummy variable.

The callback routine (which will sometimes be specified as one of the parameters) should be entered as:

        FN_callback(FNfunctionname(), npar%)

Here FNfunctionname is the name of the callback function in your program and npar% is the number of parameters it takes (this will be specified in the description of the API function).

You should ensure that your callback function executes as quickly as possible; ideally it should not perform any input or output.

The use of this facility is probably best illustrated by means of a few examples:

Enumerating windows

The following program will count the number of windows and store their handles in an array:

        INSTALL @lib$+"CALLBACK"
        DIM hwnd%(999)
        index% = 0
        SYS FN_syscalls("EnumWindows"), FN_callback(FNenumwinfunc(), 2), 0 TO !FN_systo(result%)
        PRINT "Exit code = ";result%
        PRINT "Number of windows enumerated = ";index%
        PRINT "hwnd%(0) = ";hwnd%(0)", hwnd%(";index%-1;") = ";hwnd%(index%-1)
        DEF FNenumwinfunc(hwnd%, param%)
        hwnd%(index%) = hwnd%
        index% += 1
        IF index% <= 999 THEN = 1 ELSE = 0

Enumerating fonts

The following program will count the number of fonts and store their names in an array:

        INSTALL @lib$+"CALLBACK"
        DIM font$(999)
        index% = 0
        SYS FN_syscalls("EnumFonts"), @memhdc%, 0, FN_callback(FNenumfontfunc(), 4), \
        \                             0 TO !FN_systo(result%)
        PRINT "Exit code = ";result%
        PRINT "Number of fonts enumerated = ";index%
        IF index% THEN
          PRINT "font$(0) = ";font$(0)
          PRINT "font$(";index%-1;") = ";font$(index%-1)
        DEF FNenumfontfunc(lplf%, lptm%, type%, data%)
        font$(index%) = $$(lplf%+28)
        index% += 1
        IF index% <= 999 THEN = 1 ELSE = 0

Enumerating date formats

The following program will count the number of available date formats and store them in a string array:

        INSTALL @lib$+"CALLBACK"
        DIM dfmt$(99)
        index% = 0
        SYS FN_syscalls("EnumDateFormats"), FN_callback(FNenumdatefunc(), 1), &800, \
        \                                   1 TO !FN_systo(result%)
        PRINT "Exit code = ";result%
        PRINT "Number of date formats enumerated = ";index%
        FOR i% = 0 TO index%-1
          PRINT dfmt$(i%)
        DEF FNenumdatefunc(lpdfs%)
        dfmt$(index%) = $$lpdfs%
        index% += 1
        IF index% <= 99 THEN = 1 ELSE = 0
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
using_20callback_20functions.txt · Last modified: 2018/04/14 18:17 by richardrussell