简体   繁体   中英

How do I intercept form creation outside of the form in Delphi?

I'm trying to find a generic way to know when any form has been created with windows events or something of the sort. Currently I'm listening for WM_PAINT events within TApplicationEvents.OnMessage and then when I detect a Msg.hwnd I use FindControl() and see if the control is TForm . Then I know this form is being opened and I can then do some styling that is uniform across the hundreds of forms in the application.

When I listen for WM_CREATE events instead I get nothing. I'm not sure why. I was thinking this would tell me the form has been created, but evidently it doesn't. At the moment, there are a couple of timing issues that cause only a few forms to render, and then a split second later my styling kicks in. I only find this in some cases, and the majority of the cases it works just fine. So you have the form opening up on its original styling only to have it change a split second later - in a few cases.

The moment I detect a form like this, I also reassign its OnClose event so that I can perform some operation when the form closes, and then I redirect it to its original OnClose event handler. I've tried doing the same thing with its OnCreate and OnShow events, but that doesn't fire at all this way. The OnClose have been working perfectly, though.

I need my styling to kick in first before the form is shown. Any ideas?

I'm trying to find a generic way to know when any form has been created with windows events or something of the sort.

At the Win32 level, there are events related to window creation, such as:

  • SetWindowsHookEx() hooks, such as the HCBT_CREATEWND notification of a WH_CBT hook.

  • SetWinEventHook() events, such as EVENT_OBJECT_CREATE .

The problem with this approach is that the events are triggered after the underlying HWND struct has been allocated, but before it has been sent WM_(NC)CREATE messages. So, for instance, calling FindControl() inside a handler for these events won't work, because the VCL has not yet established the link between the HWND and the TForm object.

At the VCL level, there are no global events for Form creation. There is only the TForm.OnCreate event. If you need to handle that globally for all of your Forms (or even just some of them), you should create a base TForm class that overrides the virtual DoCreate() method (and/or other virtual methods, like CreateWnd() , PaintHandler() , WndProc() , etc), and then derive your desired TForm classes from this base class.

When I listen for WM_CREATE events instead I get nothing. I'm not sure why.

WM_CREATE is not a posted message. The Win32 CreateWindow/Ex() API sends this message directly to the window's message procedure while creating the window. The message does not go through the creating thread's message queue, and thus will never appear in the TApplication(Events).OnMessage event.

At the moment, there are a couple of timing issues that cause only a few forms to render, and then a split second later my styling kicks in. I only find this in some cases, and the majority of the cases it works just fine. So you have the form opening up on its original styling only to have it change a split second later - in a few cases.

If you are doing custom styling inside of a WM_PAINT handler, there should be no timing issues.

On the other hand, why are you not utilizing the VCL's built-in styling system? For instance, you can use TCustomStyleEngine.RegisterStyleHook() to register your own styling hook derived from TStyleHook for your desired classes.

Or, you could simply define your own custom Style for the VCL to use natively, no need to write any code for this.

The moment I detect a form like this, I also reassign its OnClose event so that I can perform some operation when the form closes, and then I redirect it to its original OnClose event handler. I've tried doing the same thing with its OnCreate and OnShow events, but that doesn't fire at all this way.

Correct, because the TForm object has already been created and its window is visible onscreen before it receives WM_PAINT messages from the OS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM