The main message loop is in the Run procedure, which starts immediately after the specified forms and applet are created. You can easily replace this procedure with your own (for example, to provide higher or lower priority for some types of messages). In the case of the MCK project, for this it is enough to place your Run procedure directly in the main file of the DPR project, before the INCLUDE directives, which include the generated application start code. In the case of programming without MCK, you write the call to the Run procedure yourself: you can not call it, but write your own message loop.
Dispatching is that for each message selected from the queue, TranslateMessage and DispatchMessage are called. These are API functions that handle routing messages to specified windows. After that, messages go to the global procedure WndFunc *. This is where the main message dispatcher resides in KOL. Its main task is to find an object corresponding to the window indicated in the message (hwnd field). Previously, the GetProp API function was used to map a visual object to a window in KOL, but more recently it was decided that the so-called "custom" window attribute field is usually not involved, and using it gives a slightly faster and shorter code. As a result, in KOL, a window can be bound to an object either in one way or another, depending on the value of the USE_PROP option.
When (and if) the WndFunc procedure has received the address of an object (it must be a TControl object), it can already call its methods. This is where the WndProc method is called, which carries out further processing of window messages. But if the address of the object could not be obtained, that is, the message is intended for a window that does not have a TControl object attached to it, then the WndProc method of the Applet object is called, and if it is not assigned, then the message is passed to the system's default handler, the DefWindowProc procedure.
A window may not be associated with a specific TControl object in several cases. This can be a subordinate service window for some window object (for example, the drop-down list and the input field for the combo box itself are organized in the system as children of the combobox itself). It can be a window that you created without using TControl, your own code. Or the window is still being created and the object has not yet been bound.
All TControl objects have the same WndProc procedure, and only the most common messages are handled in it. The most important thing is that before starting to process the received message, this method first tries to "disown" it, if possible. Namely, the algorithm is as follows.
First, if the Applet variable exists and an OnMessage event handler is assigned to it, then that (your) handler is called first. If the OnMessage event handler returns FALSE, then the message is considered fully processed, and it is no longer processed in any way, including by the default message handling procedures.
Second, if an OnMessage event handler is assigned to the TControl object itself that received the message, then this (your) handler is called. Again, if the event handler returns FALSE, then the message is considered fully processed and all processing for that message ends.
|
Of course, returning TRUE to the WndProc procedure from the OnMessage event handler (and other handlers) does not mean that the system will necessarily agree with your instructions. If any requirements for processing the message are not met, then there is a possibility that the system will send this message again and again until it receives what it wants. For example, if in response to the WM_PAINT message the system does not return the value 0 (the Rslt parameter), the system will assume that the application for some reason does not want to fulfill the order immediately and wants to postpone it for some time. And he will send a message again, and again. There is a possibility that an incorrectly written message handler can seriously slow down the operation of the application; you must be careful when writing the code for the OnMessage event. |
Third, and this is the most important point, the executor of the message handlers dynamically attached (by the AttachProc, AttachProcEx methods) to the object is called. These handlers are intended primarily for internal use within the KOL library itself, to add the required message handling functionality for specific kinds of window objects. But they can be used by programmers as well, just like the fixed custom OnMessage handler. If such dynamic handlers are attached (and this is true for almost all window objects), then the EnumDynHandlers function begins to work. Its task is to view all dynamic handlers (from the last attached to the first), calling them one by one, at least until the next handler in the chain "says"
In the picture attached above, I tried to depict the message dispatching process. And only if the specified message handling is not found or has allowed the message to be processed further, the TControl.WndProc method will handle the most common messages. Namely: WM_CLOSE, WM_SIZE, WM_SYSCOMMAND, WM_SETFOCUS, WM_SETCURSOR, WM_CTLCOLORxxxx, WM_COMMAND, WM_KEYxxxx. And for all other messages will call the default system handler.