Как я могу вызвать перегруженную функцию на основе enum typeinfo?

Я хочу нарисовать некоторые части темы для нескольких TImages. В моем коде ниже GetElementDetails ожидает определенное значение перечисления. У меня есть PTypeInfo для типа перечисления, но я не знаю, как преобразовать i в тип перечисления.

procedure TForm1.Button1Click(Sender: TObject);
  procedure drawType(c: tcanvas; ti: ptypeinfo);
  var
    r: trect;
    i: integer;
    details: TThemedElementDetails;
  begin
    r.Left := 0; r.Top := 0; r.Right := 19; r.Bottom := 19;
    for i := GetTypeData(ti).MinValue to GetTypeData(ti).MaxValue do begin
      // How to cast i to the enum type of ti?
      details := StyleServices.GetElementDetails( ???(i) );

      StyleServices.DrawElement(c.Handle, details, R);
      if (i mod 10 = 0) and (i > 0) then begin
        r.Left := 0; r.Right := 19; r.Top := r.Bottom + 3; r.Bottom := r.Bottom + 22;
      end
      else r.Inflate(-22,0,22,0);
    end;
  end;
begin
  drawType(image1.canvas, typeinfo(TThemedToolBar));
  drawType(image2.canvas, typeinfo(TThemedButton));
  drawType(image3.canvas, typeinfo(TThemedCategoryPanelGroup));
  drawType(image4.canvas, typeinfo(TThemedComboBox));
end;

Мне нужно привести i к типу, переданному как вторая переменная (TThemedToolBar, TThemedButton и т. д.). Как я могу это решить?


person Kiril Hadjiev    schedule 06.08.2014    source источник
comment
Я думаю, что подобное было задано в this question.   -  person TLama    schedule 06.08.2014
comment
Я не могу получить само перечисление во внутренней функции. как вы предлагаете изменить эту строку: StyleServices.DrawElement(c.Handle, StyleServices.GetElementDetails(TEnumHelp‹ti.???›.Cast(i)), R);   -  person Kiril Hadjiev    schedule 06.08.2014


Ответы (2)


Вы не можете сделать это легко. Метод GetElementDetails сильно перегружен по своим первым параметрам. Разрешение перегрузки является статическим и выполняется во время компиляции. Вы хотите выполнить привязку к методу во время выполнения на основе типа перечисления во время выполнения. Это невозможно для обычных вызовов методов.

Единственный способ сделать это — использовать RTTI. Перечислите методы объекта службы стилей. Найдите все те, которые имеют имя GetElementDetails. Выберите тот, параметры которого соответствуют типу времени выполнения вашего перечисления. Затем вызовите его с помощью RTTI.

Я не могу написать код, чтобы показать вам это, но есть много хороших примеров этих методов, теперь, когда вы знаете, что нужно делать.

person David Heffernan    schedule 06.08.2014

Попробуй это:

type
   TAbstractStyleServicesFunction = reference to function(const styleServices: TAbstractStyleServices; const I: Integer)
      : TThemedElementDetails;


procedure TForm1.drawType(c: TCanvas; ti: PTypeInfo; const styleServicesFunction: TAbstractStyleServicesFunction);
var
   r: trect;
   I: Integer;
begin
   r.Left := 0;
   r.Top := 0;
   r.Right := 19;
   r.Bottom := 19;
   for I := GetTypeData(ti).MinValue to GetTypeData(ti).MaxValue do
   begin
      styleServices.DrawElement(c.Handle, styleServicesFunction(styleServices, I), r);

      if (I mod 10 = 0) and (I > 0) then
      begin
         r.Left := 0;
         r.Right := 19;
         r.Top := r.Bottom + 3;
         r.Bottom := r.Bottom + 22;
      end
      else
         r.Inflate(-22, 0, 22, 0);
   end;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
   drawType(image1.canvas, typeinfo(TThemedToolBar),
      function(const styleServices: TAbstractStyleServices; const I: Integer): TThemedElementDetails
      begin
         Result := styleServices.GetElementDetails(TThemedToolBar(I));
      end);
end;
person Passella    schedule 06.08.2014
comment
Это хорошая идея, но каждый раз, когда вы хотите вызвать drawType, требуется слишком много шаблонного кода. - person Rob Kennedy; 07.08.2014