Stopping events in Delphi 7

I ran into a problem in Delphi 7 about event propagation (due to my ignorance).

I am invited to dynamically attach the OnMouseUp event OnMouseUp on some controls in the form (and I'm fine with this thing), but if OnMouseUp present, the OnMouseUp event on this control should not be processed.

Background

If you ask the reason for this, well, I am responsible for changing the old application for monitoring production (sigh), which now should take into account the conditional behavior of some controls, in direct reaction to the previous click on a special function button.

Some of these controls already have an OnClick event OnClick ; the first decision the team faced was to intervene in every OnClick handler in a timely manner and manage contextual actions in relation to the status of a special function button.

I suggested using object-oriented design already for application forms: they all inherit from the same user ancestor object, so I planned to add an initialization method there for dynamically attaching OnMouseUp events to which are declared for support in subclasses.

Necessity

I do not ask you to confirm or interrogate about the (possible absence) goodness of design about all this (by the way, after many thoughts and arguments, this seemed to be the way we can walk with less pain); my problem is that for such a design, I have to let the dynamically linked OnMouseUp event OnMouseUp stop the event from propagating to previous OnClick events on these controls.

Is this possible with Delphi 7?

+6
source share
2 answers

Note that the following here does not explicitly answer the question. It is rather a proposal to redesign the concept (redirect OnClick events instead of adding additional OnMouseUp). This is about how to redirect the OnClick event handler (if assigned) of all components (can be filtered, if necessary) to another (regular) OnClick event handler. It also includes a way to restore them to their original state.

In the following example, I will try to show you how to replace, and then additionally restore the OnClick event handlers (if the component wrote several) to a specific one. This is done for all components in which the OnClick event is published, so you do not need to know in advance if the component class has an OnClick event, available or not (but you can simply change it to use only a specific class).

The code consists of the following:

  • OnSpecialClick is an event handler in which all OnClick events will be bound when the ReplaceOnClickEvents procedure is called, note that it must be published in order to be visible to RTTI !!!

  • Button1Click - is an old event handler that needs to be replaced, attached to the Button1.OnClick event during development

  • ReplaceOnClickEvents - a method that iterates through all components of the form and checks whether the current iterative event handler has OnClick; if so, it saves it to the backup collection and replaces this event handler with OnSpecialClick

  • RestoreOnClickEvents - a method that restores the original OnClick event handlers; it iterates through a collection of backups and assigns event methods to its instances of stored components.

  • CheckBox1Click - this click event flag means switching between normal and special modes (CheckBox1 checks the status means special mode), only this OnClick event is not replaced by a call to ReplaceOnClickEvents (because you cannot restore normal mode)

And here he is:

 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. 
+6
source

As both TLama and TOndrej said, there are several ways to accomplish what you are trying:

  • Perform if Assigned(Control.OnMouseUp) then Exit; in the OnClick event OnClick

  • To “ OnClick ” an OnClick event when assigning OnMouseUp (and vice versa)

Both approaches will achieve what you have described in detail, although "not assigning" the OnClick event will be best for performance (to an infinitely small degree) since you will not execute the if repeatedly.

+1
source

Source: https://habr.com/ru/post/915175/


All Articles