PDA

View Full Version : Ideas to create an event broadcasting class



cronodragon
23-05-2007, 08:01 PM
I wrote a class that registers methods (event listeners) in a linked list. The problem is I'm using a fixed procedural type like this:

TEventListener = procedure (Source: TObject; const Parameters: array of const) of object;

But I would like to know a way I could make this so that I could register any procedure with any set of parameters, and also that I could broadcast the event assigning those parameters.

Any ideas?

Regards!

jdarling
23-05-2007, 08:07 PM
Read the source code for Pascal for Delphi from RemObjects. It takes A LOT of assembly code and thunking to do it properly, but it can be done. One thing that helps, limit down the calling structure of your methods (IE: Don't support CDECL and the others, only support PASCAL methods).

cronodragon
23-05-2007, 10:13 PM
Hmm, I could program in assembly, but that might bring new problems.

Maybe I should create a class that wraps the procedural type, and helps passing the right parameters. Indeed there could be many way to do this, the thing is finding the one that needs the less effort to register and broadcast an event.

savage
23-05-2007, 10:35 PM
Basically OP really should support a delegate system so that that sort of functionality come out of the box.

cronodragon
24-05-2007, 01:35 AM
I think the delegate system comes from Design Patterns (or prehistory of DP), not from OOP, so I don't blame Delphi for not having it. Experience teaches that design patterns are a bad idea in most cases, since in most cases they are used as the formula to solve any problem. Those should be used only when they are really necessary. That's my case.

Mirage
24-05-2007, 06:01 AM
I use a kind of Software Bus, introduced by N. Wirth in his Programming on Oberon. The idea is in object-oriented (actually extensible record-oriented in the original) message system:


TMessage = class // Base message class
end;
CMessage = class of TMessage;

TMessageHandler = procedure(const Msg: TMessage) of object;

...

TWindowResizeMsg = class(TMessage) // Example: this message is sent by window manager when its size changes
OldWidth, OldHeight, NewWidth, NewHeight: Single;
constructor Create(AOldWidth, AOldHeight, ANewWidth, ANewHeight: Single);
end;

...

procedure TRenderer.HandleMessage(const Msg: TMessage);
begin
...
if Msg.ClassType = TWindowResizeMsg then with WindowResizeMsg(Msg) do begin
... // handle window size change
end end else if Msg.ClassType = TWindowMoveMsg then ...
end;



You can register a chain of message handlers (TMessageHandler) and handle (or ignore) within them any message of any kind. All parameters needed (also any number of any kind) are incapsulated in a message class. This is really secure and useful.

In Delphi you have to use a chains of annoying if-then-else operators. In Oberon the WITH operator is acting like the CASE operator in Delphi but for testing classes and used for software bus. Also the IS operator in Oberon takes just one operation to perform the test. But CodeGear don't care at all. :evil:
In Delphi we have class helpers and other useless stuff instead. :evil:

UPD: I forgot about sending code.
In OS message handler:


...
function WindowProc(WHandle: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
...
case Msg of
...
WM_SIZE: if wParam = SIZE_MINIMIZED then
Core.HandleMessage(TWindowMinimizeMsg.Create) else
Core.HandleMessage(TWindowResizeMsg.Create(0, 0, lParam and 65535, lParam shr 16));


Core.HandleMessage will deliver the messages where needed.