Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
Почему для той же формы, он может вернуть 7 конструкторов, 6 деструкторов ? Как отсортировать только те, что имеет TForm ? А не всех наследников как я понимаю

+
program Project2;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils, vcl.forms, rtti;

var
  Method: TRttiMethod;
  ClassInfo: TRttiType;
  r: TRttiContext;

begin
  try
    ClassInfo := r.FindType('Vcl.Forms.TForm');
    for Method in ClassInfo.GetMethods do
      if Method.IsConstructor or Method.IsDestructor then
        Writeln(Method.ToString);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.
25 мар 19, 21:09    [21843188]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1579
GetDeclaredMethods
25 мар 19, 21:49    [21843208]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
X-Cite,

То есть можно по base отсортировать overload и потом недостающие методы выковырять по цыпочке ? Что бы не плодить дубликаты со всех предков
25 мар 19, 22:01    [21843213]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1579
GetDeclaredMethods - вернет только то что у TForm
т.к. у TForm нет конструкторов или деструкторов, то ничего и не вернется у вас.
Если укажете TCustomForm то вернет 2 конструктора
http://docwiki.embarcadero.com/Libraries/Rio/en/System.Rtti.TRttiType.GetDeclaredMethods
25 мар 19, 22:32    [21843240]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
После очередного вык..косяка, я написал это

program Project2;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils, vcl.forms, Generics.Collections, rtti;

function GetMethodsOnly(v: TRttiType): TArray<TRttiMethod>;
type
  TMethodExistList = TDictionary<string, Integer>;
var
  ExistList: TMethodExistList;
  ListCurrent, tmp: Integer;
  base: TRttiType;
  Method: TRttiMethod;
  NewFor: Boolean;
  name: string;
begin
  ExistList := TMethodExistList.Create;
  ListCurrent := 0;
  SetLength(Result, 500);
  base := v.BaseType;
  while base <> nil do
  begin
    NewFor := ListCurrent <= 0;
    for Method in base.GetDeclaredMethods do
    begin
      name := Method.name;
      if NewFor or not ExistList.TryGetValue(name, tmp) then
      begin
        Result[ListCurrent] := Method;
        inc(ListCurrent);
        ExistList.Add(name, 1);
      end
    end;
    base := base.BaseType;
  end;
  SetLength(Result, ListCurrent);
  ExistList.Free;
end;

var
  Method: TRttiMethod;
  ClassInfo, base: TRttiType;
  r: TRttiContext;

begin
  try
    ClassInfo := r.FindType('Vcl.Forms.TForm');

    for Method in GetMethodsOnly(ClassInfo) do
      if Method.IsConstructor or Method.IsDestructor then
        Writeln(Method.ToString);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.
25 мар 19, 22:34    [21843242]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
С постепенным увеличением, оно в любом случае нужно

+
function GetMethodsOnly(v: TRttiType): TArray<TRttiMethod>;
type
  TMethodExistList = TDictionary<string, Integer>;
var
  ExistList: TMethodExistList;
  ListCurrent, ListMax, tmp: Integer;
  base: TRttiType;
  Method: TRttiMethod;
  NewFor: Boolean;
  name: string;
begin
  ExistList := TMethodExistList.Create;
  ListCurrent := 0;
  ListMax := 100;
  SetLength(Result, ListMax);
  base := v.BaseType;
  while base <> nil do
  begin
    NewFor := ListCurrent <= 0;
    for Method in base.GetDeclaredMethods do
    begin
      name := Method.name;
      if NewFor or not ExistList.TryGetValue(name, tmp) then
      begin
        Result[ListCurrent] := Method;
        inc(ListCurrent);
        ExistList.Add(name, 1);

        if ListCurrent >= ListMax then
        begin
          inc(ListMax, 100);
          SetLength(Result, ListMax);
        end;
      end
    end;
    base := base.BaseType;
  end;
  SetLength(Result, ListCurrent);
  ExistList.Free;
end;
25 мар 19, 22:55    [21843253]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1579
Совершенно непонятно для чего это и совершенно не совпадает с первым сообщением
25 мар 19, 23:11    [21843267]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
X-Cite,

надо собрать чистокровку, без повторяющийся методов от предвков. С сохранением overload, во всех классах(предках)

Функция с косясками, я сейчас её в тесты запихнул и увидел что дубликаты, все дела.. Надо переписать
25 мар 19, 23:19    [21843273]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
Без пятой бутылки пивка было не разобраться.. Пришлось бегать в ночной

