Record types, another example of a complex type, declare groupings of variables known as fields. Just as with enumerations and arrays, the names of record types should start with the letter "T." Records are especially useful when describing the properties of objects (like color, length, width, height, etc.). Records also provide a logical grouping mechanism that helps clarify the meaning of code. The following example code demonstrates declaring record types and variable instances of record types:
type
  TPoint = record
    X,Y : Integer;
  end;

var
  Point : TPoint;
The fields X and Y are now variables contained inside the variable Point. (Record types can also be declared as constants which means the fields contained inside are then constants, but this is not discussed in this section). Fields of records are accessed using the dot (.) operator:
var
  Point1 : TPoint;
  Point2 : TPoint;
begin
  Point1.X := 0;
  Point1.Y := 0;
  Point2.X := 10;
  Point2.Y := -10;
end.
Records can also be included inside other records:
type
  TLineStyle = (lsSolid,lsDashed,lsDotted);
  TLineRec = record
    Start,Stop : TPoint;
    Width : Integer;
    Style : TLineStyle;
    Color : Integer;
  end;

type
  TCircleRec = record
    Pos : TPoint;
    Radius : Integer;
    Color : Integer;
  end;
A very helpful use of records can be as elements in arrays. Say we have a series of graphical objects to draw that consist of lines and circles. Since lines and circles have their own properties such as position and color, we would normally have to keep a separate array for line position, line color, circle position, circle color, etc. Records, however, allow us to group the properties first and then declare an array of a particular record:
type
  TLineArray = array of TLineRec;
  TCircleArray = array of TCircleRec;

var
  K : Integer;
  Lines : TLineArray;
  Circles : TCircleArray;
begin
  SetLength(Lines,2);
  SetLength(Circles,5);

  {Set the properties of the first line}
  Lines[0].Start.X := 10;
  Lines[0].Start.Y := -10;
  Lines[0].Stop.X := 20;
  Lines[0].Stop.Y := 35;
  Lines[0].Width := 1;
  Lines[0].Style := lsSolid;
  Lines[0].Color := 255; // Happens to be the color red, we'll explain later

  {Set the properties of the second line}
  Lines[1].Start.X := 10;
  Lines[1].Start.Y := -10;
  Lines[1].Stop.X := 20;
  Lines[1].Stop.Y := 35;
  Lines[1].Width := 1;
  Lines[1].Style := lsSolid;
  Lines[1].Color := 65535; // The color yellow


  {Set the properties of the circles randomly with a loop}
  for K := 0 to High(Circles) do
  begin
    Circles[K].Pos.X := Random(100)-50;
    Circles[K].Pos.Y := Random(100)-50;
    Circles[K].Radius := Random(50);
    Circles[K].Color := Random(255); // Some random shade of red
  end;

  Readln;
end.
Note that in the above code we omit the subrange bounds for an array which makes it a dynamic array. The size of dynamic arrays must be set with the SetLength function.  Notice also how we assign values to the properties. Because Lines is an array we first have to access the record element using Lines[0] before we can use the dot operator as in Lines[0].Start.X. Of course, in some ways the way we declare properties for Lines[0] and Lines[1] defeats the purpose of an array. We could have declared Line0 and Line1 as variables and then set those properties. The power of having an array is that we can loop through all the elements and set properties. This is demonstrated in the for loop with Circles. The loop runs from 0 to High(Circles). High is a predefined function which returns the higest index of a dynamic array. There is also a function called Low that returns the Lowest index, but for dynamic arrays we already know this is 0. We use the for loop control variable K to reference each element and we set the properties of the circles randomly.

Of course, if we run this program, nothing happens. We may have defined lines and circles, but we have not implemented the drawing of these objects to the screen. So records simply group data together, but how that data is used depends on how the drawing algorithms of the program are written.

As with arrays, records should always be passed to procedures and functions by reference. In other words you should always use const (if you do not intend to change the argument you are passing) or var (if you want the changes to the argument to be reflected after the subroutine returns).
procedure DrawCircle1(const Circle : TCircleRec);
begin
  // Some circle drawing code here
  Circle.Pos.X := 0; // The compiler will not allow this
end;

procedure DrawCircle2(var Circle : TCircleRec);
begin
  // Some circle drawing code here
  Circle.Pos.X := 0; // The compiler will allow this
end;