2009-08-02 3 views
2

Я должен создать массив и поместить все элементы управления там, чтобы получить доступ them.Here короткий пример:Как создать массив элементов управления?

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    Button3: TButton; 
    const Test:Array[0..2] of TButton = (Button1,Button2,Button3); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

end. 

Undeclarated idenitifier «Button1» в строке, где я declarated мои array.But это declarated три строки выше.

В чем проблема, как разместить все элементы управления в массиве?

EDIT:

Спасибо за ваши ответы, но у меня есть проблемы:

var TestA:TObjectList<TButton>; 

var index:TComponent; 
begin 
TestA := TObjectList<TButton>.Create(false); 
    for index in Form7 do 
    if pos(index.name, 'Button') = 1 then 
     TestA.add(TButton(index)); 

TestA[0].Caption := 'Test'; //Exception out of range. 
+0

Что именно вы хотите сделать точно? Все ли кнопки управления или сочетание разных элементов управления? Есть ли у них что-то общее, как все они сидят на одном и том же родительском контроле или соглашении об именах? Кроме того, какую версию Delphi вы используете? – CodeAndCats

+0

Его один контроль TButton. –

+0

Я думаю, что ваши параметры Pos неправильны, поэтому вы не создаете никаких элементов управления. Переход в отладчик покажет вам, что происходит. – mj2008

ответ

4

Ben's right. Вы не можете настроить контрольный массив в конструкторе форм. Но если у вас есть 110 изображений, для этого конкретного случая вы можете поместить их в компонент TImageList и обработать его коллекцию изображений в виде массива.

Если у вас есть куча более обычных элементов управления, например кнопок, вам нужно будет создать массив и загрузить их в код. Есть два способа сделать это. Простой способ, по крайней мере, для небольших массивов - это ответ Бена. Для больших наборов управления или тех, которые часто меняются (когда ваш проект не завершен, например), пока вы не дадите им все серийные имена (Button1, Button2, Button3 ...), вы можете попробовать что-то как это:

var 
    index: TComponent; 
    list: TObjectList; 
begin 
    list := TObjectList.Create(false); //DO NOT take ownership 
    for index in frmMyForm do 
    if pos('Button', index.name) = 1 then 
     list.add(index); 
    //do more stuff once the list is built 
end; 

(. Используйте TObjectList<TComponent>, или что-то еще более конкретно, если вы используете D2009) построить список, основанный на коде выше, затем написать функцию сортировки обратного вызова, которая будет сортировать их основе по имени и использовать его для сортировки списка, и у вас есть ваш «массив».

+0

Проверьте мой код в моем вопросе, у меня проблемы. –

+0

Ошибка была в вашем коде на самом деле. Первый параметр - pos() - это substr, а не полная строка. Большой ответ, поэтому принят. Другие ответы + 1, Спасибо всем! –

+0

Ack! Извини за это. Я взломал это с головы, и я никогда не могу поддерживать строковые функции. Некоторые из них сначала берут substr, а некоторые берут первую строку. Исправлено. –

4

Вы не можете ссылаться на общие свойства вашей формы в постоянной решетки, как, что , Попробуйте сделать это в своем конструкторе форм/в событии OnCreate.

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Test[0] := Button1; 
    Test[1] := Button2; 
    Test[2] := Button3; 
end; 
+0

Пожалуйста, предложите другой способ. У меня есть 110 изображений, на самом деле это будет выглядеть уродливо. Разве это невозможно по-другому? –

+0

Хорошо, я бы предложил только то, что Мейсон или Лахлан уже предложили. Вы можете проверить Delphi Help на TControl.Controls, TControl.ControlCount, TComponent.Компоненты, TComponent.ComponentCount, TComponent.FindComponent. Все это очень полезные методы для итерации элементов управления/компонентов, находящихся на TWinControl /, принадлежащих компоненту. – CodeAndCats

+0

Все наши ответы будут хорошо работать для вашего вопроса. Могу ли я предложить подробно рассказать о вашей ситуации, чтобы мы могли придумать более подходящий ответ? – CodeAndCats

1

Как насчет этого?

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    for b := 1 to 110 do 
    Test[b] := FindComponent('Button' + IntToStr(b)) as TButton; 
end; 

Вы должны объявить массив как переменную, а не константа, и она должна будет идти от 1 до 110, а не от 0 до 109, но это не проблема.