Теперь работает как я и хотел
+
program Project2;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  vcl.forms,
  Generics.Collections,
  rtti, UnitClass;

function GetMethodsOnly(v: TRttiType): TArray<TRttiMethod>;
type
  TArrArgsType = TArray<TRttiParameter>;
  TTTArrArgsType = TArray<TArrArgsType>;
  TArgsExistList = TDictionary<string, TTTArrArgsType>;
var
  Item: TPair<string, TTTArrArgsType>;
  base: TRttiType;
  Method: TRttiMethod;
  List: TArgsExistList;
  name: string;
  tmp: TTTArrArgsType;
  l, ListCurrent, ListMax: Integer;
  isExist, NewFor: Boolean;
  function IsParameterExist(p: TArrArgsType; List: TTTArrArgsType): Boolean;
  var
    t: TArrArgsType;
    param: TRttiParameter;
    i, count: Integer;
  begin
    for t in List do
    begin
      count := length(t);
      if count <> length(p) then
        exit(false);

      for i := 0 to count - 1 do
      begin
        if t[i].ParamType <> p[i].ParamType then
          exit(false);
      end;
    end;
    exit(true);
  end;

begin
  ListCurrent := 0;
  ListMax := 100;
  SetLength(Result, ListMax);

  List := TArgsExistList.Create();
  base := v.BaseType;
  while base <> nil do
  begin
    NewFor := ListCurrent <= 0;
    for Method in base.GetDeclaredMethods do
    begin
      name := Method.name;
      isExist := List.TryGetValue(name, tmp);

      if not NewFor and isExist then
      begin
        if IsParameterExist(Method.GetParameters, tmp) then
          Continue;
      end;

      l := length(tmp);
      SetLength(tmp, l + 1);

      tmp[l] := Method.GetParameters;

      List.AddOrSetValue(name, tmp);

      Result[ListCurrent] := Method;
      inc(ListCurrent);

      if ListCurrent >= ListMax then
      begin
        inc(ListMax, 100);
        SetLength(Result, ListMax);
      end;
    end;
    base := base.BaseType;
  end;

  List.Free;

  SetLength(Result, ListCurrent);
end;

var
  Method: TRttiMethod;
  ClassInfo, base: TRttiType;
  r: TRttiContext;

begin
  try
    ClassInfo := r.GetType(TypeInfo(TForm));

    for Method in GetMethodsOnly(ClassInfo) do
      if Method.IsConstructor or Method.IsDestructor then
        Writeln(Method.ToString);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



constructor Create(AOwner: TComponent)
constructor CreateNew(AOwner: TComponent; Dummy: Integer)
destructor Destroy
constructor CreateParented(ParentWindow: HWND)
constructor Create


