Table of Contents

Events

TTMSFNCBloxControl raises events across the whole interaction and rendering lifecycle, so an application can react to what the user does, track changes, and draw its own overlays. This chapter groups the events by purpose and shows worked handlers for the three most common needs: responding to selection, tracking modifications, and custom drawing.

What you can hook into

Group Events
Element interaction OnElementClick, OnElementDblClick, OnElementMouseDown, OnElementMouseUp, OnElementMouseMove, OnElementSelect, OnElementUnselect, OnElementInsert, OnElementRemove, OnElementResizing
Selection & changes OnSelectionChange, OnModified, OnAfterMove, OnAfterResize, OnAfterUndo, OnAfterRedo
Rendering OnBeforeRender, OnAfterRender, OnAfterBackgroundRender, OnElementPainting, OnElementPainted
Zoom & registration OnZoomChanged, OnRegisterElements
In-place editing OnGetInplaceEditorClass, OnSetInplaceEditorData, OnSetInplaceEditorElementData, OnSetInplaceEditorSize

Responding to selection

OnElementClick fires for a clicked element (Element is the one clicked), and OnSelectionChange fires whenever the selection set changes. Use them to drive a property inspector or status bar:

procedure TForm1.BloxControl1ElementClick(Sender: TObject;
  Element: TTMSFNCBloxElement);
begin
  if Element is TTMSFNCBloxBlock then
    StatusLabel.Text := 'Block: ' + TTMSFNCBloxBlock(Element).Text
  else if Element is TTMSFNCBloxLine then
    StatusLabel.Text := 'Line selected';
end;

procedure TForm1.BloxControl1SelectionChange(Sender: TObject);
begin
  StatusLabel.Text := Format('%d element(s) selected',
    [BloxControl1.Presenter.SelectedCount]);
end;

Tracking modifications

OnModified fires on any change to the diagram; OnElementInsert and OnElementRemove report structural edits. Together they maintain a "dirty" flag so you can prompt before closing:

procedure TForm1.BloxControl1Modified(Sender: TObject);
begin
  FDiagramDirty := True;
  SaveButton.Enabled := True;
end;

procedure TForm1.BloxControl1ElementInsert(Sender: TObject;
  Element: TTMSFNCBloxElement);
begin
  FDiagramDirty := True;
  StatusLabel.Text := Format('Inserted (%d elements)',
    [BloxControl1.Blox.ElementCount]);
end;

procedure TForm1.BloxControl1ElementRemove(Sender: TObject;
  Element: TTMSFNCBloxElement);
begin
  FDiagramDirty := True;
end;

Custom drawing

OnAfterRender fires once all elements are painted, giving you the renderer's canvas to draw an overlay (watermark, guide region, annotation). OnElementPainting lets you take over drawing of an individual element (set Painted := True to suppress the default paint).

procedure TForm1.BloxControl1AfterRender(Sender: TObject;
  Renderer: TTMSFNCBloxRenderer);
begin
  { Renderer.Canvas draws in blox coordinates; Pen/Brush can be customised first. }
  Renderer.Canvas.DrawRectangle(0, 0, 200, 150);
end;

Putting it together

A real editor usually wires several events at once. This handler set combines selection feedback, modification tracking, and a live element count — keeping a status bar and a dirty flag in sync as the user edits:

procedure TForm1.WireDiagramEvents;
begin
  BloxControl1.OnSelectionChange := DiagramSelectionChange;
  BloxControl1.OnModified := DiagramModified;
end;

procedure TForm1.DiagramSelectionChange(Sender: TObject);
begin
  StatusLabel.Text := Format('%d of %d element(s) selected',
    [BloxControl1.Presenter.SelectedCount, BloxControl1.Blox.ElementCount]);
end;

procedure TForm1.DiagramModified(Sender: TObject);
begin
  FDiagramDirty := True;
  SaveButton.Enabled := True;
end;

Pitfalls

  • Element mouse events carry blox coordinates in X, Y — convert with Presenter.ClientToCanvas / CanvasToClient if you need pixels.
  • OnModified can fire frequently during a drag; debounce expensive work (e.g. autosave) rather than running it on every call.
  • OnElementPainting runs in the render loop. Keep handlers cheap and avoid modifying the element tree from inside them.

See also