How does Delphi's KeyPreview work?
Asked Answered
C

4

11

A colleague and myself were debating over which way was less of a burden on the system resources. (Note: this is not the question I want an answer to. Rather the title and the line below in bold is the question I seek an answer for.)

1. Using KeyPreview to get the keypresses on a form.

or

2. Using defining an OnMessage procedure and handling it there.

At first glance it seems KeyPreview would be less of a system burden since defining an OnMessage procedure results in our program checking every message that comes in. Note messages we don't care about would cause it to jump out by the first if statement. That is at worst we would have an if statement executed for every message.

But we're wondering how Delphi deals with the KeyPreview property... We wonder if Delphi internally defines its own OnMessage and looks at the messages to then trigger the events that are related to keypresses.

If this is the case then would both approaches be about the same?

Cabasset answered 28/6, 2011 at 15:46 Comment(4)
Have a look at the source, and you can find out. Basically, it is using a message handler.Induplicate
That's what I was thinking, I just haven't gotten to it yet.Cabasset
I am sure you mean KeyPreview instead of OnKeyPreview.Peace
Indeed I did. I have changed the title. ty.Cabasset
P
6

The KeyPreview functioning:

The KeyPreview property of the current active form is checked for the KeyUp-, KeyDown- and KeyPress- event handlers of the current active control. I.e.: a key press in any control results in the check of the form's KeyPreview property.

If that property is True, the event handler in question invokes the event handler of the form prior to that of itself. If the form's event handler does not change the key value to 0 (or #0, depending on KeyPress or KeyDown/KeyUp), then the active control's event handler takes back over, otherwise the event is considered handled.

Compared to Application.OnMessage:

So setting the key value to 0/#0 in a form's event handler is synonymous to setting the Handled parameter of Application.OnMessage. In this, there is virtually no difference. But since OnMessage is called very early in the dispatching process, there is a theoretical gain in performance because the message is not being dispatched any further. When you leave Handled to False, there is no difference at all, because the KeyPreview property is always checked, whether it is set or not.

The main difference that is left is that you have to set the KeyPreview of áll Forms to True, ánd implement and maintain for each of all forms the appropriate event handlers. Compare this to having just one event handler for Application.OnMessage. That is: assuming you could do with just one routine for all of your forms.

Peace answered 28/6, 2011 at 18:52 Comment(0)
B
7

As others have already said - there is probably no noticeable difference.

I just wanted to point out an exellent article by Peter Below on that topic: A Key's Odyssey archive

This article describes the key message processing as implemented in Delphi 2007 for Win32 VCL forms applications. A few things have changed in this area compared with Delphi 7, but these are mostly additions that I will highlight when we get to them. Most of this code has survived basically unchanged since the times of Delphi 1, a tribute to the robustness of the design. If you are in a hurry or not interested in all the details you can refer to the outline in the summary for a condensed overview.

Brookes answered 28/6, 2011 at 18:34 Comment(1)
+1 Aaaah, Peter Below. The Jon Skeet of Delphi. Long time since I read someting from him. He seems to have vanished.Hallie
P
6

The KeyPreview functioning:

The KeyPreview property of the current active form is checked for the KeyUp-, KeyDown- and KeyPress- event handlers of the current active control. I.e.: a key press in any control results in the check of the form's KeyPreview property.

If that property is True, the event handler in question invokes the event handler of the form prior to that of itself. If the form's event handler does not change the key value to 0 (or #0, depending on KeyPress or KeyDown/KeyUp), then the active control's event handler takes back over, otherwise the event is considered handled.

Compared to Application.OnMessage:

So setting the key value to 0/#0 in a form's event handler is synonymous to setting the Handled parameter of Application.OnMessage. In this, there is virtually no difference. But since OnMessage is called very early in the dispatching process, there is a theoretical gain in performance because the message is not being dispatched any further. When you leave Handled to False, there is no difference at all, because the KeyPreview property is always checked, whether it is set or not.

The main difference that is left is that you have to set the KeyPreview of áll Forms to True, ánd implement and maintain for each of all forms the appropriate event handlers. Compare this to having just one event handler for Application.OnMessage. That is: assuming you could do with just one routine for all of your forms.

Peace answered 28/6, 2011 at 18:52 Comment(0)
M
4

The best answer would be, measure it. Most likely neither one is going to place any noticeable "burden" on the system, and if you don't notice it when you're specifically looking for it, then your users won't either. So just go with whichever one's easier to understand in case you need to come back to that code sometime in the future.

Mafalda answered 28/6, 2011 at 16:20 Comment(3)
+1 Thank you for your answer. I agree that either way will likely be unnoticeable. I have made more clear in my question what I am really looking for.Cabasset
I expect the difference to be negligible (unmeasurably small), and that whatever code you write to do the the handling would be the problem, not the invoking of your handler.Empyrean
You don't need to measure it. It's insignificant. Your computer is not stretched by handling input messages. Come on, it can do a gazillion mega ops per nano second. How fast can you type?!! Just choose the mechanism that is most natural to the problem at handChainman
C
4

The bottom line here is that you can't generate input quick enough to make the computer even notice. The computer would not be troubled if you produced input messages at rates hundreds or even thousands greater than you typically do.

You won't be able to measure the difference between handling something in OnMessage and using KeyPreview.

So the decision as to which to use comes down to which is most convenient. If you need handling to happen at an application wide level, and you don't have a common base class for all your forms, then you use OnMessage. If you want different behaviour for different forms then you need to use KeyPreview.

Personally I strongly recommend refactoring so that all forms in your projects derive from a common base (a subclass of TForm). This allows you much more flexibility. Done this way you can, for example, use the KeyPreview mechanism to apply intervention points for all forms in your applications.

As for how KeyPreview is implemented, the input messages get redirected in KeyDown, KeyPress etc. in TControl. To learn more read the source code.

Chainman answered 28/6, 2011 at 22:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.