Весь результат
+
constructor Create(AOwner: TComponent)
constructor CreateNew(AOwner: TComponent; Dummy: Integer)
destructor Destroy
procedure ScaleForPPI(NewPPI: Integer)
procedure Close
function CloseQuery: Boolean
procedure DefaultHandler(var Message)
procedure DefocusControl(Control: TWinControl; Removing: Boolean)
procedure Dock(NewDockSite: TWinControl; ARect: TRect)
procedure FocusControl(Control: TWinControl)
procedure GetChildren(Proc: TGetChildProc = procedure(Child: TComponent) of object; Root: TComponent)
function GetFormImage: TBitmap
procedure Hide
function IsShortCut(var Message: TWMKey): Boolean
procedure MakeFullyVisible(AMonitor: TMonitor)
procedure MouseWheelHandler(var Message: TMessage)
procedure Print
procedure RecreateAsPopup(AWindowHandle: HWND)
procedure Release
procedure SendCancelMode(Sender: TControl)
procedure SetFocus
function SetFocusedControl(Control: TWinControl): Boolean
procedure Show
function ShowModal: Integer
function WantChildKey(Child: TControl; var Message: TMessage): Boolean
procedure set_PopupParent(Value: TCustomForm)
procedure AfterConstruction
procedure BeforeDestruction
procedure DisableAutoRange
procedure EnableAutoRange
procedure ScrollInView(AControl: TControl)
constructor CreateParented(ParentWindow: HWND)
class function CreateParentedControl(ParentWindow: HWND): TWinControl
procedure Broadcast(var Message)
function CanFocus: Boolean
function ContainsControl(Control: TControl): Boolean
function ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean; AllowWinControls: Boolean; AllLevels: Boolean): TControl
procedure DisableAlign
procedure DockDrop(Source: TDragDockObject; X: Integer; Y: Integer)
procedure EnableAlign
function FindChildControl(const ControlName: string): TControl
procedure FlipChildren(AllLevels: Boolean)
function Focused: Boolean
procedure GetTabControlList(List: TList)
procedure GetTabOrderList(List: TList)
function HandleAllocated: Boolean
procedure HandleNeeded
procedure InsertControl(AControl: TControl)
procedure Invalidate
procedure PaintTo(DC: HDC; X: Integer; Y: Integer)
procedure PaintTo(Canvas: TCanvas; X: Integer; Y: Integer)
function PreProcessMessage(var Msg: tagMSG): Boolean
procedure RemoveControl(AControl: TControl)
procedure Realign
procedure Repaint
procedure ScaleBy(M: Integer; D: Integer)
procedure ScrollBy(DeltaX: Integer; DeltaY: Integer)
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer)
procedure SetDesignVisible(Value: Boolean)
procedure Update
procedure UpdateControlState
function GetDockClients(Index: Integer): TControl
function GetControl(Index: Integer): TControl
procedure BeginDrag(Immediate: Boolean; Threshold: Integer)
procedure BringToFront
function ClientToScreen(const Point: TPoint): TPoint
function ClientToParent(const Point: TPoint; AParent: TWinControl): TPoint
function Dragging: Boolean
procedure DragDrop(Source: TObject; X: Integer; Y: Integer)
function DrawTextBiDiModeFlags(Flags: Integer): Integer
function DrawTextBiDiModeFlagsReadingOnly: Integer
procedure EndDrag(Drop: Boolean)
function GetControlsAlignment: TAlignment
function GetParentComponent: TComponent
function HasParent: Boolean
procedure InitiateAction
function IsRightToLeft: Boolean
function ManualDock(NewDockSite: TWinControl; DropControl: TControl; ControlSide: TAlign): Boolean
function ManualFloat(ScreenPos: TRect): Boolean
function Perform(Msg: Cardinal; WParam: NativeUInt; LParam: NativeInt): NativeInt
procedure Refresh
function ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl; DropControl: TControl; ControlSide: TAlign): Boolean
function ScreenToClient(const Point: TPoint): TPoint
function ParentToClient(const Point: TPoint; AParent: TWinControl): TPoint
procedure SendToBack
procedure SetParentComponent(Value: TComponent)
function UseRightToLeftAlignment: Boolean
function UseRightToLeftReading: Boolean
function UseRightToLeftScrollBar: Boolean
function GetTextBuf(Buffer: PWideChar; BufSize: Integer): Integer
function GetTextLen: Integer
function Perform(Msg: Cardinal; WParam: NativeUInt; LParam: PWideChar): NativeInt
function Perform(Msg: Cardinal; WParam: NativeUInt; var LParam: TRect): NativeInt
procedure SetTextBuf(Buffer: PWideChar)
function BeginInvoke(const AProc: TProc; const AContext: TObject): IAsyncResult
function BeginInvoke(const AProc: TAsyncProcedureEvent = procedure(const ASyncResult: IAsyncResult) of object; const AContext: TObject): IAsyncResult
function BeginInvoke(const AProc: TAsyncConstArrayProc; const Params: TVarRec; const AContext: TObject): IAsyncResult
function BeginInvoke(const AProc: TAsyncConstArrayProcedureEvent = procedure(const ASyncResult: IAsyncResult; const Params: TVarRec) of object; const Params: TVarRec; const AContext: TObject): IAsyncResult
function BeginInvoke(const AFunc: TAsyncConstArrayFunctionEvent = procedure(const ASyncResult: IAsyncResult; out Result: TObject; const Params: TVarRec) of object; const Params: TVarRec; const AContext: TObject): IAsyncResult
function BeginInvoke(const AFunc: TAsyncFunctionEvent = procedure(const ASyncResult: IAsyncResult; out Result: TObject) of object; const AContext: TObject): IAsyncResult
procedure EndInvoke(const ASyncResult: IAsyncResult)
function EndFunctionInvoke(const AsyncResult: IAsyncResult): TObject
procedure DestroyComponents
procedure Destroying
function ExecuteAction(Action: TBasicAction): Boolean
function FindComponent(const AName: string): TComponent
procedure FreeNotification(AComponent: TComponent)
procedure RemoveFreeNotification(AComponent: TComponent)
procedure FreeOnRelease
function GetEnumerator: TComponentEnumerator
function GetNamePath: string
procedure InsertComponent(const AComponent: TComponent)
procedure RemoveComponent(const AComponent: TComponent)
procedure SetSubComponent(IsSubComponent: Boolean)
function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HRESULT
function UpdateAction(Action: TBasicAction): Boolean
function IsImplementorOf(const I: IInterface): Boolean
function ReferenceInterface(const I: IInterface; Operation: TOperation): Boolean
function GetComponent(AIndex: Integer): TComponent
procedure Assign(Source: TPersistent)
constructor Create
procedure Free
procedure DisposeOf
class function InitInstance(Instance: Pointer): TObject
procedure CleanupInstance
function ClassType: TClass
class function ClassName: string
class function ClassNameIs(const Name: string): Boolean
class function ClassParent: TClass
class function ClassInfo: Pointer
class function InstanceSize: Integer
class function InheritsFrom(AClass: TClass): Boolean
class function MethodAddress(const Name: ShortString): Pointer
class function MethodAddress(const Name: string): Pointer
class function MethodName(Address: Pointer): string
class function QualifiedClassName: string
function FieldAddress(const Name: ShortString): Pointer
function FieldAddress(const Name: string): Pointer
function GetInterface(const IID: TGUID; out Obj): Boolean
class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry
class function GetInterfaceTable: PInterfaceTable
class function UnitName: string
class function UnitScope: string
function Equals(Obj: TObject): Boolean
function GetHashCode: Integer
function ToString: string
procedure Dispatch(var Message)
class function NewInstance: TObject
procedure FreeInstance
26 мар 19, 01:07    [21843301]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
Багфикс замены base := v.BaseType; на изначальный аргумент функции

