This article mentioned that the content may have been seen in many places, the author is also the same, but also read a lot of VCL source code, plus the experience of the actual writing of components, and patching such an article. Therefore, all remarks is a personal point of view, and experience is described only for reference only.
You can reprint, copy, but you must join the author's signature Aweay. If you are used for commercial purposes, you must agree.
Outward
Many friends have seen my first two articles, and they have trustworthy to introduce some basic knowledge of some components. Because they can't find relevant information, and ask me how I know these knowledge. It is true that there is no introduction of this paper online, not to mention that everyone is learning BCB. It is more difficult to learn from Delphi's source code. It is not much better than everyone. I think the best way is to see VCL source. Code and the newsgroup to Borland, at least I solve this problem, I hope you can.
Here is the Borland newsgroup address, if you are in English, they basically have a question:
Forums.borland.com
For friends who want to learn the knowledge of the infrastructure, I will arrange 2 articles in this series of articles as a gift to you. One is that I will actually analyze a professional-grade component, come to a source code anatomy, put all Details show to everyone, the second part is that I will actually write a simple components and introduce the whole process, I hope everyone likes.
More message processing
Two articles have been written, how is it still message processing? Yes, writing components is to process messages and expression, for general message processing, the content introduced in the previous article is already enough, but many times this is still not enough, such as if you change the Font property of the component during the design And you want to re-draw according to the font. It is clear that traditional Windows messages are handled without a slight effect, and such messages are usually WM_XXXX form. If you have studied VCL source code, you will find a lot of cn_xxxx and cm_xxxx, if you want to complete the message processing I mentioned above, these messages can help complete the task.
In fact, VCL has some non-API messages for internal use, why do you want this? This is to be stated from the WM_COMMAND & WM_NOTIFY message, we say that the WM_COMMAND message is not directly sent to the form that actually generates messages, but is sent to its parent form. However, the parent window is almost impossible to handle these messages that do not know how to handle these at all, so that the parent form adds CN_BASE to the actual sub-form and then processed by the actual sub-form.
For example, TbitBTN components processes the CN_DRAWITEM message in order to draw an image on the surface of the button, this message processing function is written this:
Fcanvas.Handle: = DrawItemstruct.hdc;
R: = ClientRect;
... / / 省 省
If isdown kil
OffsetRect (R, 1, 1);
TButtonGlyph (Fglyph) .draw (Fcanvas, R, Point (0, 0), Caption, Flayout, FMargin,
FSPACING, State, False, DrawTextBidimodeflags (0));
IF isfocused and isdefault the
Begin
R: = ClientRect;
Inflaterect (R, -4, -4);
Fcanvas.pen.color: = CLWINDOWFRAME;
FCANVAS.BRUSH.COLOR: = CLBTNFACE;
DrawFocusRect (fcanvas.handle, r); end;
Fcanvas.handle: = 0;
It can be seen that this is similar to that of usually handling Paint, in fact, in HDC. If you have learned SDK, in fact, we can handle the WM_NOTIFY message to handle the messages generated by the control, but VCL is packaged for us.
There are also some messages that are generated by the VCL internal control. This type of message is usually the format of cm_xxxx. For example, the message of cm_fontchanged is triggered when the font changes, and the detailed definition can be found in the Controls.Pas file, this is no longer Introduced in detail
For the CM_FONTCHANGED message above, it is usually processed:
Procedure Tbitbtn.cmfontchanged (Var Message: TMESSAGE);
Begin
inherited;
INVALIDATE;
END;
Through the discussion above, all CN / CM messages can be handled, but they have no corresponding virtual functions, so we have to use the old way, so the message map Macro here is the best solution, such as like such:
Begin_MESSAGE_MAP
VCL_MESSAGE_HANDLER (CN_DRAWITEM, TWMDRAWITEM, CNDRAWITEM)
END_MESSAGE_MAP (TCUSTOMCONTROL)
Void __fastcall CNDRAWITEM (TWMDrawItem MSG);
Define your own news
At the end of the last article, I demonstrate a component code. If you still remember:
Typedef void __fastcall (__closure * troveeeevent) (INDEX);
Typedef void __fastcall (__closure * tshapeselected) (Tobject * Sender, int index);
Do you still remember the above code?
Probably that is the implementation of the function pointer, for beginners, the above statement is really awkward, I will explain: THOVERSHAPEEVENT is a function pointer, the return value of the function is Void, the type of call is __fastcall, there is 2 line ginseng, the TOBJECT * and INT, the key is the red __closure keyword, what does it mean?
In BCB, I found the following description:
The keyword __closure was added to support the vcl and is buy............
It's so simple, I have no information, I only know that __closure provides support for the event handler, let me know in detail:
I don't know if you have written this code:
We have designed a class, such as traversing disk, having a data member is a callback function pointer, when we travers the disk, call this callback function when you find a file, usually, our callback function needs to declare the outside of the class So, still a pointer, it is necessary to declare this:
TypeDef void __fastcall (* bdcallback) (String path, int type);
But this is obviously not in line with the OO design principle. If you want to specify a class's member function as this member function, you will need this to declare:
Typedef void __fastcall (string path, int type); you need to assign this:
BDCallback M = & bass :: func;
The syntax is getting more and more embarrassing, this is not the most important, if there are many members of the member function to be specified as a callback function? You need to declare a similar function pointer for every class, I think you have collapsed.
__closure This time is a place of use, if you declare this:
Typedef void __fastcall (__closure * bdcallback) (String path, int type);
Then all issues have been solved, it can easily access member functions through objects, you can do this in all classes:
Class A
{
BDCallback func;
Void Dosometing ()
{
...
FUNC ("Find IT", 0);
}
}
Class B
{
Funcb ()
{
A a a;
a.func = this.callback;
}
Void __fastcall callback (String path, int type)
{
...
}
}
The above code is not very simple, but what is the relationship with the writing element?
We are still examples of the above articles as an example:
IF (! down)
{
INT SH = ShapeAtPos (X, Y);
IF (sh! = - 1)
Dohovershape (SH);
Return;
}
This code has a good explanation, you can see that the event we need to show is also a callback function, I am calling:
Void __fastcall tveccanvas :: dohovershape (int index)
{
// Todo: Add your source code here
If (fonhovershape) // If the property is assigned, there is a corresponding handler
{
FONHOVERSHAPE (this, INDEX);
}
}
I am assigning this:
__Property THOVERSHAPEEVENT OnHOVERSHAPE = {Read = Fonhovershape, Write = Fonhovershape};
The visible event processor is actually an attribute. The BCB will automatically treat the ON start attribute as an event, so this property appears in the Event list.
Let's summary: Our custom event is actually a callback function, and call the callback function specified by the component user accordingly, a sentence breaks the true meaning of the custom event, but it takes a large article. To explain its principle, even so, I still believe that many friends don't really understand this mystery. If so, you need to see what is a callback function, how the property defines such an article.
Finally, the end of this article, I left my own email:
Sineysan@163.com
If you have any questions, you can let me talk to I: