How to write your own VCL control
Friends who have used Delphi, probably to Delphi's favorite Delphi is not his strong type of Pascal syntax, but a powerful VCL control, I am a fan of a VCL control.
The Open Source of the VCL control has brought us an endless benefit. Unlike the previous OLE controls and ActiveX, you can override the Delphhi standard control, and there are many resources on the Internet.
About how to write VCL controls, and more Delphi books, in this simple explanation.
In Delphi, Tcomponent is the basis of all VCL components. Write a non-visible component to derive from Tcomponent. Delphi provides a number of basic component types specifically for making controls (visual components), which are derived from TControl and TwinControl. Its derived relationship is as follows:
Tcontrol --- TgraphicControl --- TcustomLabel
TwinControl - TCUSTOMCONTROL --- TCUSTOMGRID
--- TButtonControl - TCUSTOMGROUPBOX
--- TscrollingWinControl - TCUSTompanel
--- TCustomComboBox
--- tcustomedit
--- TCUSTOMLISTBOX
TControl's subtype is used for non-window controls, and the Subtype of TwinControl is used for window controls. Unless special needs, new controls are generally not derived from TControl and TwinControl, but derive from their subtypes. This makes it possible to reduce the original attributes, events, and methods to reduce a lot of workload.
Write controls, first select the appropriate VCL object type as a parent object to derive new objects.
A specific example is given below to implement a enhanced Edit input box, which is that he can effectively determine the input character based on the input data type, adding a left alignment similar to TLABEL, aligned, right alignment.
Inheriting from TEDIT to generate its own control from TEDIT through Delphi's component wizard:
TeditDataType = (DTPSTRING, DTPINTEGER, DTPFLOAT); // Input Data Type
TMYEDIT = Class (TEDIT)
Private
FALIGNMENT: TALIGNMENT;
FDATYPE: TEDITDATATYPE;
FPRECISION: Integer;
Procedure setAlignment (const value: talignment); ?? // to set alignment methods
Procedure setPrecision (const value: integer); ????????????
Procedure setDataType (Const Value: TeditDataType);
Function getasfloat: Double;
Function Getasinteger: Integer;
Procedure setAsfloat (Const value: double);
Procedure setasinteger (Const value: integer);
Function Getastext: string;
Procedure setastext (const value: string);
ProtectedProcedure CMEXIT (VAR Message: Tcmexit); Message Cm_exit; // Rewind message, the next article will detail the message
Procedure KeyPress (VAR Key: Char); override; // Rewrive the keyboard button event, used to control the keyboard input
public
Constructor Create (Aowner: Tcomponent); OVERRIDE;
Procedure createparams (var params: tcreateparams); override; // rewrite, implementation
Property Alignment: Talignment Read Falignment Write setAlignment Default
TaleftJustify; // Alignment
Property DataType: TeditDataType Read FDATYPE WRITETDATATYPE DEFAULT
DTPSTRING; // Set the input data type
Published
Property Precision: Integer Read FPRISION WRITETPRECISION; // Decimal point Active Bits Property Asfloat: Double Read GetAsfloat Write SetAsfloat; //? Increase the same type of conversion function similar to C , do not have to call function conversion each time
Property Asinteger: Integer Read Getasinteger Write Setasinteger;
Property Asstring: String Read atkext Write Setastext;
END;
// Let's take a function of implementing what we want to implement.
The first implementation left pair must rewrite the createParams function, and the implementation is as follows:
Procedure Tmyedit.createParams (Var params: tcreateparams);
Const
Alignments: Array [Boolean, TALIGNMENT] OF DWORD =
((SS_LEFT, SS_RIGHT, SS_CENTER), (SS_RIGHT, SS_LEFT, SS_CENTER);
Begin
Inherited Createparams (params);
CreateSubclass (params, 'edit');
With params do
Begin
STYLE: = Style or ss_notify or
Alignments [UserightToleftalignment, Falignment];
END;
END;
// Set alignment
Procedure TMYDIT.SETALIGNMENT (Const value: TALIGNMENT);
Begin
IF falignment <> Value Then
Begin
FALIGNMENT: = Value;
RereateWnd; // Heavy painting control
END;
END;
Rewote the keypress event based on the set data type
Procedure tlscustomedit.KeyPress (VAR Key: char);
Begin
Case fdattype of
DTPINTEGER: // If it is an integer
Begin
IF not (key in ['0' .. '9', '-', # 8, # 13, # 35, # 39]) THEN
Key: = # 0;
IF (key = '-') and ((POS ('-', text)> 0) or (SELSTART <> 0)) THENKEY: = # 0;
END;
DTPFLOAT: // If it is a bit number
Begin
IF not (key in ['0' .. '9', '.', '-', # 8, # 13, # 35, # 36, # 37, # 39]) THEN
Key: = # 0;
IF (Key = '.') and (POS ('.', text)> 0) THEN
Key: = # 0;
IF (key = '-') and (('-', text)> 0) or (SELSTART <> 0)) THEN
Key: = # 0;
end
END;
Inherited KeyPress (key); // Call the keypress method of the parent class
END;
No. now, this control is almost.
About the writing of simple controls, generally only need to inherit from Delphi for your basic component type, then rewrite some methods of the parent class, add some methods, and attributes, you can also write Delphi Out of some abstract components, such as the above TMYEDIT, you can write a basic TCUSTOMMYEDIT then, from him, guide out more controls. It is abstract. Here, the idea of the OOP you can have a big show. Habular, basic component type, no Published.
When making a component, there is a lot of classes and many properties and methods, where there are some important and relatively common class and its properties and methods.
Tcomponent
The ComponentState property, the status of the flag component, such as editing, transfer, reading, etc. It can be based on the status to determine what the current components should do;
Notification method: When a component is deleted, this method is notified of all components (in addition to the one of the deleted or added). This method has two parameters: Acomponent, Operation. Which component is now operated in which a component is made now. When using, override the Notification method in the new component, you can write the code to receive the notification in the Notification method; do some container controls, controls, such as the DB component is useful. Otherwise, you will delete it There is an address error.
Loaded method: This method is called when a component is loaded. Like the Notification method, in use, cover the loaded method in the new component, and then write the code to be loaded on the loaded method;
Updating method: When a component is being changed, it is called;
Updated method: When the component changes, it is called.
TGRAPHICCONTROL
Canvas Attributes: Canvas, the properties of the graphics components;
Left, Top, Width, Height Attribute: The size displayed in the parent component;
ControlState attribute: Control status, such as the mouse button, whether to accept the palette change information, whether the focus is accepted;
ControlStyle Attribute: Control type, if it is transparent, there is a 3D frame, etc.; Paint method: This method is called after accepting the WM_PAINT message, drawing yourself;
The preliminary study of VCL is generally easier, like any computer language, when you need more deeper, progress is slower, and what you need is more and more. Write some difficulties in the Writing of VCLs One 2: One is a system message a few Windows APIs. You need to write a complicated control, you need to be familiar with the system message. The other is the attribute editor and the writing of the component editor. Don't look at the VCL in Delphi, but not all, you want to find some reference value, it is difficult to find some reference value. I will discuss slowly, readers in the next chapter.