+
program Project2;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  vcl.forms,
  Generics.Collections,
  rtti, UnitClass;

function GetMethodsOnly(base: TRttiType): TArray<TRttiMethod>;
type
  TArrArgsType = TArray<TRttiParameter>;
  TTTArrArgsType = TArray<TArrArgsType>;
  TArgsExistList = TDictionary<string, TTTArrArgsType>;
var
  Item: TPair<string, TTTArrArgsType>;
  Method: TRttiMethod;
  List: TArgsExistList;
  name: string;
  tmp: TTTArrArgsType;
  l, ListCurrent, ListMax: Integer;
  NewFor: Boolean;
  function IsParameterExist(p: TArrArgsType): Boolean;
  var
    t: TArrArgsType;
    param: TRttiParameter;
    i, count: Integer;
  begin
    for t in tmp do
    begin
      count := length(t);
      if count <> length(p) then
        exit(false);

      for i := 0 to count - 1 do
      begin
        if t[i].ParamType <> p[i].ParamType then
          exit(false);
      end;
    end;
    exit(true);
  end;

begin
  ListCurrent := 0;
  ListMax := 100;
  SetLength(Result, ListMax);

  List := TArgsExistList.Create();
  while base <> nil do
  begin
    NewFor := ListCurrent <= 0;
    for Method in base.GetDeclaredMethods do
    begin
      name := Method.name;

      if not NewFor and List.TryGetValue(name, tmp) then
      begin
        if IsParameterExist(Method.GetParameters) then
          Continue;
      end;

      l := length(tmp);
      SetLength(tmp, l + 1);

      tmp[l] := Method.GetParameters;

      List.AddOrSetValue(name, tmp);

      Result[ListCurrent] := Method;
      inc(ListCurrent);

      if ListCurrent >= ListMax then
      begin
        inc(ListMax, 100);
        SetLength(Result, ListMax);
      end;
    end;
    base := base.BaseType;
  end;

  List.Free;

  SetLength(Result, ListCurrent);
end;

var
  Method: TRttiMethod;
  ClassInfo, base: TRttiType;
  r: TRttiContext;

begin
  try
    ClassInfo := r.GetType(TypeInfo(TForm));

    for Method in GetMethodsOnly(ClassInfo) do
      if Method.IsConstructor or Method.IsDestructor then
        Writeln(Method.ToString);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.
26 мар 19, 01:53    [21843309]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1579
 TA = class
  public
    constructor Create; virtual;
  end;

  TB = class(TA)
  public
    constructor Create; overload; override;
    constructor Create(const aParam: Int32); reintroduce; overload;
  end;

