Reputation: 27276
I was wondering if there's a way to define a type of string or similar in delphi 7 which is intended to be in a particular format, or matching certain specifications? For example, I'd like to define a TSizeString
type which accepts values such as 4x6
or 9x12
or maybe even 2.5x10.75
. It should require the x
as the only deliminator between two numbers. So there should never be anything like x9
or 65
or 2-4
or 4-6x6-2
and not even 4 x 6
.
Just INTEGER + 'x' + INTEGER
or SINGLE + 'x' + SINGLE
.
Similar I guess to how like a TFilename works, standard filenames may look like C:\MyPath\MyFile.txt
or \\Storage\SomeDir\SomeFile.doc
Upvotes: 0
Views: 379
Reputation: 108963
In newer versions of Delphi, advanced records and operator overloading are very handy in this case:
type
TSizeString = record
x, y: single;
public
class operator Implicit(const S: string): TSizeString;
class operator Implicit(const S: TSizeString): string;
end;
implementation
class operator TSizeString.Implicit(const S: string): TSizeString;
var
DelimPos: integer;
begin
DelimPos := Pos('x', S);
if (DelimPos = 0) or (not TryStrToFloat(Copy(S, 1, DelimPos-1), result.X)) or
(not TryStrToFloat(Copy(S, DelimPos + 1), result.y)) then
raise Exception.CreateFmt('Invalid format of size string "%s".', [S]);
end;
class operator TSizeString.Implicit(const S: TSizeString): string;
begin
result := FloatToStr(S.x) + 'x' + FloatToStr(S.y);
end;
Now you can do
procedure TForm1.Button1Click(Sender: TObject);
var
S: TSizeString;
begin
S := '20x30'; // works
ShowMessage(S);
S := 'Hello World!'; // exception raised
ShowMessage(S);
end;
In older versions of Delphi, you simply have to write a class, or create a basic record to hold your size (and then, of course, you can create functions that convert between such records and formatted strings).
Upvotes: 9
Reputation: 116110
Special types, like TFileName and TCaption are nothing special, like Andreas mentioned, but they can be used to register a specific property editor in the IDE. This will help entering such values through the object inspector.
To really enforce such a value, if your string is a property of an object, you can write a setter for it.
Otherwise, I should make a TSize class that has properties for the two integers, and an AsString property that combines its properties to a string.
type
TSize = class
private
FLeftInt, FRightInt: Integer;
function GetString: string;
procedure SetString(Value: string);
public
property LeftInt: Integer read FLeftInt write FLeftInt;
property RightInt: Integer read FRightInt write FRightInt;
property AsString: string read GetString write SetString;
end;
function TSize.GetString: string;
begin
Result := Format('%dx%d', [FLeftInt, FRightInt]);
end;
function TSize.SetString(Value: string);
begin
// Validate and parse Value. Set LeftInt and RightInt.
end;
Upvotes: 1
Reputation: 1045
Simplest way is just to use a function, and always use it when defining your strings...
function MyString(numA, numB: single) : string;
begin
Result := FloatToStr(numA) + 'x' + FloatToStr(numB)
end;
If you want to get fancier, you can do it as a class which allows a direct string assignment as a property, but which parses the string for compliance.
Upvotes: 0