Address Entry and Validation
TTMSFNCIPEdit provides segmented entry for network-style values. Use it when users need to enter IPv4, IPv6, or MAC addresses without manually typing separators in a plain edit control.
IPv4 Entry
Set IPAddressType before assigning values. IPv4Address is available only while the control is in IPv4 mode; using it in another mode raises an exception.

procedure TForm1.ConfigureIPEdit;
begin
TMSFNCIPEdit1.IPAddressType := IPv4;
TMSFNCIPEdit1.IPAddress := '192.168.0.10';
TMSFNCIPEdit1.OnChange := TMSFNCIPEdit1Change;
end;
IPv6 and MAC Modes
Switching IPAddressType resets the fields to the default shape for the selected mode. Use IPAddress for formatted IPv6 or MAC strings, and use IPv6Address when you already have the four-part record value.

procedure TForm1.ConfigureAddressModes;
begin
TMSFNCIPEdit1.IPAddressType := IPv6;
TMSFNCIPEdit1.IPAddress := '0000:0000:0000:0000:0000:0000:0000:0001';
TMSFNCIPEdit2.IPAddressType := MAC;
TMSFNCIPEdit2.IPAddress := '00-11-22-33-44-55';
end;
Change Handling
Handle OnChange when the form needs to validate dependent fields, enable an apply command, or store the current address.
procedure TForm1.TMSFNCIPEdit1Change(Sender: TObject);
begin
Caption := TMSFNCIPEdit1.IPAddress;
end;
Combining address mode, validation, and change handling
The following example drives IPAddressType from a mode selector, checks every
segment on each change, and enables a Save command only for a complete address.
TTMSFNCIPEdit deliberately exposes no validity flag: IPAddress is assembled
from the segment editors on read, so what counts as "complete" is an application
decision — and switching IPAddressType is the only built-in reset, which does
nothing when the mode is unchanged.
procedure TForm1.cbModeChange(Sender: TObject);
const
Modes: array[0..2] of TTMSFNCIPEditType = (IPv4, IPv6, MAC);
begin
{ Assigning a different IPAddressType rebuilds the segments and resets them to
the default shape for that mode. Assigning the mode it already has does
nothing, so clear explicitly when you want a blank editor in one mode. }
TMSFNCIPEdit1.IPAddressType := Modes[cbMode.ItemIndex];
btnSave.Enabled := False;
end;
procedure TForm1.TMSFNCIPEdit1Change(Sender: TObject);
begin
{ There is no IsValid property: IPAddress is assembled from the segment
editors, so completeness is an application-level check. }
btnSave.Enabled := AddressIsComplete(TMSFNCIPEdit1);
lblAddress.Text := TMSFNCIPEdit1.IPAddress;
end;
function TForm1.AddressIsComplete(AEdit: TTMSFNCIPEdit): Boolean;
var
Separator: Char;
Segments: TArray<string>;
Segment: string;
begin
case AEdit.IPAddressType of
IPv4: Separator := '.';
IPv6: Separator := ':';
else
Separator := '-';
end;
Segments := AEdit.IPAddress.Split([Separator]);
Result := Length(Segments) > 0;
for Segment in Segments do
if Trim(Segment) = '' then
Result := False;
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
SaveAddress(TMSFNCIPEdit1.IPAddress);
ResetAddress(TMSFNCIPEdit1);
end;
{ Switching IPAddressType is the only built-in reset, and it does nothing when
the mode is unchanged - so blank the editor by assigning the zero address for
the mode it is already in. }
procedure TForm1.ResetAddress(AEdit: TTMSFNCIPEdit);
begin
case AEdit.IPAddressType of
IPv4: AEdit.IPAddress := '0.0.0.0';
IPv6: AEdit.IPAddress := '0000:0000:0000:0000:0000:0000:0000:0000';
MAC: AEdit.IPAddress := '00-00-00-00-00-00';
end;
end;
Styling
Use IPAddressFont for the field text. Fill and Stroke control the surrounding surface, so align them with adjacent edit controls when the address editor appears inside forms or property panels.
Sizing across DPI scales
The high-DPI support added in 1.0.1.0 means the control handles the two things
it can see for itself: the insets and separator gaps between segments are
computed at paint time from the current scale, and IPAddressFont.Height is
rescaled when the form's DPI changes. Two consequences for calling code.
First, choose the field font size once, in design (96 DPI) units. Deriving it from the display scale at runtime scales it twice — once by you and once by the control — and produces oversized text on a dense monitor.
Second, do not pin the editor's width. The segments are laid out by dividing the
control's own width by the segment count, so a width that just fits eight IPv6
groups at 100% clips them at 200%. Align or anchor the editor so it grows with
its container, and reserve TTMSFNCUtils.GetDPIScale / IsHighDPIScale (unit
FMX.TMSFNCUtils) for decisions the control genuinely cannot make for you.
procedure TForm1.ConfigureIPEditForHighDPI;
begin
{ Set the font size once, in design (96 DPI) units. On a DPI change the
control rescales IPAddressFont itself, so recomputing a size per monitor
would scale it twice. }
TMSFNCIPEdit1.IPAddressFont.Name := 'Segoe UI';
TTMSFNCUtils.SetFontSize(TMSFNCIPEdit1.IPAddressFont, 10);
TMSFNCIPEdit1.IPAddressFont.Color := gcBlack;
{ The segments are laid out by dividing the control's own width, so a fixed
pixel width that just fits eight IPv6 groups at 100% clips them at 200%.
Let the editor grow with its container instead. }
TMSFNCIPEdit1.Align := TAlignLayout.Top;
TMSFNCIPEdit1.Margins.Left := 8;
TMSFNCIPEdit1.Margins.Right := 8;
{ Only branch on the display scale for decisions the control cannot make for
you - here, giving the wider IPv6 layout more room on a dense display. }
if TTMSFNCUtils.IsHighDPIScale(Self) and (TMSFNCIPEdit1.IPAddressType = IPv6) then
TMSFNCIPEdit1.Height := Round(TMSFNCIPEdit1.Height * 1.25);
end;