Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.05.2023, 23:23   #1
The_Immortal
Пользователь
 
Регистрация: 08.10.2008
Сообщений: 27
По умолчанию Как проверить принадлежность к классу компонента

В качестве входных данных поступает строка 'TEdit' (или любой другой класс компонентов). Надо проверить имеется ли на форме компонент, относящийся к такому классу компонента и если да, то взять сам компонент. Т.е. в общем, мне надо на вход подать имени классво компоентов, а на выходе получить имена всех контролов, относящихся к заданным классам.

Перепробовал разное:
Код:
var
  i: Integer;
  ComponentClass, ComponentClass2: TClass;
begin
  ComponentClass := GetClass('StdCtrls.TEdit'); // nil
  ComponentClass2 := GetClass('TEdit'); // nil

  for i := 0 to self.ComponentCount - 1 do

  begin
//    if self.Components[i] is GetClass('TEdit') // BAD
//    if self.Components[i] is ComponentClass // BAD
//    if self.Components[i] is ComponentClass2 // BAD
//    if self.Components[i].ClassType = FindClass('TEdit') // BAD
    if self.Components[i] is TEdit then // OK
    ...
  end;
end;
Срабатывает явное указание TClass, но на входе-то строка...

Подскажите, пожалуйста, как побороть.

Спасибо!

Последний раз редактировалось The_Immortal; 16.05.2023 в 23:42.
The_Immortal вне форума Ответить с цитированием
Старый 16.05.2023, 23:47   #2
jillitil
Форумчанин
 
Аватар для jillitil
 
Регистрация: 17.10.2018
Сообщений: 184
По умолчанию

Код:
    TForm1 = CLASS(TForm)
        BitBtn1: TBitBtn;
        BitBtn2: TBitBtn;
        Edit1: TEdit;
        ASDASD: TEdit;
        TRRRRR: TEdit;
        PROCEDURE BitBtn1Click(Sender: TObject);
    END;
..
..
PROCEDURE TForm1.BitBtn1Click(Sender: TObject);
VAR
    i: Integer;
    S: STRING;
BEGIN
    FOR i := 0 TO ComponentCount - 1 DO
        IF Components[i] IS TEdit THEN
            S := S + #13#10 + (Components[i].Name);
    ShowMessage(S);
END;
Изображения
Тип файла: jpg screenshot.7.jpg (29.4 Кб, 19 просмотров)
jillitil вне форума Ответить с цитированием
Старый 17.05.2023, 00:02   #3
The_Immortal
Пользователь
 
Регистрация: 08.10.2008
Сообщений: 27
По умолчанию

Вероятно, я не так объяснил... Попробую еще разок.
У меня на входе не TEdit (тип TClass), а строка 'TEdit' (тип string). И 'TEdit' (тип string) надо как-то преобразовать к TEdit (тип TClass). Ну или как-то по-другому подойти к задаче - правда, не знаю как...
Повторюсь, на вход может подаваться 'TEdit', 'TButton' или любой другой класс компонента в виде строки.

Последний раз редактировалось The_Immortal; 17.05.2023 в 00:04.
The_Immortal вне форума Ответить с цитированием
Старый 17.05.2023, 00:53   #4
jillitil
Форумчанин
 
Аватар для jillitil
 
Регистрация: 17.10.2018
Сообщений: 184
По умолчанию

Код:
    TForm1 = CLASS(TForm)
        BitBtn1: TBitBtn;
        BitBtn2: TBitBtn;
        Edit1: TEdit;
        ASDASD: TEdit;
        TRRRRR: TEdit;
        PROCEDURE BitBtn1Click(Sender: TObject);
        PROCEDURE FormCreate(Sender: TObject);
    END;

PROCEDURE TForm1.BitBtn1Click(Sender: TObject);
VAR
    i: Integer;
    S: STRING;
    P: TPersistentClass;
BEGIN
    P := GetClass(Edit1.Text);
    FOR i := 0 TO ComponentCount - 1 DO
        IF Components[i] IS P THEN
            S := S + #13#10 + (Components[i].Name);
    ShowMessage(S);
END;

PROCEDURE TForm1.FormCreate(Sender: TObject);
BEGIN
    RegisterClasses([TBitBtn]);
END;
Изображения
Тип файла: jpg screenshot.8.jpg (26.1 Кб, 20 просмотров)
jillitil вне форума Ответить с цитированием
Старый 17.05.2023, 00:58   #5
The_Immortal
Пользователь
 
