0

I have a main form where I set a handler for the Application.OnMessage event. (Code of this handler is placed in the main form). Then, while running the program, there can be calls to SysUtils.LoadPackage that loads some bpl-package. And after that is loaded, the handler of Application.OnMessage is changed.

I couldn't find what doing this. At least there is not right such code that goes Application.OnMessage := in the package.

One more thing: in the debugger, before LoadPackage, I see OnMessage handler described as Main.TMainForm.AppMessage. All other handlers (such as OnMinimize, OnModalBegin e.t.c.) are nil. And after LoadPackage all events have handlers, described as Vcl.AppEvnts.TMultiCaster.DoMessage.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
Daugawpils
  • 37
  • 1
  • 2
    The package implements its own Application.Onmessage handler perhaps? How can we know without knowing what is in either your application or the bpl. – Dsm Nov 12 '18 at 12:09
  • Well, the obvious thing is that there is code in the package that you loaded that does `Application.OnMessage := ...` and it's pretty hard to imagine that it could be anything else. I mean, how else do you imagine that a property changes? – David Heffernan Nov 12 '18 at 12:27
  • well. maybe, but I couldn't find what doing this. At least there is not right such code that goes `Application.OnMessage :=` at the package. One more thing: in debugger before LoadPackage I see OnMessage handler descrived as `Main.TMainForm.AppMessage`. All other handlers (such as OnMinimize, OnModalBegin e.t.c.) are equal to nil. And after LoadPackage all methods has handlers and desribed as `Vcl.AppEvnts.TMultiCaster.DoMessage`. – Daugawpils Nov 12 '18 at 12:46
  • 1
    Including unit `AppEvents` will through unit's initialization create a `TMultiCaster`, which assigns handlers to (some or all?) `TApplication` events. – nil Nov 12 '18 at 12:55
  • 2
    Set a breakpoint just after InitControls in vcl.controls.initialization. Run application. When the breakpoint is hit, set a data breakpoint for Application.FOnMessage. Run (resume) again. When the data breakpoint is hit, examine the code. – Sertac Akyuz Nov 12 '18 at 13:00
  • If you won't show a [mcve], then you will need to remove this post (because it cannot be answered) and debug your program yourself. – David Heffernan Nov 12 '18 at 13:43
  • Why cannot? Mr. @nil gave right clue. Indeed adding `vcl.AppEvnts` to uses causes this behavoiur. – Daugawpils Nov 12 '18 at 14:25
  • Because this question wouldn't be useful for future readers, which is pretty much what SO is all about. Any answer would be based on guesses, and that's not how we work. We work on facts, and facts require an MCVE. – Jerry Dodge Nov 12 '18 at 14:59
  • 1
    That unit contains the TApplicationEvents component, which can be used to assign application events at designtime. Because you could use multiple components, I think the unit attaches its own event handler, which then forwards any events to the event handlers assigned to all the TApplicationEvent components. It would be nice, of course, if it kept track of existing handlers, because if every bpl is going to do the same trick again, that also implies that TApplicationEvents wouldn't work well at all in applications with multiple packages... – GolezTrol Nov 12 '18 at 16:01
  • Can you try adding `Vcl.AppEvnts` to the main application too? – GolezTrol Nov 12 '18 at 16:28
  • 1
    @GolezTrol you are right that `TApplicationEvents` is a multicaster, it delegates `TApplication` events to every `TApplicationEvents` instance, allowing multiple Forms, components, etc to receive the same app events without stepping on each other's toes trying to assign handlers to `TApplication` directly. So yes, the solution to the OP's issue is to add `TApplicationEvents` to the `MainForm`. – Remy Lebeau Nov 13 '18 at 06:08
  • Yes. Just including the unit in the main application should do the trick already, because that will assign the multicaster before you assign your own event handler. But assigning your own will overwrite the one assigned by the multicaster, so I agree it's cleaner to use a TApplicationEvents in the main application too. (All this is assuming that Vcl.AppEvnts Initialize won't fire again when the package is loaded, but I don't think it will, although I must admin my experience with runtime packages is limited.) – GolezTrol Nov 13 '18 at 10:56

1 Answers1

5

The package in question uses an internal instance of TApplicationEvents, which is a multicaster that intercepts TApplication events and delegates them to every TApplicationEvents instance in the application, allowing multiple Forms, components, etc to receive the same app events without stepping on each other's toes trying to assign handlers to TApplication directly.

So, to coexist with the package, the solution is to add a TApplicationEvents to your MainForm and assign a handler to its OnMessage event, instead of assigning a handler to the TApplication.OnMessage event directly.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770