_DLiteGridTurboCtrlEvents 33 events fired by the LiteGrid Turbo ActiveX control
In registered mode events arrive natively, wired by naming convention. In
registration-free mode WithEvents is unavailable — it needs early
binding against a registered type library — so you attach a callback object instead and
32 of the 33 events are delivered to it, cancellable ones included. See
Receiving Events Registration-Free below.
Name handler subs as LiteGrid1_EventName (matching the control's Name property). Events use the design-time OCX naming convention — no WithEvents needed.
Events with a Cancel As Boolean parameter are cancelable — set Cancel = True to block the action.
Receiving Events Registration-Free
Registration-free deployment cannot provide early binding, so WithEvents is unavailable.
Instead you give the grid an object that exposes a public OnGridEvent method and it calls you
back. One signature serves every event.
' Attach once, after the grid exists. The second argument is a caller-chosen
' id echoed back on every callback — useful when one handler serves several grids.
m_Grid.SetEventCallback Me, 1
' The handler. Name must be exactly OnGridEvent, and it must be Public:
' the grid resolves it by name when SetEventCallback is called.
Public Sub OnGridEvent(ByVal gridId As Long, ByVal eventId As Long, _
ByVal a1 As Variant, ByVal a2 As Variant, _
ByVal a3 As Variant, ByVal a4 As Variant, _
ByVal a5 As Variant, ByVal a6 As Variant, _
ByRef Cancel As Boolean)
Select Case eventId
Case 1 ' ColumnClick — a1 = column index
Debug.Print "header " & a1
Case 12 ' BeforeRowDelete — cancellable
If MsgBox("Delete?", vbYesNo) = vbNo Then Cancel = True
End Select
End Sub
Reading the arguments: the parameter count is always nine, whatever the
event. eventId tells you which event fired — the id is shown against every event on this
page. a1…a6 carry that event's own arguments in the order documented for it;
unused slots arrive as Empty. Cancel only has meaning for the cancellable events,
and setting it True vetoes the operation. Setting it False can never
un-cancel a veto another subscriber already applied.
BeforeCellPaint (event 26) hands the handler a live drawing context valid only inside
the paint loop, so it is not bridgeable and cannot be enabled. Data-driven appearance is covered by
SetCellColor, SetCellFontStyle, SetCellIcon and
AddFormatRule; genuine custom painting requires registered mode. Every other event —
32 of 33 — is available.
Two independent delivery routes exist. The direct route calls a callback object;
the macro route calls a named macro through the host's Application.Run.
They can be attached at the same time and cleared separately.
| Member | Parameters | Returns | Description |
|---|---|---|---|
| SetEventCallback | callbackObject As Object, gridId As Long | Attach the direct route. The object must expose a public OnGridEvent. Validation is all-or-nothing — a failed call leaves any existing callback installed. | |
| ClearEventCallbackObject | Detach the direct route only, leaving the macro route alone. Idempotent. | ||
| SetEventCallbackMacro | hostApplication As Object, macroName As String, gridId As Long | Attach the macro route, e.g. Application, "Module1.OnGridEvent". The name is trimmed. Whether the macro exists is only discovered on first fire. | |
| ClearEventCallbackMacro | Detach the macro route only, leaving the direct route alone. Idempotent. | ||
| ClearEventCallback | Detach both routes. Does not change which events are enabled. Idempotent. | ||
| SetEventCallbackEnabled | eventId As Long, enabled As Boolean | Turn delivery of one event on or off for the bridge. Never affects registered-mode WithEvents delivery. Event 26 cannot be enabled. | |
| GetEventCallbackEnabled | eventId As Long | Boolean | Whether that event currently reaches the bridge. Querying event 26 returns False rather than failing. |
| GetEventCallbackInfo | String | Diagnostics as JSON: per-route attach state, invoke and failure counts, the last failure, and the list of events not being delivered. |
The macro route
Useful when the handler belongs in a standard module rather than on a form. The macro takes the same
nine arguments, but cancellation comes back through the return value, so it is a
Function, not a Sub:
' Attach: pass the host Application and a public macro name
m_Grid.SetEventCallbackMacro Application, "Module1.OnGridEvent", 1
' In Module1 — note: Function, and the last argument is ByVal
Public Function OnGridEvent(ByVal gridId As Long, ByVal eventId As Long, _
ByVal a1 As Variant, ByVal a2 As Variant, _
ByVal a3 As Variant, ByVal a4 As Variant, _
ByVal a5 As Variant, ByVal a6 As Variant, _
ByVal cancelSoFar As Boolean) As Boolean
' cancelSoFar = True means someone already vetoed this operation.
' Return True to cancel. Returning False never un-cancels.
If eventId = 12 Then OnGridEvent = True
End Function
The macro must accept exactly nine parameters. A mismatch surfaces
as a parameter-count error in GetEventCallbackInfo's last-failure block, not as an error on
the LiteGrid Turbo call that triggered it — a handler that fails never propagates its failure back into
your grid operation.
Delivery Defaults
Most events reach the bridge as soon as you attach a callback. Six high-frequency ones do not — they fire often enough to matter for performance, so they are opt-in.
| Group | Count | Delivered by default | Events |
|---|---|---|---|
| Notification | 18 | Yes | ColumnClick (1), ItemClick (2), ItemDoubleClick (3), AfterCellEdit (6), AfterSort (8), ContextMenu (9), KeyDown (10), DataLoaded (11), IconClick (14), FilterChanged (15), CheckboxToggle (16), AfterPaste (18), ValidationFailed (19), ColumnReorder (20), ButtonClick (21), CellValueChanged (25), DataChanged (27), NeedRows (31) |
| Cancellable | 8 | Yes | BeforeCellEdit (5), BeforeSort (7), BeforeRowDelete (12), BeforePaste (17), BeforeContextMenu (29), BeforeHeaderMenu (30), SortRequested (32), FilterRequested (33) |
| High-frequency | 6 | No — opt in | SelectionChanged (4), ScrollChanged (13), CellHover (22), CellMouseEnter (23), CellMouseLeave (24), LoadProgress (28) |
| Not bridgeable | 1 | Never | BeforeCellPaint (26) — registered mode only |
' Opt in to a high-frequency event
m_Grid.SetEventCallbackEnabled 4, True ' SelectionChanged
' Turn a noisy one back off
m_Grid.SetEventCallbackEnabled 13, False ' ScrollChanged
' Check state, and see everything currently NOT being delivered
Debug.Print m_Grid.GetEventCallbackEnabled(4)
Debug.Print m_Grid.GetEventCallbackInfo()
Enable state belongs to the control, not to the callback. It survives
detaching and re-attaching a callback, switching to a different callback object, and the form recreating the
control's window. Both routes share one set. Disabling an event for the bridge never silences a
registered-mode WithEvents subscriber.
| Event | Parameters | Description |
|---|---|---|
| BeforeCellEdit Cancelable | rowIndex As Long, columnIndex As Long, Cancel As Boolean | Before cell enters edit mode. Set Cancel = True to prevent editing. |
| AfterCellEdit | rowIndex As Long, columnIndex As Long, oldValue As String, newValue As String | After cell edit is committed. |
| CellValueChanged | rowIndex As Long, columnIndex As Long, oldValue As Variant, newValue As Variant | User committed a cell edit, or toggled a checkbox cell by clicking.
Not raised by programmatic writes — SetCellValue,
AddRow and the LoadFrom… methods change data silently.
Use it for edit auditing, not as a general data-change hook; for that see
DataChanged. |
| ValidationFailed | rowIndex As Long, columnIndex As Long, message As String | Cell edit failed validation. |
Per-Event Usage
' BeforeCellEdit — prevent editing specific columns
Private Sub LiteGrid1_BeforeCellEdit(ByVal rowIndex As Long, ByVal columnIndex As Long, _
Cancel As Boolean)
If columnIndex = 0 Then Cancel = True ' Column 0 is read-only
End Sub
' AfterCellEdit — cell edit committed
Private Sub LiteGrid1_AfterCellEdit(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal oldValue As String, ByVal newValue As String)
Debug.Print "Changed: " & oldValue & " -> " & newValue
End Sub
' CellValueChanged — any value change (edit or programmatic)
Private Sub LiteGrid1_CellValueChanged(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal oldValue As Variant, ByVal newValue As Variant)
Debug.Print "Cell(" & rowIndex & "," & columnIndex & "): " & oldValue & " -> " & newValue
End Sub
' ValidationFailed — validation error
Private Sub LiteGrid1_ValidationFailed(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal message As String)
MsgBox "Validation error in row " & rowIndex & ": " & message
End Sub
| Event | Parameters | Description |
|---|---|---|
| BeforeSort Cancelable | columnIndex As Long, Cancel As Boolean | Before sort begins. Set Cancel = True to prevent sorting. |
| AfterSort | columnIndex As Long, sortOrder As Long | After sort completes. sortOrder: 0=Ascending, 1=Descending. |
| FilterChanged | filteredRowCount As Long | After any filter is applied or cleared. |
Per-Event Usage
' BeforeSort — prevent sorting specific columns
Private Sub LiteGrid1_BeforeSort(ByVal columnIndex As Long, Cancel As Boolean)
If columnIndex = 5 Then Cancel = True ' Don't sort column 5
End Sub
' AfterSort — sort completed
Private Sub LiteGrid1_AfterSort(ByVal columnIndex As Long, ByVal sortOrder As Long)
Debug.Print "Sorted column " & columnIndex & " " & IIf(sortOrder = 0, "ASC", "DESC")
End Sub
' FilterChanged — filter applied or cleared
Private Sub LiteGrid1_FilterChanged(ByVal filteredRowCount As Long)
lblStatus.Caption = filteredRowCount & " rows visible"
End Sub
Raised only when DataMode = 1. In Embedded mode these never fire and the
corresponding operations behave exactly as they always have.
| Event | Parameters | Description |
|---|---|---|
| NeedRows | requestId As Long, generation As Long, firstRow As Long, lastRow As Long | The grid needs rows it does not have. Answer by calling SupplyRows — from inside the handler is supported and needs no timer, no DoEvents and no thread. Never raised during painting. |
| SortRequested Cancelable | colIndex As Long, direction As Long, handled As Boolean | The host is asked to re-order the data. direction: 0=Ascending, 1=Descending. ClearSort reports colIndex = -1. |
| FilterRequested Cancelable | colIndex As Long, mode As Long, pattern As String, handled As Boolean | The host is asked to filter the data. mode carries a real FilterMode where one exists, else a negative sentinel (see below). |
Ownership rule
In Virtual Mode the host owns the data; the grid owns only a cache of it. The grid
therefore cannot sort or filter on the host's behalf — it can only ask. Both events are
seeded handled = False and the host writes True to accept:
handled = False(or no sink attached) — the operation did not happen. No sort indicator moves, no filter rule is stored, the generation is not bumped and the cache is untouched. The originating COM call returnsLG_E_VIRTUAL_NOT_HANDLED(0x80040202) andunhandledRequestCountadvances by one. On a UI path (header click, filter dropdown) there is no HRESULT to return, so the action is simply a no-op with the same counter bump.handled = True— the host has accepted and will re-supply the data in the new order. The grid updates its indicator state, bumps the generation, invalidates and returnsS_OK. The next paint raisesNeedRowscarrying the new generation.
Requests are not fetches. Neither event issues a NeedRows
synchronously, and painting never raises either event. Argument validation happens before
the host is asked, so an out-of-range column returns E_INVALIDARG and fires nothing —
handled = False can never be confused with "your arguments were invalid". Over the bridge both
arrive through OnGridEvent with the trailing Cancel parameter carrying
handled, merged raise-only: a handler can acknowledge, but nothing it writes
can un-acknowledge.
FilterRequested.mode sentinels
Operations with no natural FilterMode use negative sentinels, which can never collide
because every real FilterMode is >= 0.
| Sentinel | Value | Raised by | colIndex | pattern |
|---|---|---|---|---|
| Clear | -1 | ClearColumnFilter / ClearAllFilters | the column, or -1 for all | "" |
| Replace state | -2 | SetFilterState / LoadFilterPreset | -1 | the whole JSON document, verbatim |
| Value list | -10 | SetColumnValueListFilter | the column | "<includeBlanks 0|1>|<comma-joined values>" |
SetColumnNumericFilter sends the threshold as text;
SetColumnNumericFilterRange sends "min|max" with mode 9 (Between).
Value-list values are upper-cased and joined in unspecified order — treat the payload
as a set, not a sequence.
Per-Event Usage
' NeedRows — the grid is asking for rows; answer it synchronously
Private Sub Grid_NeedRows(ByVal requestId As Long, ByVal generation As Long, _
ByVal firstRow As Long, ByVal lastRow As Long)
Dim data() As Variant
data = MyData.GetPage(firstRow, lastRow) ' 2-D Variant array, any lower bound
Grid.SupplyRows requestId, generation, firstRow, data
End Sub
' SortRequested — the host owns the ordering
Private Sub Grid_SortRequested(ByVal colIndex As Long, ByVal direction As Long, _
handled As Boolean)
If colIndex = -1 Then
MyData.ClearSort ' ClearSort convention
Else
MyData.SortBy colIndex, (direction = 0)
End If
handled = True ' accepted; the grid will re-ask via NeedRows
End Sub
' FilterRequested — decline what you cannot honour
Private Sub Grid_FilterRequested(ByVal colIndex As Long, ByVal mode As Long, _
ByVal pattern As String, handled As Boolean)
Select Case mode
Case -1: MyData.ClearFilter colIndex ' -1 = clear
Case -2: handled = False: Exit Sub ' decline what you cannot honour
Case Else: MyData.Filter colIndex, mode, pattern
End Select
handled = True
End Sub
| Event | Parameters | Description |
|---|---|---|
| ContextMenu | rowIndex As Long, columnIndex As Long, x As Long, y As Long | Right-click on grid. rowIndex = -1 if header. |
| CellHover | rowIndex As Long, columnIndex As Long | Mouse hovering over a cell. |
| CellMouseEnter | rowIndex As Long, columnIndex As Long | Mouse entered a cell. |
| CellMouseLeave | rowIndex As Long, columnIndex As Long | Mouse left a cell. |
Per-Event Usage
' ContextMenu — right-click
Private Sub LiteGrid1_ContextMenu(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal x As Long, ByVal y As Long)
' Show custom context menu at x, y
End Sub
' CellHover — mouse hovering over cell
Private Sub LiteGrid1_CellHover(ByVal rowIndex As Long, ByVal columnIndex As Long)
lblHover.Caption = "Hover: (" & rowIndex & ", " & columnIndex & ")"
End Sub
' CellMouseEnter / CellMouseLeave — track mouse movement
Private Sub LiteGrid1_CellMouseEnter(ByVal rowIndex As Long, ByVal columnIndex As Long)
lblHover.Caption = "Hovering: (" & rowIndex & ", " & columnIndex & ")"
End Sub
Private Sub LiteGrid1_CellMouseLeave(ByVal rowIndex As Long, ByVal columnIndex As Long)
lblHover.Caption = ""
End Sub
| Event | Parameters | Description |
|---|---|---|
| KeyDown | keyCode As Long, shift As Long | Key pressed while grid has focus. |
Per-Event Usage
' KeyDown — handle keyboard shortcuts
Private Sub LiteGrid1_KeyDown(ByVal keyCode As Long, ByVal shift As Long)
If keyCode = vbKeyDelete Then LiteGrid1.DeleteSelectedRows
End Sub
| Event | Parameters | Description |
|---|---|---|
| CheckboxToggle | rowIndex As Long, columnIndex As Long, checked As Boolean | Checkbox cell toggled. |
| ButtonClick | rowIndex As Long, columnIndex As Long | Button-renderer cell clicked. |
| IconClick | rowIndex As Long, columnIndex As Long, iconId As Long | Cell icon clicked. |
Per-Event Usage
' CheckboxToggle — checkbox state changed
Private Sub LiteGrid1_CheckboxToggle(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal checked As Boolean)
Debug.Print "Row " & rowIndex & " checked: " & checked
End Sub
' ButtonClick — button cell clicked
Private Sub LiteGrid1_ButtonClick(ByVal rowIndex As Long, ByVal columnIndex As Long)
MsgBox "Button clicked at row " & rowIndex
End Sub
' IconClick — cell icon clicked
Private Sub LiteGrid1_IconClick(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal iconId As Long)
Debug.Print "Icon " & iconId & " clicked at row " & rowIndex
End Sub
| Event | Parameters | Description |
|---|---|---|
| BeforePaste Cancelable | rowIndex As Long, columnIndex As Long, rowCount As Long, colCount As Long, Cancel As Boolean | Before clipboard paste. Set Cancel = True to prevent paste. |
| AfterPaste | rowIndex As Long, columnIndex As Long, rowCount As Long, colCount As Long | After clipboard paste completes. |
Per-Event Usage
' BeforePaste — validate paste size
Private Sub LiteGrid1_BeforePaste(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal rowCount As Long, ByVal colCount As Long, Cancel As Boolean)
If rowCount > 1000 Then
MsgBox "Cannot paste more than 1000 rows"
Cancel = True
End If
End Sub
' AfterPaste — paste completed
Private Sub LiteGrid1_AfterPaste(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal rowCount As Long, ByVal colCount As Long)
Debug.Print "Pasted " & rowCount & " rows at (" & rowIndex & "," & columnIndex & ")"
End Sub
| Event | Parameters | Description |
|---|---|---|
| ColumnReorder | fromIndex As Long, toIndex As Long | Column dragged to a new position. |
| ScrollChanged | scrollTop As Long, scrollLeft As Long | Scroll position changed. |
Per-Event Usage
' ColumnReorder — column dragged to new position
Private Sub LiteGrid1_ColumnReorder(ByVal fromIndex As Long, ByVal toIndex As Long)
Debug.Print "Column moved from " & fromIndex & " to " & toIndex
End Sub
' ScrollChanged — use for lazy-loading data
Private Sub LiteGrid1_ScrollChanged(ByVal scrollTop As Long, ByVal scrollLeft As Long)
' Lazy-load data as user scrolls
End Sub
| Event | Parameters | Description |
|---|---|---|
| BeforeRowDelete Cancelable | rowIndex As Long, Cancel As Boolean | Before row deletion. Set Cancel = True to prevent deletion. |
Per-Event Usage
' BeforeRowDelete — confirm before deleting
Private Sub LiteGrid1_BeforeRowDelete(ByVal rowIndex As Long, Cancel As Boolean)
If MsgBox("Delete row?", vbYesNo) = vbNo Then Cancel = True
End Sub
| Event | Parameters | Description |
|---|---|---|
| BeforeCellPaint Cancelable | rowIndex As Long, columnIndex As Long, hdc As Long, Cancel As Boolean | Before each cell is painted. Requires EnableBeforeCellPaint = True. Set Cancel = True to skip default painting. |
You must set EnableBeforeCellPaint = True on the grid control before this event will fire. This is disabled by default for performance.
Per-Event Usage
' BeforeCellPaint — custom cell rendering
Private Sub LiteGrid1_BeforeCellPaint(ByVal rowIndex As Long, ByVal columnIndex As Long, _
ByVal hdc As Long, Cancel As Boolean)
' Custom paint logic here using the device context handle
End Sub