Please enable JavaScript to view this site.

KOL/MCK - User Guide

I didn't even notice the elephant ...

(Krylov's Fable)

 

The idea of ​​the need for this chapter came to me when, once again, looking at the forum, I found a question that had already been asked many times, was answered many times, entered into the FAQ and FAQ, but continues to be asked again and again, and sometimes even by people, who started writing on KOL not yesterday. I hope that having another source with answers to such questions will help reduce the number of such errors, leaving room on the forum for more meaningful discussions. Some of the problems presented here have already been described in the relevant sections of this book. However, it will probably not be superfluous to bring them all together and discuss in even more detail. I'll try to sort the errors by their repetition rate: the first will be the ones with the highest rating in the list of questions from the developers.

 

 

1. Assigning an event handler using the MakeMethod function and typecasting to TOnSomeEvent. ("Why isn't my handler responding to the event?")

 

Usually a similar problem occurs among people who are even quite familiar with the Pascal language, but do not think especially about what machine code is formed as a result of the compiler's work. / Don't worry, the vast majority of programmers don't think about it. And they do the right thing: that is why compilers exist to think not about what machine code will be obtained from the source code in a High Level Language, but to think only about the problem to be solved. /

 

It looks like this. You are not trying to assign an object method to an event handler, but a regular procedure. For example, like this:

 

procedure MyOnClick (Sender: PObj);
begin
 ... some code ...
end;
...
MyControl.OnEvent: = TOnEvent (MakeMethod (nil, @ MyOnClick));

 

At first glance, everything is correct here, and the description of the MyOnClick function is quite consistent with the description of the handler type.

TOnMessage = procedure (Sender: PObj) of object;

 

But in fact, this description is not entirely correct, namely, the matter is in the boldface phrase of object, which indicates to the compiler that a handler of this type should not be a simple procedure, but a method of an object. The difference between a method and a simple procedure is, in fact, in the presence of a hidden additional (first in order) parameter - a pointer to the object for which the method is called. In order to formally reconcile this discrepancy in the number and order of parameters, it is enough to add one more parameter, just the first in order, to a simple procedure. Its name, of course, does not matter; the type can be a pointer or any other type of the same size. For example, the following fix to the handler header will put everything in place:

procedure MyOnClick (DummySelf, Sender: PControl);

 

Why didn't the previous version work? The explanation is quite simple: instead of the formal Sender parameter, an object pointer nil fell (exactly in accordance with how your method was "created" by the MakeMethod function), and the Sender parameter itself did not reach the handler at all, being left out.

 

And if we remember about the implementation of the parameter passing mechanism in Pascal procedures, it becomes clear why the incorrect version of the header did not necessarily lead to much more fatal consequences. The first three parameters, which fit into double words (32 bits on the PC platform, or 4 bytes), are transferred through the processor registers EAX, EDX and ECX. The absence of one parameter in the description of the handler led to the confusion in the procedure of the order of the parameters passed through the registers, and nothing more. Note that in the case of an agreement on passing parameters through the machine stack, as it happens in C, or when using the stdcall directive, the very first attempt to access an incorrectly declared function would most likely lead to a stack level violation and an immediate application crash. Perhaps, in this case, there would be more sense in such behavior: at least, it would become clear immediately that something is really wrong on this site - compared to the tacit disregard of the processor of his duties, in our case. However, if an incorrectly passed parameter is used in the handler, then access to the fields of the object, which was replaced by the nil pointer, will also be immediately detected when trying to execute the handler.

 

 

2. "Can't install MCK", "compile MCK application", asks for some designintf file, proxies ", and the like

 

Some people who ask this question sometimes get straight to the point and ask me to send them this ill-fated file. In fact, such a file is not needed at all, and the only problem is not having read the instructions for creating an MCK project carefully enough. All you need to do is close the VCL project prototype and open the "true" MCK project - with the name specified in the projectDest property of the TKOLProject component.

 

Sometimes the same trouble happens with the previously created MCK project. The reason for the breakdown is usually the loss of the conditional compilation symbol KOL_MCK. It could get lost, for example, as a result of deleting an unnecessary, at first glance, file with the drc extension in the project directory (or you could forget to take it with you, transferring the project to another machine or to another folder). The cure is very simple: open a dialog with project properties and add the KOL_MCK symbol manually to the list of conditional compilation symbols (Conditional Defines, on the Directories / Conditionals tab - for all Delphi versions, at least from Delphi2 to Delphi7, this tab takes place).

 

The reason designintf is starting to be required is, as it should be clear by now, in the presence of a reference to it in the mirror.pas module, which is the main one in the MCK package. All MCK modules have a link to the mirror.pas module, closed from the prying eyes of the compiler by the conditional construct {$ IFNDEF KOL_MCK}… {$ ENDIF}. This is, so to speak, part of a trick that allows MCK to exist and trick the Delphi environment at design time by passing off a KOL project as a respectable VCL project.

 

A completely similar phenomenon can occur with an application in which the KOL_MCK symbol is present, and has not disappeared anywhere. For example, if, when adding any MCK component to a form, a reference to the MCK module (for example, to mckCtrls.pas) will be inserted outside the above brackets {$ IFNDEF KOL_MCK}… {$ ENDIF}. In this case, the compiler's message may be somewhat different: for example, that a certain module was compiled with a different version of the VCL, and as a result, compilation cannot be continued. The solution is the same: find the module in the USES section, the link to which is in the wrong position, and move it inside the brackets.

 

Interestingly, the experience of the first struggle with such mistakes does not set you on the right path once and for all. There is a very high chance that after successfully working on one or even several projects developed using MCK, you will again come across this message, and you will not be able to immediately remember what the solution to the problem is.

 

 

3. A KOL project containing two or more forms is not working properly

 

More often than not, the problem is in the use (or rather, non-use) of the Applet object. If the project uses MCK, this means that the TKOLApplet component must be dropped onto the main form. In case of programming without using MCK, you need to execute the following code:

Applet: = NewApplet ('Title');

And only then create all forms as children of the applet:

Form1: = NewForm (Applet, 'Form1');

And most importantly, the Run procedure must be called with this special purpose object as a parameter:

Run (Applet);

 

In the section on this object, I have already explained that the Applet is needed, among other things, to provide control over the flow of messages between multiple forms. With a separate Applet object, all forms in the project become "children" of the Applet object, which in this case acts as the application button on the taskbar.

 

In KOL / MCK projects, the Applet global variable is similar to the Application global variable of type TApplication in VCL projects. But, unlike the VCL, the use of the Applet is optional. In the case of a simple application from one form, you can often do without using this object. At least, if you do not use other special features of this object, namely: hiding the application button on the taskbar, working with the icon in the system tray, and others. This will save another half a kilobyte of code, which can be noticeable for a small application.

 

KOL / MCK User Guide - Created by Carl Peeraer - Diamant Soft, based on the work of Vladimir Kladov - Artwerp.be

  

Keyboard Navigation

F7 for caret browsing
Hold ALT and press letter

This Info: ALT+q
Nav Header: ALT+n
Page Header: ALT+h
Topic Header: ALT+t
Topic Body: ALT+b
Exit Menu/Up: ESC