ClassInfo := r.GetType(TypeInfo(TB));


Выведет
constructor Create
constructor Create(const aParam: Integer)
constructor Create
constructor Create
destructor Destroy
26 мар 19, 10:17    [21843462]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
X-Cite,


Картинка с другого сайта.

constructor Create
constructor Create(const aParam: Integer)
destructor Destroy


+
program Project2;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  vcl.forms,
  Generics.Collections,
  rtti;

type
  TA = class
  public
    constructor Create; virtual;
  end;

  TB = class(TA)
  public
    constructor Create; overload; override;
    constructor Create(const aParam: Int32); reintroduce; overload;
  end;

function GetMethodsOnly(base: TRttiType): TArray<TRttiMethod>;
type
  TArrArgsType = TArray<TRttiParameter>;
  TTTArrArgsType = TArray<TArrArgsType>;
  TArgsExistList = TDictionary<string, TTTArrArgsType>;
var
  Item: TPair<string, TTTArrArgsType>;
  Method: TRttiMethod;
  List: TArgsExistList;
  name: string;
  tmp: TTTArrArgsType;
  l, ListCurrent, ListMax: Integer;
  NewFor: Boolean;
  function IsParameterExist(p: TArrArgsType): Boolean;
  var
    t: TArrArgsType;
    i, count: Integer;
  begin
    for t in tmp do
    begin
      count := length(t);

      if count = length(p) then
      begin
        if count = 0 then
          exit(true);

        for i := 0 to count - 1 do
        begin
          if t[i].ParamType <> p[i].ParamType then
            exit(false);
        end;
      end;
    end;
    exit(true);
  end;

begin
  ListCurrent := 0;
  ListMax := 100;
  SetLength(Result, ListMax);

  List := TArgsExistList.Create();
  while base <> nil do
  begin
    NewFor := ListCurrent <= 0;
    for Method in base.GetDeclaredMethods do
    begin
      name := Method.name;

      if not NewFor and List.TryGetValue(name, tmp) then
      begin
        if IsParameterExist(Method.GetParameters) then
          Continue;
      end;

      l := length(tmp);
      SetLength(tmp, l + 1);

      tmp[l] := Method.GetParameters;

      List.AddOrSetValue(name, tmp);

      Result[ListCurrent] := Method;
      inc(ListCurrent);

      if ListCurrent >= ListMax then
      begin
        inc(ListMax, 100);
        SetLength(Result, ListMax);
      end;
    end;
    base := base.BaseType;
  end;

  List.Free;

  SetLength(Result, ListCurrent);
end;

constructor TA.Create;
begin
end;

constructor TB.Create;
begin
end;

constructor TB.Create(const aParam: Int32);
begin

end;

var
  Method: TRttiMethod;
  ClassInfo: TRttiType;
  r: TRttiContext;

begin
  try
    ClassInfo := r.GetType(TypeInfo(TB));

    for Method in GetMethodsOnly(ClassInfo) do
      if Method.IsConstructor or Method.IsDestructor then
        Writeln(Method.ToString);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.
26 мар 19, 11:21    [21843530]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
DimaBr
Member

Откуда:
Сообщений: 11287
А нельзя напихать описание в TStringList и выкидывая дубликаты ?
Зачем такая простынь ?
26 мар 19, 23:58    [21844391]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
DimaBr,

1) Нужна динамика
2) Один раз нужно вызвать, для сбора информации
27 мар 19, 01:06    [21844406]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
Функция работает так

1) Набираем информацию о методах текущего класса
2) Идём гулять по унаследованным классам
3) Добавляем из них новые методы
4) Если метод существует в базе по имени ранее, смотрим есть ли в нём различие в аргументах. Если есть, то добавляем в базу

В общем то и всё.

Я не представляю для себя возможных, проверку аргументов для методов используя TStringList
27 мар 19, 01:11    [21844407]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
DimaBr
Member

Откуда:
Сообщений: 11287
Зачем их проверять ? Нельзя просто собрать уникальные ?
27 мар 19, 02:55    [21844428]     Ответить | Цитировать Сообщить модератору
 Re: RTTI GetMethods  [new]
Foxpc
Member

Откуда:
Сообщений: 162
DimaBr,

Картинка с другого сайта. почитай про overload
27 мар 19, 11:02    [21844729]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить