Win32Forth


Windows Callback support


The Windows operating system DLLs often needs application defined callbacks to be supplied for certain jobs. Since it is written in C then it assumes the callback only needs a single stack to work with, so Win32Forth must wrap a Forth word to allocate a second stack and transfer the input arguments to it. It also sets up other registers for Forth, including the USER pointer for the calling Task (Versions of Win32Forth prior to V6.06.xx always used the CONUSER pointer for this so callbacks were restricted to the main (console) task only). It is important to remember a normal xt will not work as a callback.

Glossary

: __STDCALL     ( -- )                          \ w32f sys

Turn on stdcall type callback (the default).

: __CDECL       ( -- )                          \ w32f sys

Turn on __cdecl type callback for the next callback only.

: CALLBACK      ( n1 -<name function>- )        \ w32f sys

Define a callback with "name" that has n1 arguments. "name" will return the address of the callback at runtime.

Note that a maximum of 19 arguments is supported by Win32Forth.

: CALLBACK:     ( args -<name>- )               \ w32f sys

Define a callback function that has n1 arguments.

CALLBACK: creates TWO definitions! The first has the name you specify, and the second has the same name, prefixed with a '&' meaning 'address of' This second definition is the one which returns the address of the callback, and must be passed to Windows.

Note that a maximum of 19 arguments is supported by Win32Forth.

**********************************************************************

An example of how to use a callback

**********************************************************************

The "EnumFonts" windows call requires an application callback that will be called repeatedly to process each font in the system. We are just displaying the fonts, so we just look at the "dwType" to decide how to display each font.

4 CallBack: FontFunc { lplf lptm dwType lpData -- int }
\ The callback function for EnumFonts() used by .FONTS to dump
\ all installed fonts to the console window.
\ This callback as specified by "EnumFonts" passes four (4) parameters to
\ the callback procedure, so we must say "4 CallBack: FontFunc" to define
\ a callback that accepts four parameters.
                cr
                dwType
                dup TRUETYPE_FONTTYPE and
                IF      ."     "
                ELSE    ." Non-"
                THEN    ." TrueType "
                dup RASTER_FONTTYPE and
                IF      ." Raster "
                ELSE    ." Vector "
                THEN
                DEVICE_FONTTYPE and
                IF      ." Device "
                ELSE    ." GDI    "
                THEN
                lplf 28 + LF_FACESIZE 2dup 0 scan nip - type
                cr 5 spaces
                lplf dup @ 4 .r                 \ height
                4 + dup @ 4 .r                  \ width
                4 + dup @ 6 .r.1                \ escapement angle
                4 + dup @ 6 .r.1                \ orientation angle
                4 + dup @ 4 .r                  \ weight
                4 + dup c@ 1 and 2 .r           \ italics
                1 + dup c@ 1 and 2 .r           \ underline
                1 + dup c@ 1 and 2 .r           \ strike-out
                1 + dup c@ 4 .r                 \ character set
                1 + dup c@ 2 .r                 \ output precision
                1 + dup c@ 4 .r                 \ clip precision
                1 + dup c@ 2 .r                 \ output quality
                1 +     c@ 4 h.r                \ family and pitch
                1 ;  \ return "1=success" flag to windows

: .fonts        ( -- )          \ w32f sys
: .fonts        ( -- )          \ w32f sys

Dump all installed Fonts to the console window.

\ The callback name is passed to windows as shown.
                cr 5 spaces
                ."   ht wide  esc  ornt wt  I U S set p  cp q  fp"
                0
                &FontFunc \ here it goes...
                0 conDC Call EnumFonts drop ;

**********************************************************************

The window message handler for Win32Forth.

**********************************************************************
: HandleMessages { pMsg -- 0 }

This is the word which handles the messages send by windows to our Application. The chain MSG-CHAIN receives all messages.

This word is called by WINPAUSE, and is also used as a callback by the console.

**********************************************************************

Allow Forth to send messages to itself.

**********************************************************************

Each instance of forth running under windows is able through the method WM32Forth: and a unique set of application specific constants (WM_BEEPME in this example) to detect a message being set to itself, and subsequently perform some specific operation as ordered.

:M Win32Forth:  ( h m w l -- )
           over WM_BEEPME =
           if   beep
           then ;M

 Note:  This Win32Forth feature is  deprecated , and may be removed in a future release.

-1 value WM_WIN32FORTH                          \ w32f

This windows message definition for WM_WIN32FORTH, provides a way for multiple Win32Forth applications to interact between themselves while running.

: WM_WIN32FOR-INIT ( -- )                       \ w32f internal

WM_WIN32FOR-INIT obtains a unique windows message value from Windows then Win32Forth starts up, so this instance of forth will be able to talk to other instances of forth.

' _win32forth-message is win32forth-message ( lParam wParam -- ) \ w32f

WIN32FORTH-MESSAGE allows a unique message to be broadcast to all currently running instances of Win32Forth.

'wParam' is the application specific sub-message that each instance can

** use to determine if it should handle the message. 'lParam' is available to pass specific information between instances of Win32Forth.

Note: The message is not only broadcast to to all currently running instances of Win32Forth. It is brodcast to ALL windows in the system. So it may be rather slow...

: HandleWindowsMessages { hwnd msg wParam lParam -- flag }

This is the callback which handles the messages send by win32forth-message. It is called in the windows procedure of the console window of win32forth.

A Win32Forth-message example:

31415 constant WM_BEEPME    \ a command code to beep

\ Send the message "WM_BEEPME" to all running instances of Win32Forth
: beepme        ( -- )
                0 WM_BEEPME win32forth-message ;

\ The chain "FORTH-MSG-CHAIN" receives all messages that are broadcast by any
\ program with the WM_WIN32FORTH message.  "FORTH-MSG-BEEP" tests the sub-message
\ WM_BEEPME, and if it matches, then it beeps the console. Any sub-message that
\ is not recognized by any instance of a Win32Forth program must be ignored.
: forth-msg-beep ( wParam lParam -- wParam lParam )
                 over WM_BEEPME =
                 if   beep
                 then ;

forth-msg-chain chain-add forth-msg-beep

********************************************************************** ********************************************************************** ********************************************************************** **********************************************************************

Document $Id: p-callback.htm,v 1.5 2007/05/26 10:24:11 dbu_de Exp $