Events Reference A-Z
This page documents every event available in HarbourBuilder. Events are code blocks assigned
to control properties that are invoked when the corresponding OS-level event fires. Events form
the core of HarbourBuilder's reactive programming model.
How events work
Each event is a property on a control object. You assign a Harbour code block
({ || ... }) to it. When the user interacts with the control, HarbourBuilder routes
the native OS event through the backend (Win32/Cocoa/GTK3) and evaluates your code block.
Event Assignment Syntax
Events are assigned using the standard Harbour assignment operator with a code block:
--- Simple event: show a message ---
oBtn:OnClick := { || MsgInfo( "Button clicked!" ) }
--- Event calling a function ---
oBtn:OnClick := { || ProcessClick( oBtn, oForm ) }
--- Event with parameters (keyboard events) ---
oEdit:OnKeyDown := { | nKey, nFlags | HandleKey( nKey, nFlags ) }
--- Event with mouse coordinates ---
oPaintBox:OnMouseMove := { | nX, nY | TrackMouse( nX, nY ) }
--- Multi-statement code block ---
oBtn:OnClick := { || ;
LogAction( "button clicked" ), ;
MsgInfo( "Done!" ), ;
oForm:Close() ;
}
Designer-assigned events
In the Form Designer, select a control, go to the Events tab in the Object Inspector,
and double-click an event. The IDE generates the code block and jumps to the code editor.
Mouse Events
| Event | Parameters | Available Controls | Description |
OnClick |
none |
All interactive controls |
Fires when the user clicks the control with the left mouse button. This is the most commonly used event for buttons, list items, and tree nodes. |
OnDblClick |
none |
All interactive controls |
Fires on a double-click. For list/grid controls, this often triggers an "edit" or "open" action. For forms, can trigger default behavior. |
OnMouseDown |
nButton, nShiftState, nX, nY |
All visual controls |
Fires when any mouse button is pressed. nButton: 1=left, 2=right, 3=middle. nShiftState: bitmask for Shift/Ctrl/Alt. |
OnMouseUp |
nButton, nShiftState, nX, nY |
All visual controls |
Fires when any mouse button is released. Useful for drag-and-drop completion or measuring click duration. |
OnMouseMove |
nX, nY |
All visual controls |
Fires continuously as the mouse moves over the control. Use sparingly; it fires very frequently. Good for tracking cursor position or hover effects. |
OnMouseWheel |
nDelta, nX, nY |
All visual controls |
Fires when the mouse wheel is scrolled. nDelta is positive for scroll up/forward, negative for scroll down/back. Typically used for zooming or scrolling content. |
Mouse Event Examples
--- OnClick: simple button action ---
oBtn:OnClick := { || MsgInfo( "Hello!" ) }
--- OnMouseDown: detect right-click context menu ---
oPanel:OnMouseDown := { | nBtn, nShift, nX, nY | ;
if nBtn == 2 /// right click
ShowContextMenu( nX, nY )
endif ;
}
--- OnMouseWheel: zoom in/out on an image ---
oImage:OnMouseWheel := { | nDelta, nX, nY | ;
if nDelta > 0
oImage:nZoom += 0.1
else
oImage:nZoom -= 0.1
endif, ;
oImage:Refresh() ;
}
Keyboard Events
| Event | Parameters | Available Controls | Description |
OnKeyDown |
nKey, nFlags |
All focusable controls |
Fires when a key is pressed down. nKey is the virtual key code (VK_ constants). nFlags contains repeat count and scan code. Fires before the character is processed. |
OnKeyUp |
nKey, nFlags |
All focusable controls |
Fires when a key is released. Useful for detecting how long a key was held or for key-chord detection. |
OnKeyPress |
cKey |
Edit, Memo, MaskEdit, ComboBox |
Fires when a character key is typed. cKey is the actual character (not virtual code). Allows you to modify or cancel the character by changing the parameter. |
Keyboard Event Examples
--- OnKeyDown: handle Enter and Escape ---
oForm:OnKeyDown := { | nKey, nFlags | ;
if nKey == VK_RETURN
AcceptForm()
elseif nKey == VK_ESCAPE
CancelForm()
endif ;
}
--- OnKeyPress: filter input to digits only ---
oEdit:OnKeyPress := { | cKey | ;
if !( cKey >= "0" .and. cKey <= "9" ) .and. cKey != Chr( 8 )
Alert( "Only digits allowed" )
return .F. /// cancel the key
endif ;
}
--- OnKeyUp: detect Ctrl+S for save shortcut ---
oForm:OnKeyUp := { | nKey, nFlags | ;
if nKey == 83 .and. GetKeyState( VK_CONTROL ) < 0
SaveProject()
endif ;
}
Focus and Selection Events
| Event | Parameters | Available Controls | Description |
OnEnter |
none |
All focusable controls |
Fires when the control receives input focus (via Tab, click, or programmatically). Useful for highlighting the active field or showing context-sensitive help. |
OnExit |
none |
All focusable controls |
Fires when the control loses focus. Use this for validation: check the field value and prevent focus loss by returning .F. if invalid. |
OnChange |
none |
Edit, Memo, ComboBox, CheckBox, Radio, TrackBar, UpDown |
Fires when the control's value changes. For edit controls, fires on every keystroke. For combos, fires when the selection changes. |
Focus Event Examples
--- OnEnter: highlight the active field ---
oEdit:OnEnter := { || ;
oEdit:nBackColor := CLR_YELLOW, ;
oEdit:Refresh() ;
}
--- OnExit: validate email format ---
oEmailEdit:OnExit := { || ;
local cVal := oEmailEdit:GetValue()
if "@" $ cVal .and. "." $ cVal
return .T.
else
MsgStop( "Invalid email address" )
return .F. /// keep focus
endif ;
}
--- OnChange: live character counter ---
oMemo:OnChange := { || ;
oStatusLabel:SetText( ;
LTrim( Str( Len( oMemo:GetValue() ) ) ) + " characters" ;
) ;
}
| Event | Parameters | Available Controls | Description |
OnCreate |
none |
Form |
Fires when the form object is first created, before any controls are added. Use this for early initialization, loading configuration, or setting up data connections. |
OnInit |
none |
Form |
Fires after all controls have been created and the form is about to be displayed. This is the ideal place for final setup: populating lists, setting default values, positioning. |
OnShow |
none |
Form |
Fires each time the form becomes visible. Fires on initial display and again if the form was hidden and shown again. |
OnHide |
none |
Form |
Fires when the form is hidden (via Hide() or minimized). Use to pause timers or stop background tasks. |
OnActivate |
none |
Form |
Fires when the form gains focus (becomes the active window). Distinct from OnShow: a form can be shown but not activated if another window is on top. |
OnDeactivate |
none |
Form |
Fires when the form loses focus to another window in the same application. |
OnActivateApp |
lActive |
Form |
Fires when the entire application gains or loses focus at the OS level. lActive is .T. when the app is foregrounded, .F. when backgrounded. |
OnCloseQuery |
@lCanClose |
Form |
Fires before the form closes. Set lCanClose to .F. to cancel the close operation. Use for "Save changes?" prompts. |
OnClose |
none |
Form |
Fires when the form is closing (after OnCloseQuery allows it). Use for cleanup: closing database connections, saving state, releasing resources. |
OnDestroy |
none |
Form, all controls |
Fires when the control/form is being destroyed and memory is about to be freed. Last chance for cleanup. |
--- OnCreate: early initialization ---
oForm:OnCreate := { || ;
LoadConfig( "app.ini" ), ;
oForm:cTitle := "My App v" + GetVersion() ;
}
--- OnInit: populate controls after everything is created ---
oForm:OnInit := { || ;
oComboBox:aItems := { "Option A", "Option B", "Option C" }, ;
oComboBox:nItemIndex := 0, ;
LoadRecentFiles() ;
}
--- OnCloseQuery: prompt to save changes ---
oForm:OnCloseQuery := { | @lCanClose | ;
if lDataModified
local nResp := MsgYesNo( "Save changes before closing?" )
if nResp == 6 /// IDYES
SaveData()
elseif nResp == 2 /// IDCANCEL
lCanClose := .F.
return
endif
endif, ;
lCanClose := .T. ;
}
--- OnClose: cleanup resources ---
oForm:OnClose := { || ;
oDb:Close(), ;
oTimer:lRunning := .F., ;
SaveWindowState( oForm ) ;
}
Timer Events
| Event | Parameters | Available Controls | Description |
OnTimer |
none |
Timer |
Fires at regular intervals set by the Timer's nInterval property (in milliseconds). Use for periodic tasks: updating a clock, polling a server, animating, auto-saving. |
Timer Event Example
--- OnTimer: update a clock label every second ---
oTimer:nInterval := 1000 /// 1 second
oTimer:OnTimer := { || ;
oClockLabel:SetText( Time() ) ;
}
oTimer:lRunning := .T. /// start the timer
--- OnTimer: auto-save every 5 minutes ---
oAutoSave:nInterval := 300000 /// 5 minutes
oAutoSave:OnTimer := { || ;
if lDataModified
AutoSave()
endif ;
}
Paint and Resize Events
| Event | Parameters | Available Controls | Description |
OnPaint |
none |
PaintBox, Form, Panel, Shape, all visual controls |
Fires when the control needs to be redrawn. Use with PaintBox for custom GDI/Cairo drawing. Access the device context via platform-specific drawing functions. |
OnResize |
nNewWidth, nNewHeight |
Form, Panel, ScrollBox |
Fires when the container is resized. Parameters provide the new dimensions. Use for repositioning child controls or recalculating layout. |
Paint and Resize Examples
--- OnPaint: custom drawing on a PaintBox ---
oPaintBox:OnPaint := { || ;
DrawLine( 0, 0, oPaintBox:nWidth, oPaintBox:nHeight ), ;
DrawRect( 10, 10, 50, 50, CLR_BLUE ), ;
DrawText( 70, 10, "Custom Drawing", CLR_BLACK ) ;
}
--- OnResize: keep controls proportionally positioned ---
oForm:OnResize := { | nW, nH | ;
oGrid:nWidth := nW - 40, ;
oGrid:nHeight := nH - 100, ;
oBtn:nTop := nH - 50, ;
oBtn:nLeft := nW - 160 ;
}
Complete Event Summary Table
| Event | Category | Primary Controls |
OnClick | Mouse | Button, ListBox, TreeView, MenuItem, Image |
OnDblClick | Mouse | ListBox, TreeView, StringGrid, Form |
OnMouseDown | Mouse | All visual controls |
OnMouseUp | Mouse | All visual controls |
OnMouseMove | Mouse | All visual controls |
OnMouseWheel | Mouse | All visual controls |
OnKeyDown | Keyboard | All focusable controls |
OnKeyUp | Keyboard | All focusable controls |
OnKeyPress | Keyboard | Edit, Memo, MaskEdit, ComboBox |
OnChange | Value | Edit, Memo, ComboBox, CheckBox, TrackBar |
OnEnter | Focus | All focusable controls |
OnExit | Focus | All focusable controls |
OnCreate | Lifecycle | Form |
OnInit | Lifecycle | Form |
OnShow | Lifecycle | Form |
OnHide | Lifecycle | Form |
OnActivate | Lifecycle | Form |
OnDeactivate | Lifecycle | Form |
OnActivateApp | Lifecycle | Form |
OnCloseQuery | Lifecycle | Form |
OnClose | Lifecycle | Form |
OnDestroy | Lifecycle | All controls |
OnTimer | Timer | Timer |
OnPaint | Drawing | PaintBox, Shape, Form, Panel |
OnResize | Layout | Form, Panel, ScrollBox |
Event firing order
When a user clicks a button, the event order is: OnMouseDown → OnMouseUp → OnClick.
For keyboard input: OnKeyDown → OnKeyPress → OnKeyUp.
Understanding this order helps you choose the right event for your use case.