+0

Плохая идея, поскольку FindComponent выполняет поиск O (N) через (потенциально) весь компонентный компонент каждый раз. В зависимости от того, насколько сложна форма, это может добавить заметное время настройки для формы. Лучше сделать это за один проход. –

+1

Эй, плохая идея немного сильна! ;-) Это ясно, просто и будет выполняться в мгновение ока на 99% форм. Лучше сначала писать четкий и простой код, а затем использовать профилировщик для определения узких мест, прежде чем вы начнете оптимизировать IMO. – LachlanG

+0

Извините. Я не собирался оскорблять таким комментарием. Я просто считаю, что лучше написать алгоритм, который может масштабироваться. На работе я часто сталкивался с ошибками, вызванными старым кодом, который был написан «просто» и, вероятно, работал отлично, когда наше приложение было намного меньше, чем сегодня, но теперь оно сломано. Иногда я могу это исправить. В других случаях вокруг него выросла архитектура, и это настоящая боль, чтобы приспособиться, не нарушая что-то еще. Лучше проектировать, чтобы избежать этого, ИМО. –

2

Эта функция выполняет итерацию по всем элементам управления в определенном контейнере, например, отдельную TPanel или даже всю форму, и заполняет указанный TObjectList элементами управления TImage.

procedure TForm1.AddImageControlsToList(AParent: TWinControl; AList: TObjectList; Recursive: boolean); 
var 
    Index: integer; 
    AChild: TControl; 
begin 
    for Index := 0 to AParent.ControlCount - 1 do 
    begin 
    AChild := AParent.Controls[Index]; 
    if AChild is TImage then // Or whatever test you want to use 
     AList.Add(AChild) 
    else if Recursive and (AChild is TWinControl) then 
     AddImageControlsToList(TWinControl(AChild), AList, True); 
    end; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    // Call like this or similar to get your list of images 
    // (assumes MyImageList is declared in Form) 
    MyImageList := TObjectList.Create(False); 
    AddImageControlsToList(Self, MyImageList, True); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    // Destroy the list 
    FreeAndNil(MyImageList); 
end; 
1

Я использую это все время - это просто и быстро (несмотря на комментарий г-Уилера) - объявить maxbuttons как постоянный

вар Form1: TForm1; pbutton: array [1..maxbuttons] of^tbutton;

реализация

{$ R * .dfm}

процедура TForm1.Button1Click (Отправитель: TObject);

(* Выход *)

вар к: целое число;

начинают

для к: = 1, чтобы сделать maxbuttons утилизацию (pbutton [K]);

закрыть;

конец;

процедура TForm1.FormActivate (отправитель: TObject);

var k: integer;

начинают

(* обратите внимание, кнопки должны быть Button1, Button2 и т.д. в последовательности или вам необходимо выделить их вручную, например, pbutton [1] ^: = exitbtn и т.д. *)

для к: = 1 в maxbuttons сделать

начинают

new(pbutton[k]); 

pbutton[k]^:= tbutton(FindComponent('Button'+IntToStr(k))); 

конец;

конец;

процедура TForm1.ButtonMouseDown (отправитель: TObject; кнопка: TMouseButton; Shift: TShiftState; X, Y: целое число);

var k: integer; b: boolean;

начало b: = false; k: = 1;

в то время как (к < = maxbuttons) и (не б) у

начинают

если pbutton [к]^= отправитель затем (Примечание отправитель указывает, какая кнопка была нажата)

begin 

    { found it so do something} 

    b:=true; 

end; 

k:=k+1; 

конец;

конец;

+0

Почему вы используете оператор ^? Вы должны использовать. Создавать и бесплатно методы! Они намного безопаснее и удобнее в обслуживании, а перфоманс сопоставим. – smok1

1

Попробуйте следующее var TestA: TObjectList;

index:TComponent; 
begin 
    TestA := TObjectList<TButton>.Create(false); 
    try 
    for index in Form7 do 
     if (pos is TButton) OR {or/and} (pos.tag and 8=8) then 
     TestA.add(TButton(index)); 
    if TestA.Count>0 then //Fix:Exception out of range. 
     TestA[0].Caption := 'Test'; 
    finally 
     TestA.Free; 
    end; 
end; 
Смежные вопросы