Регистрация: 08.10.2008
Сообщений: 27
По умолчанию

Это получается надо каждый класс регистрировать? А если этих классов уйма и их вариации заранее неизвестны?..
The_Immortal вне форума Ответить с цитированием
Старый 17.05.2023, 01:11   #6
jillitil
Форумчанин
 
Аватар для jillitil
 
Регистрация: 17.10.2018
Сообщений: 184
По умолчанию

Цитата:
Make sure the classes are registered so that GetClass will work
Usually, this goes in the initialization section where it is only executed once
В руководстве скользко намекают что да.
jillitil вне форума Ответить с цитированием
Старый 17.05.2023, 01:26   #7
The_Immortal
Пользователь
 
Регистрация: 08.10.2008
Сообщений: 27
По умолчанию

В общем, получилось через RTTI вот так:

Код:
function StringToClass(AClassName: string): TClass;
var
  LCtx: TRttiContext;
  LTp: TRttiType;
begin
  Result := nil;

  try
    LTp := LCtx.FindType(AClassName);
  except
    Exit;
  end;

  if (LTp <> nil) and (LTp is TRttiInstanceType) then
    Result := TRttiInstanceType(LTp).MetaclassType;
end;

procedure TForm2.FormCreate(Sender: TObject);
var
  i: Integer;
  ComponentClass: TPersistentClass;
  S: string;
begin
    for i := 0 to Self.ComponentCount -1 do
    begin
      if self.Components[i] is StringToClass('Vcl.StdCtrls.TEdit') then
        ShowMessage(self.Components[i].Name);
    end
end;
Но тут требуется указывать полное пространство имен, а у меня только сам класс

Вот тут (где, собственно, само решение) советуют:
Цитата:
The fix is to attach the unit where you store these classes in the loop or in the list.
Не врублюсь как это сделать...

И почему народу понравился первый ответ - я также не понял. Как-то можно использовать StringList для моей задачи?

Последний раз редактировалось The_Immortal; 17.05.2023 в 01:38.
The_Immortal вне форума Ответить с цитированием
Старый 17.05.2023, 02:22   #8
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

А так?
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
    i: integer;
    S: string;
begin
    for i := 0 to ComponentCount - 1 do
        if Components[i].ClassName = 'TButton' then
            S := S + sLineBreak + Components[i].Name;
    ShowMessage(S);
end;
Цитата:
Сообщение от The_Immortal Посмотреть сообщение
Как-то можно использовать StringList для моей задачи?
Ну они предлагают составить список вида строковое имя класса и сам класс, но раз вариации неизвестны, то вам не подойдет.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 17.05.2023, 03:43   #9
The_Immortal
Пользователь
 
Регистрация: 08.10.2008
Сообщений: 27
По умолчанию

Как все просто оказалось-то!)

А я уже в дебри RTTI ушел:

Код:
function GetClass(const AClassName: string): TClass;
var
  ctx: TRttiContext;
  ThisType: TRttiType;
  ThisList: TArray<TRttiType>;
begin
  Result := nil;
  ctx := TRttiContext.Create;
  try
    ThisList := ctx.GetTypes;
    for ThisType in ThisList do
    begin
      if ThisType.IsInstance and (EndsText(AClassName, ThisType.Name)) then
      begin
        Result := ThisType.AsInstance.MetaClassType;
        BREAK;
      end;
    end;
  finally
    ctx.Free;
  end;
end;
Код:
ctx.GetTypes;
ооочень долго отрабатывает - туда дохрениллион типов попадает и по ним идет поиск

Спасибо большое!
The_Immortal вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[C] Надо вычислить область определения функции (ООФ), в программе после ввода аргументов проверить их принадлежность. Код есть. Lixer Помощь студентам 2 10.11.2018 18:41
Как проверить принадлежность определённой странице PageControl? Serik2010 Общие вопросы Delphi 2 04.07.2014 23:31
Delphi 7,проверить последовательность чисел на принадлежность к последовательности Фибоначчи SaintJon Помощь студентам 2 12.05.2014 16:42
решение задачи в Pascal - Проверить принадлежность точки с заданными координатами кругу с заданным радиусом и координатами центра Екатерина23 Помощь студентам 1 05.12.2013 16:35
Проверить элементы на принадлежность к множеству. altermag Помощь студентам 2 15.12.2007 22:07