Остановить распространение событий в Delphi 7
Я застрял на проблеме в Delphi 7 О распространении событий (из-за моего невежества).
меня просят динамически присоединить OnMouseUp
обработчик событий на некоторых элементах управления в форме (и я в порядке с этой вещью), но если OnMouseUp
присутствует OnClick
событие на этом элементе управления не должно обрабатываться.
фон
если вы спрашиваете причину этого, ну, я отвечаю за изменение старого приложения мониторинга производства (вздох), которое из теперь on должен учитывать условное поведение для некоторых элементов управления, в прямом ответе на прежний щелчок по специальной функциональной кнопке.
некоторые из этих элементов имеют OnClick
обработчик событий уже; первое решение, которое придумала команда, было пунктуально вмешиваться в каждый OnClick
обработчик и управление контекстными действиями по отношению к статусу кнопки специальной функции.
я предложил воспользоваться объектно-ориентированным дизайном уже на месте для формы приложений: все они наследуются от одного и того же пользовательского объекта-предка, поэтому я планировал вставить туда метод инициализации для динамического присоединения OnMouseUp
события для элементов управления, которые объявлены для поддержки его в подклассах.
необходимость
Я не прошу подтверждения или вопроса о (возможном отсутствии) благости дизайна обо всем этом (кстати, после многих размышлений и рассуждений это, казалось, путь, по которому мы можем идти с меньшей болью); моя проблема разве что для такого дизайна я должен был бы позволить динамически подключаться OnMouseUp
обработчики событий останавливают распространение событий до существующего OnClick
события на этих элементах управления.
возможно ли это с Delphi 7?
2 ответов
обратите внимание, что следующее явно не отвечает на вопрос здесь. Это скорее предложение по перепроектированию концепции (перенаправление событий OnClick вместо добавления дополнительного OnMouseUp). Речь идет о том, как перенаправить обработчик событий OnClick (если он назначен некоторым) всех компонентов (при необходимости может быть отфильтрован) на другой (общий) обработчик событий OnClick. Он также включает в себя метод восстановления их в исходное состояние.
в следующем примере я попробуйте показать, как заменить, а затем при необходимости восстановить обработчики событий OnClick (если компонент написал некоторые) конкретным. Это делается для всех компонентов, имеющих опубликованное событие OnClick, поэтому вам не нужно заранее знать, доступно ли событие onclick в классе компонентов (но его можно очень просто изменить, чтобы использовать только определенный класс).
код состоит из следующий:
OnSpecialClick - это обработчик событий, к которому будут привязаны все события OnClick при вызове процедуры ReplaceOnClickEvents, обратите внимание, что он должен быть опубликован, чтобы быть видимым для RTTI !!!
Button1Click - представляет здесь старый обработчик событий, который должен быть заменен, он привязан к Button1.Событие onclick на дизайн времени
ReplaceOnClickEvents - метод, который перебирает все компоненты на форме и проверяет
если текущий итерационный имеет назначенный обработчик событий OnClick; если это так, он сохраняет его в резервную коллекцию и заменяет этот обработчик событий OnSpecialClickRestoreOnClickEvents - метод, который восстанавливает исходные обработчики событий OnClick; это выполняет итерацию по коллекции резервных копий и назначает методы событий ее сохраненным экземплярам компонентов
CheckBox1Click - этот флажок click event предназначен для переключения между общим и специальным режимом (CheckBox1 checked state означает специальный режим), только это событие OnClick не заменяется вызовом ReplaceOnClickEvents (потому что вы не сможете восстановить режим обратно в нормально)
и вот это:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TypInfo, StdCtrls, Contnrs;
type
TEventBackup = class
Component: TComponent;
OnClickMethod: TMethod;
end;
type
TForm1 = class(TForm)
Button1: TButton;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
procedure ReplaceOnClickEvents;
procedure RestoreOnClickEvents;
published
procedure OnSpecialClick(Sender: TObject);
end;
var
Form1: TForm1;
EventBackupList: TObjectList;
implementation
{$R *.dfm}
procedure TForm1.OnSpecialClick(Sender: TObject);
begin
ShowMessage('Hi, I''m an OnSpecialClick event message!');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('Hi, I''m just that boring original OnClick event message!');
end;
procedure TForm1.ReplaceOnClickEvents;
var
I: Integer;
Component: TComponent;
EventMethod: TMethod;
EventBackup: TEventBackup;
begin
for I := 0 to ComponentCount - 1 do
begin
Component := Components[I];
if Component = CheckBox1 then
Continue;
if IsPublishedProp(Component, 'OnClick') then
begin
EventMethod := GetMethodProp(Component, 'OnClick');
if Assigned(EventMethod.Code) and Assigned(EventMethod.Data) then
begin
EventBackup := TEventBackup.Create;
EventBackup.Component := Component;
EventBackup.OnClickMethod := EventMethod;
EventBackupList.Add(EventBackup);
EventMethod.Code := MethodAddress('OnSpecialClick');
EventMethod.Data := Pointer(Self);
SetMethodProp(Component, 'OnClick', EventMethod);
end;
end;
end;
end;
procedure TForm1.RestoreOnClickEvents;
var
I: Integer;
EventBackup: TEventBackup;
begin
for I := 0 to EventBackupList.Count - 1 do
begin
EventBackup := TEventBackup(EventBackupList[I]);
SetMethodProp(EventBackup.Component, 'OnClick', EventBackup.OnClickMethod);
end;
EventBackupList.Clear;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if CheckBox1.Checked then
ReplaceOnClickEvents
else
RestoreOnClickEvents;
end;
initialization
EventBackupList := TObjectList.Create;
EventBackupList.OwnsObjects := True;
finalization
EventBackupList.Free;
end.
как сказали и Тлама, и Тондрей, есть несколько способов выполнить то, что вы пытаетесь:
сделать
if Assigned(Control.OnMouseUp) then Exit;
наOnClick
обработчик события"отменить назначение"
OnClick
событие при назначенииOnMouseUp
(и наоборот)
оба подхода позволяют достичь того, что вы полная, хотя "назначая" на OnClick
событие будет лучше всего для производительности (в бесконечно малой степени), так как вы не будет выполнять if
неоднократно заявление.