Visual Component is actually a class. To write a class, you can write it directly in the *.pas file. But to write a control, you must use a package. Select New from the File menu and create a new Package. This is the package used to store and install controls. Then click the Add button in the Package window to add a component (Unit).
Select New Component at the top of the pop-up dialog box. Because all attributes, methods, and events of a control cannot be composed by itself, you need to select the ancestor class (or "parent class" or "base class") and then add your own attributes, methods, and events on it. . Select the desired ancestor class in the drop-down box after Ancestor type. Since you have to draw a picture by writing a visual control, TGraphicControl is selected as the ancestor class. Then enter the name of the new control (class) in the Class Name box, which usually starts with "T". Palette Page is used to select the control page name of the new control in the Delphi window, such as "Standard", which can be taken by yourself. Add the path and file name of the new control file in Unit File Name and click the OK button. New controls are added. Now you can write code for this control.
The following is an example of writing a scroll bar that can customize the image to illustrate how to write a visual control.
Follow the above method, select TGraphicControl as the ancestor class, and the name of the new control is TPigHorizontalScroller (pig horizontal scrollbar). After selecting the file path and file name, click the OK button to start writing the code.
Each control will be created and deleted, so you must first write these two processes. For each process in the control, it must be defined first and then written later. There are three types of processes or attributes that are defined:
1. The defined after PRivate is used internally to the control, and the person who uses the control cannot see it;
2. What is defined after protected is generally invisible, and can only be seen when others use the control as an ancestor class to write other controls;
3. Only others can be called in the program after public;
4. The defined after publishing can be seen in the property window (Object Inspector). Since the creation and deletion process are not only automatically executed when the control is created during the programming process, it may also be called when the control is created dynamically during the program running, so it is defined after public⑴. (This sequence number indicates the location of the code in the attached source program, the same below) Now, maybe I don’t know what to write in these two processes and how to edit it. We will talk about it below.
Let's first add some properties to this control. We define a Max property to set or read the maximum value of the scrollbar. Because attributes are not used directly in programs, you need to define a variable that corresponds to the attribute, while modifying or reading its value. Since it is only used inside the control, we define it after private ⑵. (Generally, variables associated with attributes start with "F", such as FMax) After defining the variable, define the attributes. This property needs to be visible in the Object Inspector window, so define it and publish it after ⑶. The syntax defined is:
property <property name>:<type> read <responsive variable when reading this property> write <responsive variable or process when writing this property>
Other variables and attributes are also defined similarly (such as Min minimum value, Value current value, etc.). Below we define several attributes and variables to set the scrollbar image (because the image variables are special, I will talk about them separately). We define LeftButtonUpPicture (left button picture), LeftButtonDownPicture (left button press picture) and so on as TBitmap type (must define the corresponding variable).
Everyone must have noticed that in the attached source program, when defining these properties, the corresponding variable when reading the properties specified after reading is F..., and the corresponding variable when writing the properties specified after writing is not Variables, but something like Set…, it's a custom process. The process as this function is defined as:
procedure <Process name>(Value: <Type of value of the set property>)
Because other things need to be done when writing the attributes of this class, it cannot be processed with just one variable, but should be processed with a process. This process is generally defined after protected. In this class process, a statement such as this at ⑷ is used to assign values to a variable of type TBitmap, which is adopted because variables of this type cannot be assigned directly.
After defining the properties of these TBitmap type variables, the code needs to be written in the create process and destroy process mentioned above. Because TBitmap is also a class, it must be created in the create process ⑸, and free must be released during the destroy process. The inherited statement referred to here is used to indicate that the process is inherited from the ancestor class. (This must not be dropped).
Because we write visual controls, we have to draw pictures on the controls. The ancestor class of our control, TGraphicControl, encapsulates a Canvas object, which we can use directly to draw pictures. If you are not familiar with the use of canvas, it is best to find a book to read it.
The following job is to draw pictures. How to draw pictures on the control? There is a Paint event in the ancestor class TGraphicControl, which will automatically trigger when the control needs to be repainted. What we have to do now is to write a program for this event. First, define a Canvas object after protected. Since it is already in the ancestor class, there is no need to add any explanation⑻. We will use this object to draw. Next, you need to define a Paint process and write the code to draw the control. First define the Paint process in public. Since it is triggered by the ancestor class, not by the user, override must be added afterwards, otherwise the control will not become a visual control because the Paint procedure will never be called. Let’s write the code for the Paint process⑽.
The variables such as T_Height in the Paint process of the source program attached to this article are used to save the size of buttons, sliders, etc. in the scroll bar. This part of the program is not much different from the programs in ordinary applications, most of which are correct I believe everyone will understand the operation of the canvas at a glance. It is worth noting that the following judgment on the FAutoSize variable⑾
FAutoSize is a Boolean variable associated with the property AutoSize of the control. It is used to set whether the size of the control varies with the size of the image. Note that in the control code, the attribute is not called directly, but the corresponding variable is used.
After the program has been compiled here, even if I finally made a look for my new control, it cannot scroll. Now let's write the mouse event so we can manipulate it. The definition of the mouse event process is very similar to the Paint process, except that parameter descriptions should be added later.
Mouse events are divided into MouseDown, MouseMove and MouseUp, and override must be added after the definition. Next write its code later. Note: The mouse event here is Mouse…, not the usual OnMouse…. But what is the definition in ⒀ for? The event definitions here are all for users to use, that is, when using this control, they will be displayed in the Event page in the Object Inspector.
The code for these mouse events is also very simple. You can judge the coordinates of the mouse, draw the corresponding picture on the canvas, etc., and trigger the corresponding event at the same time. It is worth noting that when calling a custom event, you must first use such a statement at ⒁ to determine whether the user has written code for the event. This is very important, otherwise an error will occur in the call.
Everyone has noticed that the events called just now are all customized, and the definition method is very simple, which is similar to the definition attribute, but TNotifyEvent when typed.
TNotifyEvent is the default event, which is defined as:
TNotifyEvent = procedure(Sender: TObject)
If you want to define another form of event, you must do this: first write it in type and then
<Event Type Name> = procedure(<parameter>:<type>)
For example:
TCustomEvent = procedure(a: Integer; b:String);
Then after public definition:
<Event Name>:<Event Type Name>
For example:
AnEvent: TCustomEvent;
After reading these, you should understand the entire program. If there is an error in compilation or operation, please check the following points:
1. Whether there are inherited statements in the create and destroy process;
2. Whether the variables of TBitmap type create and free are created or free;
3. Is there a control name before the process, for example: TPigHorizontalScroller.MoseMove
How to determine whether the mouse enters or leaves the control:
Define the following process:
procedure MouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
procedure MouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
Just write the code below!
This method is very useful for writing three-state buttons!