Delphi - Доступ к объекту Frame из формы - PullRequest
1 голос
/ 28 января 2009

Мне нужно запустить действие, которое прикреплено к кнопке (скажем, SQLBtn), которая помещается в Frame1 в моем приложении из Form1.
Я включил фрейм в формы Form1, но никак не могу обратиться к нему.
Я пробовал Frame1.SQLbtn TFrame1.SQLbtn TFrameSQLBtn и т. Д., Но не могу добраться до него.
Я хотел бы получить что-то похожее на «SQLbtn.click», чтобы запустить событие позади него.

У кого-нибудь есть идеи, как решить эту проблему?

Ответы [ 4 ]

5 голосов
/ 28 января 2009

Я не уверен, что правильно понял ваш вопрос. Похоже, у вас есть рамка с кнопкой (и обработчик события TAction или click на кнопке), и этот кадр находится на форме. Теперь вы хотите программно симулировать нажатие на эту кнопку.

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

TForm1...
  ...
  Frame1: TFrame1;
end;

Затем вы можете выполнить этот код с помощью Frame1.SQLbtn.Click из любого из методов формы. Возможно, лучшим способом было бы предоставить публичный метод для фрейма, который вы можете использовать из формы. Тогда вам не нужно напрямую обращаться к кнопке (кнопка - это деталь реализации фрейма, так сказать, фрейм частный).

Редактировать после уточнения

Я так понимаю, у вас есть следующий сценарий:

TFrameForm1...
  ...
  Frame1: TFrame1;
end;

TForm1...
  ...
  procedure something;
end;

procedure TForm1.something;
begin
  // how to call a method on Frame1 which is on FrameForm1
end;

Ваш лучший выбор - переместить код из фрейма кнопки обработчика события OnClick в отдельный блок. Это может быть модуль данных или просто другой модуль с отдельной процедурой. Затем вы можете вызвать этот код как из Form1, так и из обработчика событий кнопки Frame1. Это то, что прокомментировал Вегар.

Если это невозможно, например, поскольку для обработки требуется доступ к другим элементам управления в Frame1, переместите код в новую процедуру для Frame1 (мое первоначальное предложение):

TFrame1...
  ...
public
  procedure framestuff;
end;

procedure TFrame1.framestuff;
begin
  ...
end;

procedure TFrame1.SQLbtnClick(Sender...);
begin
  framestuff;
end;

Теперь вам нужно вызвать этот метод из Form1. Для этого вам понадобится ссылка на FrameForm1. Который вам нужно инициализировать вручную (!) При создании TFrameForm1. В этом примере ссылка - это поле FFrameForm:

TForm1...
  ...
  FFrameForm: TFrameForm1;
  procedure something;      
end;

procedure TForm1.something;
begin
  FrameForm.framestuff;
end;

Или, по умолчанию, Delphi добавляет глобальные переменные для всех форм в блоки формы (автоматическое создание формы, проверка параметров / форм проекта). Затем вы делаете это:

procedure TForm1.something;
begin
  FrameForm1.framestuff; // if FrameForm1 is the name Delphi used for the global variable
end;

Конечно, есть много других вариантов ...

1 голос
/ 28 января 2009
procedure TDiferentForm.DoSomething();
begin
  Form1.YourFrame.ButtonClick(nil);
end;
0 голосов
/ 29 января 2009

Другим решением является использование интерфейсов, чтобы избежать проблемы циклических ссылок и немного упростить код. Допустим, у вас есть процедура с именем foo , которую вы хотите вызвать из любого места в системе. Реализация этой процедуры находится в tFooForm , которая является не основной формой, а формой, о которой знает основная форма.

Сначала создайте новый юнит и назовите его Foo_Intf.pas

Его содержимое будет следующим:

unit Foo_Intf;

interface

type
  IFoo = interface
    ['{4AC12AB9-557B-4E61-AB2D-8B10E591E33A}'] 
    // CTRL-SHIFT-G to create a new guid
    procedure Foo;
  end;

implementation

end.

затем добавьте метод в класс tFooForm, а также включите интерфейс. Не забудьте использовать модуль foo_intf.pas в вашем интерфейсе использования предложения. Реализуйте класс foo, чтобы делать то, что вы хотите, чтобы эта процедура выполняла.

tFooForm = class(tForm,IFoo)
  :
  procedure Foo;
  :
end;

Также добавьте интерфейс IFoo в основную форму, точно так же, как предыдущий шаг, но измените реализацию на следующую:

procedure tMainForm.Foo;
begin
  if not Assigned(FooForm) then
    FooForm := tFooForm.Create(Application);  // for simplicity sake
  FooForm.Foo;
end;

Теперь, в любом месте, где вы хотите вызвать функцию foo, просто включите ТОЛЬКО модуль Foo_Intf в условие использования и используйте следующий фрагмент:

var
  FooIntf : IFoo;
begin
  if Not Supports(Application.MainForm, IFoo, FooIntf) then
    Raise Exception.create('Application.mainform does not implement IFoo');   
  FooIntf.Foo;
end;
0 голосов
/ 29 января 2009

Одна вещь, которая может помочь вам понять: когда вы создаете экземпляр формы (или фрейма), delphi проходит через DFM и создает экземпляры всех описанных там объектов.

ЕСЛИ у вас есть переменная в определении формы, которая соответствует имени объекта в DFM, загрузчик установит переменную, указывающую на объект; если у вас нет переменной, объект создается, но вам придется перебирать .Components или .Controls, чтобы добраться до него.

Если форма имеет переменную экземпляра фрейма (и эта переменная общедоступна), то код любой другой формы может получить к ней доступ (например, MainForm.Frame1 ...) и делать то, что хочет.

Чтобы инкапсулировать фрейм, форма (которая, в конце концов, просто класс) может иметь публичные свойства , которые имеют методы доступа и мутаторы для передачи информации во встроенный фрейм и из него. Инкапсуляция хороша (ИМХО самый важный аспект ООП), потому что она освобождает связь между вызывающей стороной и фреймом: вы можете изменить любую сторону, не нарушая ничего.

Приветствия

...