⑵ Define Process Type
Once you decide to generate an event, define how the event is handled, which is the type that determines the event-handling process. In most cases, the type of the event-handling procedure that is defined is a simple notification type (tnotifyevent) and a defined event type.
Notifying events only tells you that a particular event has occurred, without describing when and where. Notification events are used with only one tobject type of parameter, which is sender. However, the process of all notification events knows what happens and occurs in that part. For example, the Click event is the notification type. When you write the process for the click event, you know what the Click event occurred and which part was pressed. Notification events are one-way processes. No feedback mechanism provided.
In some cases, it's not enough to know just what happened and what happened in that part. If the key event occurs, the event handling process often knows which key the user pressed. In this case, you need an event-handling procedure that contains parameters for the necessary information about the event. If the event is generated in response to a message, the argument passed to the event is best derived directly from the message parameter.
Because all event-handling procedures are procedures, the only way to return information from an event-handling process is through the Var parameter. Custom parts can use this information to determine whether and how events are handled after the user event handling process is executed.
For example, all keystroke events (OnKeyDown, onkeyup, and onkeypressed) pass key values through the Var argument named key. In order for the application to see the different keys contained in the event, the event-handling process can change the value of the key variable.
⑶ declaring events
Once you have decided on the type of event handling process, you will be prepared to declare the method pointers and attributes for the event. To make it easier for users to understand the functionality of an event, you should give the event a meaningful name, and be consistent with the name of a similar property in the part.
The names of all standard events in Delphi begin with "on". This is only for convenience, the compiler does not enforce it. Object Inspector is to look at the attribute type to determine whether the property is an event, and all method pointer properties are treated as events and appear in the event page.
⑷ Invoke Event
Generally, it is best to focus the call on the event. This means that a virtual method is created in the part to invoke the user's event-handling process and provide any default processing. When calling an event, consider the following two points:
Empty events must be allowed
User can override default processing
It is not allowed to cause an error in an empty event handling process to occur. That is, the normal functionality of a custom part cannot depend on the response from the user's event-handling process. In fact, an empty event-handling process should produce the same results as a no event-handling process.
Parts should not require users to use them in a special way. Since an empty event-handling process should act like a no event-handling process, the code that invokes the user event-handling procedure should look like this:
If assigned (onclick) then OnClick (Self);
{Perform default processing}
Instead of having this code:
If assigned (OnClick) then
OnClick (Self)
Else
...; {Perform default processing}
For certain kinds of events, users may want to replace the default processing and even delete all responses. To support user implementation of this function, you need to pass the Var parameter to the event handler and detect a value when the event handling process returns. The null event handling process has the same effect as the no event handling process. Because the null event processing does not change any of the Var parameter values. Therefore, the default processing always occurs after an empty event-handling procedure is invoked.
For example, in handling the Key-press event, the user can suppress the default processing of a part by setting the value of the Var parameter key to a null character (#0), as follows:
If assigned (OnkeyPress) then OnkeyPress (Self key);
If key <> #0 then {perform default processing};
The actual code will differ slightly from this, because it only handles window messages, but the processing logic is the same. By default, a part invokes any user-assigned event-handling process and then performs standard processing. If the user's event-handling process sets the key to NULL, the part skips the default processing.
19.2.2.3 processing messages
A key aspect of traditional Windows programming is handling messages that Windows sends to applications. Delphi has helped you with most of the ordinary messages, but it is possible that Delphi did not have to process the process in creating the parts, had to process the messages by itself, or created new messages that needed to be processed.
Learn to master the message Processing Delphi, to master the following three aspects:
Understanding Message Processing Systems
Modify (change) the message processing method
Create a new Message processing method
1. Understanding Message Processing System
All Delphi objects have a mechanism for handling messages, such as invoking a message-handling method or a message-handling process. The basic idea of message processing is that objects receive some kind of message and dispatch them by invoking the method corresponding to the received message, and calling the default processing if there is no specified method corresponding to the message. The following illustration shows the message dispatch system:
The Delphi Part gallery defines a message delivery system that converts all Windows messages, including user-defined messages, directly to object method calls. There is generally no need to change this message delivery system, as long as the message processing method is established.
What's in the ⑴windows message?
A Windows message is a data record that contains a number of useful fields. The most important thing in a record is an integer size value that identifies the message. Windows defines a large number of messages. The library unit messages declares the identity of all messages. Other useful information in the message includes two domain parameters and result fields. Two parameters are 16-bit and 32-bit respectively. Windows code always references them with wparam and lparam.
Initially, Windows programmers had to remember every parameter that was included. Now, Microsoft has named this parameter. This makes it easier to understand the information that accompanies these messages. For example, the parameters of the WM_KEYDOWN message are called Vkey and Keydata, which gives more descriptive information than the wparam and lparam.
Delphi defines the specified record type for different types of messages. such as mouse messages passing mouse events in the long parameter x, y coordinates, one in the high word, one in the low word. Using mouse message logging, you don't need to care which word is which coordinates, because these parameters are referenced by the name xpos and Ypos replaced the Lparamlo and LPARAMHI.
⑵ Dispatch method
When an application creates a window, a window procedure is registered in Windows kernel. A window procedure is a function that handles window messages. Traditionally, the window process includes case expressions, each of which is a message to be processed by the window. When you create a window each time, you must establish a complete window procedure.
Delphi simplifies message delivery in the following three ways:
Each part inherits the complete message dispatch system
The dispatch system has default processing. The user only needs to define the processing method of the message that wants to respond
You can modify the part of message processing by relying on inherited methods to do most of the processing
The biggest advantage of this messaging system is that users can safely send any message to any part at any time. If the part does not define a processing method for the message, the default processing resolves the problem, usually ignoring it.
Delphi registers a method named Mainwndproc as a window procedure for each type of part of the application. Mainwndproc contains an exception handling block that completes a virtual method of sending message records from Windows to WndProc, and handles exceptions by calling the Application object's HandleException method.
Mainwndproc is a static method and does not contain a specified method of handling any messages. The customization process occurs in WndProc, because each part type can override the method to fit a specific need.
The WndProc method checks for each condition that affects their handling to catch messages that are not. For example, when dragged, the part ignores keyboard events, so Twincontrol's WndProc transfers keyboard events only when there is no drag. Finally WndProc calls the dispatch method, which is a static method inherited from TObject and determines what methods are used to process the message.
Dispatch uses the MSG domain of the message record to determine how to dispatch a particular message. If the part has already defined a processing method for the message, dispatch calls the method, whereas dispatch invokes the default processing method.
2. Change the message processing method
Before changing the message handling method for a custom part, figure out what you really want to do. Delphi translates most Windows messages into events that can be handled by part writers and parts users. Generally speaking, you should change the event handling behavior rather than change the message handling behavior.
To change the message handling behavior, overwrite the message processing method. You can also provide a capture message to prevent a part from processing the message.
⑴ Overlay Treatment Method
To change the way a part handles a particular message, overwrite the way that message is processed. If the part does not process the message, you need to declare a new message-handling method.
To override the message processing method, you declare the new method in the part with the same message index. Do not use the override directive, you must use the message command and the corresponding messages index.
For example, to override a method that handles WM_PAINT messages, you should declare the Wmpaint method:
Type
Tmycomponent=class (...)
Procedure Wmpaint (var message:twmpaint); Message wm_paint;
End
⑵ using message parameters
Within the message processing method, custom parts access all parameters of the message record. Because the message is always the Var parameter, the event-handling process can change the value of the parameter if necessary. The result field is a parameter that changes frequently. Result is the return value of the message that is referred to in the Windows document: returned by SendMessage.
Because the type of the message parameter for the message processing method changes with the message being processed, you should refer to the name and meaning of the parameter in the Windows message document. If you want to use old-style message parameters (WParam, lParam) for some reason, you can work with the common type tmessage to determine messages.
⑶ Capture Message
In some cases, you might want a custom widget to ignore some kind of message. That is, the blocking part sends the message to its processing method. To capture messages like that, you can override the virtual method WndProc.
The WndProc method masks the message before it is passed to the dispatch method. It decides which method to process the message in turn. By overwriting WndProc, parts get the chance to filter them before sending messages.
Typically, this covers WndProc as follows:
Procedure Tmycontrol.wndproc (var message:tmessage);
Begin
{Determines whether to proceed with the process}
Inherited WndProc (message);
End
The following code is part of the Tcontrol WndProc. Tcontrol defines the entire range of mouse messages that will be filtered when the user drags and places control.
Procedure Tcontrol WndProc (var message:tmessage);
Begin
if (message.msg >= Wm_movsefirst) and
(message.msg <= Wm_mouselast) Then
If dragging then
Dragmousemsg (twmmouse (message)) {Handle Drag}
Else
... {Normal processing of other}
... {Otherwise normal processing}
End