fisadmaster Ответов: 1

Как определить, какая дочерняя форма запускает обычное пользовательское событие в delphi


Сценарий таков: у меня есть родительская форма, которая создает дочернюю форму, чтобы общаться между ними, в родительской форме создается объект пользовательского типа события. Гендель родительской формы передается в качестве параметра процедуре создания события.

В дочерней форме создается пользовательское свойство типа события того же типа, что и родительская форма, затем в момент создания дочерней формы из родительского объекта родительский объект приравнивается к дочернему свойству, например: propForm.CreateScheduleEvent:= CreateScheduleFormEvent;

В сценарии, где используются только родительская форма и соответствующая дочерняя форма, обратный вызов работает без проблем.

В сценарии создания нескольких родительских форм с соответствующими дочерними формами событие распознается только последней созданной родительской формой, независимо от того, какую дочернюю форму выполнило пользовательское событие. Предположительно, если в каждой родительской форме активирован объект типа listener (внимательный к обратным вызовам пользовательского события), то в момент выполнения пользовательского события должен быть запущен цикл, который прослушивает каждую родительскую форму, что является причиной использования переменной handle, но в результате он запускается только один раз.

Пользовательское объявление события выглядит следующим образом:

  TCreateScheduleEvent = procedure(source: HWND; GroupSchedule: TGroupSchedule) of object;
  TNewScheduleFormEvent = class
  private
    FCreateScheduleForm: TCreateScheduleEvent;
    FHandle: Int64;
  public
    constructor Create(source: HWND);
    property OnCreateScheduleForm: TCreateScheduleEvent read FCreateScheduleForm write FCreateScheduleForm;
    property Source: Int64 read FHandle write FHandle;
    procedure CreateScheduleForm(GroupSchedule: TGroupSchedule);
  end;

//TNewScheduleFrmEvent
constructor TNewScheduleFormEvent.Create(source: HWND);
begin
  inherited Create;
  FHandle:= source;
end;

procedure TNewScheduleFormEvent.CreateScheduleForm(GroupSchedule: TGroupSchedule);
begin
 { Call the registerd event only if there is a listener }
 if Assigned(FCreateScheduleForm) then FCreateScheduleForm(FHandle, GroupSchedule);
end;


Родительская реализация такова:

  TFileListener = class
    procedure CreateScheduleFormEvent(source: HWND; GroupSchedule: TGroupSchedule);
  end;
.........
  private
    { Private declarations }
    FileListener: TFileListener;
    CreateScheduleFormEvent : TNewScheduleFormEvent;
........

procedure TFileListener.CreateScheduleFormEvent(source: HWND; GroupSchedule: TGroupSchedule);
begin
  if FormHandle = source then
    begin
    ...............
    end;
end;

........
//OnCreate
  FileListener := TFileListener.Create();

  FormHandle:= Handle;

  CreateScheduleFormEvent:= TNewScheduleFormEvent.Create(FormHandle);
  CreateScheduleFormEvent.OnCreateScheduleForm:= FileListener.CreateScheduleFormEvent;

//Child form
  propForm:= TfrmPropList.Create(Self);
  propForm.PopupMode:= pmExplicit;
  propForm.Parent:= Parent;
  propForm.CreateScheduleEvent:= CreateScheduleFormEvent;
  propForm.Show;


Реализация дочерней формы такова:

  private
    { Private declarations }
    FCreateScheduleEvent : TNewScheduleFormEvent;
........
  public
    { Public declarations }
    property CreateScheduleEvent: TNewScheduleFormEvent read FCreateScheduleEvent write FCreateScheduleEvent;
......
//Event Execution
  CreateScheduleEvent.OnCreateScheduleForm(CreateScheduleEvent.Source, GroupSchedule);


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

Что я уже пробовал:

Прояснение проблемы:

Дочерняя форма создается из родительской формы

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

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

CreateScheduleFormEvent:= TNewScheduleFormEvent.Create(FormHandle); CreateScheduleFormEvent.OnCreateScheduleForm:= FileListener.CreateScheduleFormEvent; propForm.CreateScheduleEvent:= CreateScheduleFormEvent;

Если существует только одна родительская форма с дочерней формой, событие из дочерней формы правильно воспринимается ее родительской формой.

Если существует несколько родительских форм одного и того же типа, каждая со своим соответствующим дочерним элементом, событие не слышится соответствующими родителями, то есть, если от child1 событие выполняется, оно должно быть услышано parent1, и если оно выполняется от child2, это должно быть услышано от parent2.

В случае нескольких родителей с их соответствующими детьми событие, выполняемое любым из детей, child1 ... child10, слышно только от последнего родителя, созданного parent10 ..

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

1 Ответов

Рейтинг:
2

fisadmaster

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

С помощью этого метода вы можете передать дескриптор родительской формы и имя метода, который будет выполняться, и независимо от того, сколько экземпляров одной и той же формы существует в приложении, он всегда указывает на метод в правильном родительском элементе.