Suitable for beginners in delphi, people with object-oriented knowledge and experience in Java or vc programming.
We often see code like this in the delphi class: property property property property type name read string 1 write string 2
The names of attributes here may be different. All are in this format: property property name read string 1 write string 2
I took property Left: Integer read FLeft write SetLeft; as an example, it is a property of Tcontrol, which you can find in the controls file. Left is an Integer property. Read declares the variable or method to access the variable, and write declares the variable or method to access when modifying the variable. Note: It can be a variable or a method. I will tell you what's going on later. Here it is a variable called FLeft. For the purpose of encapsulation, we usually put such variables in the middle of private. Sure enough, we can find them in private.
FLeft: Integer code (for naming habits, we name such a variable as a capital F before the attribute name). In this way, when you read the property, you are actually accessing the value of Fleft. So you can write some methods to modify flex and indirectly modify the value of left. Then let's look at SetLeft again. Here it is a method (ask me how to know? Or look at the naming rules, usually prefixed with Set), and it is usually placed in private. Let's verify that we are in private. See the statement:
procedure SetLeft(Value: Integer);
and the following code implementation:
procedure TControl.SetLeft(Value: Integer);
Begin
SetBounds(Value, FTop, FWidth, FHeight);
Include(FScalingFlags, sfLeft);
end;
If you write the following code to change left: control1.left:=23, then the program calls the function SetLeft(23), SetBounds is a function that changes the region. Here you understand the benefits of it encapsulation. Every time you change left, It will change the size of the area according to the new left, and this function also changes the size of the Fleft. Please refer to the source code of SetBounds.
procedure TControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
Begin
if CheckNewSize(AWidth, AHeight) and
((ALeft <> FLeft) or (ATop <> FTop) or
(AWidth <> FWidth) or (AHeight <> FHeight)) then
Begin
InvalidateControl(Visible, False);
FLeft := ALeft;
FTop := ATop;
FWidth := AWidth;
FHeight := AHeight;
UpdateAnchorRules;
Invalidate;
Perform(WM_WINDOWPOSCHANGED, 0, 0);
RequestAlign;
if not (csLoading in ComponentState) then Resize;
end;
end;
This way the outside looks like the value of the attribute is changed only through assignment operations. Read and write can be variables, or functions, depending on your design. Of course you can write this: property property property property type name read variable 1 write variable 2. Variable 1 and variable 2 can be the same. You can also do this property property property property type name read method 1 write method 2. Any combination for you. But there are two things to note:
1. The naming rules are best based on habits and are easy to read.
2. If it is a variable, the type must be the same as the type of the attribute. If it is a method, the entry parameters must be the same as the type of the attribute.
We often use the event attributes of components, such as click events, but it is difficult for us to see from the surface how it is called and how it is triggered. I'll answer you below.
In the property manager object inspector, we see that the name of a method is corresponding to the right of the event page onclick. In fact, we can give a component's event corresponding to the previous method. Take a form as an example Form1. OnMouseDown:='Your method'. Note that the entry parameters of the method are of particular importance, here is (Sender: TObject)
Let's use tcontrol as an example, and we find this code:
property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown; similar to the above, but there is a special type here, TNOtifyEvent, which is an event type. We found its declaration:
TMouseEvent = procedure(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer) of object;
As you can see, it is actually a function, but the blue part limits the entry parameters. Then we assign Form1. OnMouseDown:='Your method', which corresponds to the OnMouseDown method. Then we just write a function that intercepts mouse messages and directly or indirectly call FonMouseDown, and then we will correspond to the message and the processing function. Here, there are many layers indirectly called, which is time-consuming and involves the Message type. It is recommended that you read Li Wei's book.
The following is an indirect call process. In fact, many messages are called indirectly when they occur, so I won't mention them one by one: (
procedure WMRButtonDblClk(var Message: TWMRButtonDblClk); message WM_RBUTTONDBLCLK;//Message intercepting function
procedure TControl.WMRButtonDblClk(var Message: TWMRButtonDblClk);
Begin
inherited;
DoMouseDown(Message, mbRight, [ssDouble]);
end;
procedure DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
Shift: TShiftState);
procedure TControl.DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
Shift: TShiftState);
Begin
if not (csNoStdEvents in ControlStyle) then
with Message do
if (Width > 32768) or (Height > 32768) then
with CalcCursorPos do
MouseDown(Button, KeysToShiftState(Keys) + Shift, X, Y)
else
MouseDown(Button, KeysToShiftState(Keys) + Shift, Message.XPos, Message.YPos);
end;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); dynamic;
procedure TControl.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Begin
if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
end;
If you write more of your own classes, you will find how convenient it is to do this, without writing getleft, setleft like Java, and then putting the text in private. Different methods should be called when accessing and modifying, and delphi you All of them are just calling control1.text to access, control1.text:='a certain string' to modify its value.
In terms of processing messages, the base class declares properties such as onclick and onmousedown as protected. If you want to use it, you can declare it as published and it can appear in the object inspector, and then write the processing method conveniently, you can not disclose it. Assign it to the caller function without having to write a listener as complicated as Java.
My research is not deep, please correct me if you have any inappropriate :). Welcome to [email protected]