2008. november 9., vasárnap

How to check what type of component is the Sender


Problem/Question/Abstract:

The piece of code below is typical of some routines we have. This example only uses 2 component types but sometimes there could be 7 or 8 and then the code is really bad.

procedure TEN1FORM.myonEnter(Sender: TObject);
begin
  if Sender is TDBComboBox then
    enterstr := TDBComboBox(Sender).text
  else if Sender is TOVCDBPICTUREFIELD then
    enterstr := TOVCdbPICTUREFIELD(Sender).text;
end;

Answer:

Solve 1:

function CheckIsType(AObject: TObject; const ClassArray: array of TClass): Integer;
{Return an index indicative of a type match on the object, and array of types passed}
begin
  for Result := 0 to High(ClassArray) do
    if AObject is ClassArray[Result] then
      Exit;
  Result := -1;
end;

{ ... }
case CheckIsType(Sender, [TdbComboBox, TOVCDBPctureField, TSpeedButton, TEdit]) of
  0: { ... }; {TDBComboBox}
  1: { ... }; {TOVCDBPctureField}
  2: { ... }; {TSpeedButton}
  3: { ... }; {TEdit}
end;
{ ... }

I also use the following routine which does an exact type match:

function CheckType(AObject: TObject; const ClassArray: array of TClass): Integer;
var
  Index: Integer;
begin
  Result := -1;
  if Assigned(AObject) then
    for Index := 0 to High(ClassArray) do
      if AObject.ClassType = ClassArray[Index] then
      begin
        Result := Index;
        Exit;
      end;
end;


Solve 2:

Let me add one more way to tackle this: use run-time type information. Text is a published property so RTTI exists for it. So you can use the stuff in Unit TypInfo to access it.

uses
  TypInfo;

function GetStrProperty(anObj: TObject; const propname: string): string;
var
  PInfo: PPropInfo;
begin
  result := EmptyStr;
  PInfo := GetPropInfo(anObj.ClassInfo, propname);
  if PInfo <> nil then
    {found aproperty with this name, check if it has the correct type}
    if PInfo^.Proptype^.Kind in [tkString, tkLString] then
    begin
      {it has! Get the string value from theproperty}
      Result := GetStrProp(anObj, PInfo);
    end;
end;

Using this function your handler becomes

procedure TEN1FORM.myonEnter(Sender: TObject);
begin
  enterstr := GetStrProperty(sender, 'text');
  { ... }

Nincsenek megjegyzések:

Megjegyzés küldése