Delphi Initialize Record
This question has come up in the newsgroups reasonably frequently eventhough there is a help topic all about it filed in the index under theentry “record constants,” so besure to consult the help as well.
Nov 7, 2018 - Custom Managed Records Coming in Delphi 10.3. Code to be executed when records are first initialized, disposed from memory and copied. Understanding Delphi Class (and Record) Helpers - ThoughtCo Thoughtco.com A feature of the Delphi language added some years ago (way back in in Delphi 2005) called 'Class Helpers' is designed to let you add new functionality to an existing class (or a record) by introducing new methods to the class (record).
Let us begin with an example from the Delphi source code. Consider theUtilWindowClass
variable from theClasses
unit. Delphi uses the variable in implementing theAllocateHWnd
function. Since most of the fields are staticand known in advance, the variable is initialized where it is declared,as shown in Listing 1. Only the hInstance
fieldgets set at run time.
Listing 1
A record variable with initialization from Classes.pas
var
UtilWindowClass: TWndClass = (
style: 0;
lpfnWndProc: @DefWindowProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'TPUtilWindow');
Note that the entire value is wrapped in parentheses, and each fieldname precedes a constant expression. Semicolons separate the pairs ofnames and values.
The fields must occur in the same order in which they appear in therecord type’s declaration. Any field may be omitted, but allsubsequent fields must also be omitted. Any omitted field is initializedwith the default value for itstype.
Arrays of records
To initialize an array constant, the elements’ values need toappear in a comma-separated list within a set of parentheses. Combinethis with the syntax above for record constants to reveal that arrays ofrecords should be initialized with comma-separated lists of parenthesizedsemicolon-separated lists of field: value pairs.
For example, suppose a simple command interpreter has a handfulbuilt-in commands, each implemented with a different function. Theprogram could use a record type to associate a command name with ahandler function and a short description of the command, and shownbelow.
Listing 2
Type declarations for a simple command interpreter
type
TArgArray = array of WideString;
TCommandProcessor = procedure(const Arguments: TArgArray);
TCommand = record
Command: WideString;
Processor: TCommandProcessor;
Description: PResStringRec;
end;
The program could then use an array to keep a list of all the built-infunctions the program recognizes. As with all array constants, the arraymust have constant dimensions; Delphi does not allow dynamic-arrayconstants other than nil
.
Listing 3
An array of built-in commands for a simple command interpreter
Delphi Initialize Recorder
// Declarations of command handlers
procedure DoHelp(const Args: TArgArray); forward;
procedure DoExit(const Args: TArgArray); forward;
procedure DoChdir(const Args: TArgArray); forward;
procedure DoHistory(const Args: TArgArray); forward;
resourcestring
// Help messages
RsHelp = 'Print this help message';
RsExit = 'Quit the command interpreter';
RsChdir = 'Change the working directory';
RsHistory = 'Display the command history';
const
{$TYPEDADDRESS OFF}
Builtins: array[0..4] of TCommand = (
(Command: 'help'; Processor: DoHelp; Description: @RsHelp),
(Command: 'exit'; Processor: DoExit; Description: @RsExit),
(Command: 'cd'; Processor: DoChdir; Description: @RsChdir),
(Command: 'chdir'; Processor: DoChdir; Description: @RsChdir),
(Command: 'history'; Processor: DoHistory; Description: @RsHistory)
);
{$TYPEDADDRESS ON}