CALLBACK allows you to write a function or method in dBL code and setup a pointer to it that can be passed to an external program - such as Windows or the BDE or some other 3rd party software that supports callbacks.

Callbacks can be used to notify your program of specific events occurring with an external program OR to allow your program to modify what an external program is doing.

Syntax

CALLBACK <return type> <function name>([<param type>,...])

         [FROM <filename>]

         [OBJECT <oRef>]

      

<return type>

EXTERN type returned by function

<function name>

Name of dBL function or method to be made callable From external program

<param type>,...

Zero or more EXTERN types specifying the parameter types expected by the dBL function or method

<filename>

dBL source file containing function or method

<oRef>

Object reference of object containing dBL method

 

Examples:

this first example illustrate how we can use the Callback solutions

to subclassing  the Window procedure of Form; in the following steps:

1) Open Form

2) Press the Notebook button "Attach"

3) Watch the messages on Command Window

class MyForm of FORM

   with (this)

      canClose = class::FORM_CANCLOSE

      onOpen = class::FORM_ONOPEN

      height = 12.2273

      left = 57.5714

      top = 8.3636

      width = 59.8571

      text = ""

   endwith

   this.ENTRYFIELD1 = new ENTRYFIELD(this)

   with (this.ENTRYFIELD1)

      height = 1.0

      left = 4.0

      top = 1.5

      width = 22.0

      value = "Entryfield1"

   endwith

   this.NOTEBOOK1 = new NOTEBOOK(this)  

   with (this.NOTEBOOK1)

      canSelChange = class::NOTEBOOK1_CANSELCHANGE

      tabStop = false

      height = 2.5

      left = 49.0

      top = 0.5

      width = 10.0

      dataSource = 'ARRAY {"Detach","Attach"}'

      buttons = true

      multiple = true

      focus = 2 // Never

   endwith

    

 function form_onOpen

    #define GWL_WNDPROC   (-4)

    if type("GetWindowLong") # "FP"

       extern CLONG GetWindowLong(CHANDLE, CINT) user32 from "GetWindowLongA"

    endif

    if type("SetWindowLong") # "FP"

       extern CLONG SetWindowLong(CHANDLE, CINT, CLONG) user32 from "SetWindowLongA"

    endif

    if type("CallWindowProc") # "FP"

       extern CLONG CallWindowProc(CPTR, CHANDLE, CUINT, CUINT, CUINT) user32 from "CallWindowProcA"

    endif

    this.newProc = null

    this.oldProc = null

    this.attached = false

    return

 

 function form_canClose

    

    if this.attached

       return false

    endif

    

    release callback callWndProc object this

    return true

 

 function NOTEBOOK1_canSelChange(newSel)

    if newSel == 1

       return form.detach()

    elseif newSel == 2

       return form.attach()

    endif   

    return true

 

  function attach

   if this.attached OR this.hwnd == 0

       return false

    endif

    if this.oldProc == null

       this.oldProc = GetWindowLong(this.hwnd, GWL_WNDPROC)

    endif

    if this.newProc == null

       callback CLONG callWndProc(CHANDLE, CUINT, CUINT, CUINT) object this   

       this.newProc = GetCallAddress(this.callWndProc)

    endif

    SetWindowLong(this.hwnd, GWL_WNDPROC, this.newProc)

    ? "hwnd:", this.hwnd, "oldProc:", this.oldProc, "newProc:", this.newProc

    this.attached = true

    return true

 

 function detach

    if not this.attached

       return false

    endif

    SetWindowLong(this.hwnd, GWL_WNDPROC, this.oldProc)

    this.attached = false

    return true

 

 function callWndProc(hWnd, uMsg, wParam, lParam)

    ? [MSG:], uMsg, [WP:], wParam, [LP:], lParam

    

    return CallWindowProc(this.oldProc, hwnd, uMsg, wParam, lParam)

 

endclass

See Also

GETCALLADDRESS

RELEASE CALLBACK