_DLiteGridTurboCtrlEvents 33 events fired by the LiteGrid Turbo ActiveX control

Both deployment modes receive events

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.

Tip — registered mode wiring

Name handler subs as LiteGrid1_EventName (matching the control's Name property). Events use the design-time OCX naming convention — no WithEvents needed.

Tip

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.

One event can never be delivered this way

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.

▶ Event Bridge API 8 members

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.

MemberParametersReturnsDescription
SetEventCallbackcallbackObject As Object, gridId As LongAttach the direct route. The object must expose a public OnGridEvent. Validation is all-or-nothing — a failed call leaves any existing callback installed.
ClearEventCallbackObjectDetach the direct route only, leaving the macro route alone. Idempotent.
SetEventCallbackMacrohostApplication As Object, macroName As String, gridId As LongAttach the macro route, e.g. Application, "Module1.OnGridEvent". The name is trimmed. Whether the macro exists is only discovered on first fire.
ClearEventCallbackMacroDetach the macro route only, leaving the direct route alone. Idempotent.
ClearEventCallbackDetach both routes. Does not change which events are enabled. Idempotent.
SetEventCallbackEnabledeventId As Long, enabled As BooleanTurn delivery of one event on or off for the bridge. Never affects registered-mode WithEvents delivery. Event 26 cannot be enabled.
GetEventCallbackEnabledeventId As LongBooleanWhether that event currently reaches the bridge. Querying event 26 returns False rather than failing.
GetEventCallbackInfoStringDiagnostics 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.

GroupCountDelivered by defaultEvents
Notification18Yes 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)
Cancellable8Yes BeforeCellEdit (5), BeforeSort (7), BeforeRowDelete (12), BeforePaste (17), BeforeContextMenu (29), BeforeHeaderMenu (30), SortRequested (32), FilterRequested (33)
High-frequency6No — opt in SelectionChanged (4), ScrollChanged (13), CellHover (22), CellMouseEnter (23), CellMouseLeave (24), LoadProgress (28)
Not bridgeable1Never 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.

See also: Registration-Free Deployment — how to create the grid in the first place.
▶ Core Events 7 events
EventParametersDescription
ColumnClick columnIndex As Long Column header clicked.
ItemClick rowIndex As Long, columnIndex As Long Cell clicked.
ItemDoubleClick rowIndex As Long, columnIndex As Long Cell double-clicked.
SelectionChanged (none) Selection changed (row, cell, or column).
DataLoaded rowCount As Long, columnCount As Long Data loading completed.
DataChanged changeType As Long Grid data modified (add, delete, or edit).
LoadProgress rowsLoaded As Long, totalRows As Long Fires periodically during large LoadFromArray operations.

Per-Event Usage

' ColumnClick — column header clicked
Private Sub LiteGrid1_ColumnClick(ByVal columnIndex As Long)
    LiteGrid1.Sort columnIndex, 0  ' Sort ascending
End Sub

' ItemClick — cell clicked
Private Sub LiteGrid1_ItemClick(ByVal rowIndex As Long, ByVal columnIndex As Long)
    Debug.Print "Clicked: " & LiteGrid1.GetCellValue(rowIndex, columnIndex)
End Sub

' ItemDoubleClick — cell double-clicked
Private Sub LiteGrid1_ItemDoubleClick(ByVal rowIndex As Long, ByVal columnIndex As Long)
    MsgBox LiteGrid1.GetCellValue(rowIndex, columnIndex)
End Sub

' SelectionChanged — selection changed
Private Sub LiteGrid1_SelectionChanged()
    lblStatus.Caption = "Selected: " & LiteGrid1.GetSelectedRow
End Sub

' DataLoaded — data loading completed
Private Sub LiteGrid1_DataLoaded(ByVal rowCount As Long, ByVal columnCount As Long)
    lblStatus.Caption = rowCount & " rows loaded"
End Sub

' DataChanged — grid data modified
Private Sub LiteGrid1_DataChanged(ByVal changeType As Long)
    Debug.Print "Data changed: type " & changeType
End Sub

' LoadProgress — progress during large loads
Private Sub LiteGrid1_LoadProgress(ByVal rowsLoaded As Long, ByVal totalRows As Long)
    lblProgress.Caption = rowsLoaded & " / " & totalRows
End Sub
▶ Editing Events 4 events
EventParametersDescription
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
▶ Sort & Filter Events 3 events
EventParametersDescription
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
▶ Virtual Mode Events 3 events

Raised only when DataMode = 1. In Embedded mode these never fire and the corresponding operations behave exactly as they always have.

EventParametersDescription
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 returns LG_E_VIRTUAL_NOT_HANDLED (0x80040202) and unhandledRequestCount advances 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 returns S_OK. The next paint raises NeedRows carrying 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.

SentinelValueRaised bycolIndexpattern
Clear-1ClearColumnFilter / ClearAllFiltersthe column, or -1 for all""
Replace state-2SetFilterState / LoadFilterPreset-1the whole JSON document, verbatim
Value list-10SetColumnValueListFilterthe 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
See also: Virtual Data Mode — SupplyRows, InvalidateAllRows and the rest of the host-side API.
▶ Mouse Events 4 events
EventParametersDescription
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
▶ Keyboard Events 1 event
EventParametersDescription
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
▶ Action Events 3 events
EventParametersDescription
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
▶ Clipboard Events 2 events
EventParametersDescription
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
▶ Layout Events 2 events
EventParametersDescription
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
▶ Lifecycle Events 1 event
EventParametersDescription
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
▶ Custom Paint Events 1 event
EventParametersDescription
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.
Note

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
▶ Context Menu Events 2 events

Events fired before the built-in context menus appear, allowing you to suppress the default menu and show a custom one instead.

EventParametersDescription
BeforeContextMenu Cancelable rowIndex As Long, columnIndex As Long, x As Long, y As Long, Cancel As Boolean Fires before the built-in cell right-click menu is shown. Set Cancel = True to suppress the default menu. The x and y parameters are screen coordinates where the menu would appear — use them to position your own custom menu.
BeforeHeaderMenu Cancelable columnIndex As Long, Cancel As Boolean Fires before the built-in header right-click menu is shown. Set Cancel = True to suppress the default menu and show a custom header menu instead.

Remarks: Both events are cancelable. When Cancel is set to True, the built-in menu is suppressed entirely — no popup appears. Use the provided coordinates or column index to display your own context menu. These events only fire when ShowBuiltinContextMenu = True or ShowHeaderMenu = True respectively. If the built-in menus are already disabled, these events do not fire.

Per-Event Usage

' BeforeContextMenu — suppress built-in menu and show a custom one
Private Sub LiteGrid1_BeforeContextMenu(ByVal rowIndex As Long, _
        ByVal columnIndex As Long, ByVal x As Long, _
        ByVal y As Long, Cancel As Boolean)
    Cancel = True  ' Suppress the built-in menu
    ' Show your custom popup menu at (x, y)
    ShowCustomContextMenu x, y, rowIndex, columnIndex
End Sub

' BeforeHeaderMenu — suppress built-in header menu
Private Sub LiteGrid1_BeforeHeaderMenu(ByVal columnIndex As Long, _
        Cancel As Boolean)
    Cancel = True  ' Suppress the built-in header menu
    ' Show a custom header menu with your own sort/filter options
    Debug.Print "Custom header menu for column: " & columnIndex
End Sub