Delphi component writes a common question problem

zhaozj2021-02-16  46

1.1 What is the purpose of this document?

The purpose of this document is to answer questions about writing Delphi components or files. I have spent a long time to learn about exploring the TDATALINK category, which makes me feel that I should write the problem and experience of the computation component and share it with everyone. However, I can't guarantee that the answer written in this document is completely correct. If you have a better solution to any of the questions, or if there is any information that is suitable for in this document, please inform the author. Any wrong or missing is also welcome.

In addition to adding more questions and answers, I tried to supplement two parts:

Advanced programming designer favorite tools: this may have no direct relationship with the component design but at least they have a relationship with Delphi.

Files worth mentioning: Due to the relationship of space, this document cannot be placed too much example program, so refer to other files is very needed. This is not a textbook file, I will not do too many instruments, but will try to list the most reference value.

If you have any opinions or suggestions, welcome to let me tell me.

-------------------------------------------------- ------------------------------

Second part integrated environment

2.1 How to find out the problems generated in the integration environment?

I found that the only way to find a problem is:

Tick ​​the "Compile With Debug Info" option in the library page of the Tools | Options dialog box of the Delphi integration environment.

Select Component | Rebuild Library recompores the component library.

Execute Delphi from Turbo Debugger.

Select File | Change DIR to move to the directory containing the component program code.

If your component can check the stack when you have a GPF, you can find out which problems have occurred.

2.2 How to view the assembly language code generated by Delphi?

Glen Boyd Answer:

Turn on the login editor (regedit.exe), then add a string code "EnableCPU" under "HKEY_CURRENT_USER / SOFTWARE / BORLAND / DELPHI / 2.0 / Debugging" to set its string to "1". There will then be more "CPU" options under the View menu of the Delphi integration environment, which opens a window to view the memory and assembly language of the current program instruction. You can use a single step tracking or other method to observe it when it is detected.

2.3 I can dynamically establish components during the execution period, but errors will occur during the design period. why?

Your components must inherit from the Tcomponent category or their derivative category.

Your component constructs a letter and an extinguishing system to declare that you must look like this:

Constructor Create (Aowner: Tcomponent); OVERRIDE;

DESTRUCTOR DESTROY; OVERRIDE;

All fields declared in the Published section must be Ordinal, Single, Double, Extended, Comp, Currency, String, Small Set (Element Number; None Element Not more than 0..31) The set of this range; One of the ranges of 0..255), Method Pointer or Class. If you declare a field of other types, the Delphi compiler does not check an error. However, when you use this component, you will still get a GPF.

If you want the TMYComponent component to operate during design, pay attention to the following declarations will trigger a very serious problem:

Type Tcomplex = Record

Realpart: Double;

ComplexPart: Double;

END;

Class Tmycomponent = Class (Tcomponent) Private

F1: Tcomplex;

Published

Property P1: Tcomplex Read F1 Write F1;

END;

2.4 How to write a component that cannot be placed on the table?

Ray Lischner Answer:

If you don't want the user to pull the component to the table, use the Registernoicon and RegisterClass programs to register components.

2.5 What is the easiest way to quickly switch program sections in the program code editor?

Ray Konopka Answer:

When exploring the VCL original program code, it is highly recommended that you are best to be familiar with the bookmark function in the program code editor. How to use is simple: Ctrl-Shift-N, N is from 0 to 9 numbers to set a bookmark. After that, Ctrl-N can be used to jump to the bookmark. (Translation: Using this feature can really save you many round-up scrolls and find a freighter, don't hesitate, hurry!)

2.6 How to make my components appear fast function menu when pressing the right mouse button?

You have to create a component editor. The component editor determines the reactions and action of the component to the mouse button during the design period, you can define its own fast features menu for the component.

The steps to establish a component editor are as follows:

Inheriting a new category from the TcomponenTeditor category.

Remote Category Getverbcount, Getverb and ExecuteverB methods.

Use the RegisterComponEntedIster program in the Register program to register this component editor.

This topic of Component Editor is detailed and information in "developing delphi company".

2.7 Why does I / O 103 incorrect in the design period?

You may use the Writeln program in the component.

2.8 Why does the component editor store changes in the component properties?

I found that sometimes homemade component editor does not store component properties. There is everything in the design period, but there is a problem after storage and re-reading.

The reason is that you are likely to forget to call this method in the component editor:

Designer.Modified;

This will only know that your component editor changes the value of your component editor.

-------------------------------------------------- ------------------------------

The third part uses other components in the component

3.1 How do I join the scroll bar assembly in the component and make it possible to operate during the design?

Your scroll bar component category must handle the cm_designhittest component message.

TMYSCROLLBAR = Class (tscrollbar)

Procedure cmdesignhittest

(VAR Message: tcmdesignhittest); message cm_designhittest;

END;

Procedure TMYSCROLLBAR.CMDesignHittest (Var Message: Tcmdesignhittest);

Begin

Message.Result: = 1;

END;

Your components must establish scroll bars in the following methods:

TMYSCROLLBAR.CREATE (NIL);

Instead of

TMYSCROLLBAR.CREATE (Self);

3.2 How to establish a Windows95 model of scroll bar?

You must set the page size of the scroll bar. You can do the following program code:

Procedure setpageSize (scrollbar: tscrollbar; pagesize: integer);

VAR

ScrollInfo: Tscrollinfo; Begin

ScrollInfo.cbsize: = sizeof (scrollInfo);

ScrollInfo.fmask: = SIF_PAGE;

Scrollinfo.npage: = PAGESIZE;

SetscrollInfo (scrollbar.handle, sb_ctl, scrollinfo, true);

END;

To achieve the current page size available:

Function GetPageSize (Scrollbar: Tscrollbar): Integer;

VAR

ScrollInfo: Tscrollinfo;

Begin

IF HandleAllocated Then

Begin

ScrollInfo.cbsize: = sizeof (scrollInfo);

ScrollInfo.fmask: = SIF_PAGE;

GetScrollinfo (scrollbar.handle, sb_ctl, scrollinfo);

Result: = scrollInfo.npage;

END;

END;

-------------------------------------------------- ------------------------------

Part IV Bound Controls

4.1 Where can I find a documentation about the TDATALINK category?

I can boldly say that there is only one explanation of TDATALINK in TDATALINK, just here:

Property introduction

Property Active: Boolean (read-only)

When this Datalink links to a True when it is turned on. ActiveChanged method is triggered when the Active status changes.

Property ActiveRecord: Integer (can be erasable)

Used to set or get the record code pointed to by the Datalink buffer, the scope of the code is 0 .. buffercount - 1. Be careful not to exceed this range when you use it to set the recording code, otherwise it may result in unpredictable errors.

Property Buffercount: Integer (can be erasable)

Datalink has a data buffer. The buffercount property is used to set or obtain the size of the buffer, and the buffer size determines a DataSet to record the number of information recordings. For most data perceived components, the value of buffercount is 1; but for TDataGrid, BufferCount represents its visual column.

Property DataSet: TDataSet (read-only)

Pass the Dataset connected to this Datalink. In fact, DataSource.DataSet.

Property Datasource: TDataSource (can be erasable)

Passing this Datalink connected to DataSource.

Property DataSourceFixed: Boolean (can be erasable)

This attribute can be used to prevent the DataSource property from being changed. If this property is set to True, when we try to change the DataSource property, one exception is triggered.

Property Editing: Boolean (read-only)

If Datalink is in an editing state, it is returned to True.

Property Readonly: Boolean (can be erasable)

Set whether DataLink is read-only. This attribute does not affect the connected DataSet. This Datalink cannot enter the editing state in a read-only state. Property Recordcount: Integer (read-only)

The number of data records that pass the DataSet.

Method introduction

Function edit: boolean;

Let the connected DataSet enters the editing state. Passage value: successfully returned True, failed to return false

Procedure UpdateRecord;

We don't call this method directly, it is to provide other programs to call. This method only sets a flag and then calls the Updatedata method.

Virtual Method

To make TDATALINK objects and component communication must be rewritten:

Procedure activeChanged, PROCEDURE ACTIVECHANGED

This method is called when the connected DataSource is turned on. Using the Active property can know if the current is turned on.

Procedure Checkbrowsemode

The database will call this method after any changes.

Procedure datasetchange;

This method will be called when any event occurs when the following events occur:

Move to DataSet

Move to DataSet

Insert or add information in DataSet

Delete DataSet information

Cancel DataSet editing

update record

If you don't want to rewrite this method, as long as you call:

RecordChanged (NIL);

Procedure DataSetscrolled (Distance: Integer)

This method is called whenever you currently record changes. The Distance parameter represents the number of rows that the buffer wants to roll. (The value range is between -1 ..1). Use the ActiveRecord property to get the records currently pointed to by the buffer. We can't enforce the buffer of Datalink.

Procedure FocusControl (Field: Tfieldref)

The same as the Tfield.focusControl method.

Procedure EditingChanged

This method is called when Datalink's editing state changes. Using the Editing property can know if DataLink is in an editing state.

Procedure LayoutChanged

This method is called when DataSet's Layout changes (for example, adding a column).

Procedure Recordchanged (Field: Tfield)

This method will be called when any event occurs when the following events occur:

Currently recorded editing status

Currently recorded content

Procedure Updatedata

This method is called before a record is updated. You can call the ABORT program to prevent database updates.

4.2 How do I know a few records in a DataSet?

The TDATESET's RecNo property can return to the number of data records, but very unfortunately it only applies to DBASE and PARADOX information forms. If you want to know the number of current data records, you can derive a new category from the TDATALINK category, then make the following steps:

Change the DataSetscrolled method to obtain whether the current record is flushed.

Change the DataSetChangeD method to confirm if the current record is jumped to the foremost or last.

Then you can link this new category of objects to the TDataSource object and you can always know the current record number.

-------------------------------------------------- ------------------------------

Part 5 VCL

5.1 How to track the program code for viewing the VCL component when using the integrated environment

Copy the VCL original program unit you want to track to the directory stored in the project and recompile the component library. You can track the viewpoint code in those VCL cells. 5.2 My Component Reference to other components, how to get a message that the reference component is eliminated?

Max Nilson's answer:

The Tcomponent category provides a Notification method. When a component is removed, we can use this method to get the message to carry out appropriate reactions. You can refer to "Component Writer's Guide" for instructions on NOTINATION and FREENOTIFICATION.

When your component references to another component, for example, there is a TDataSource type attribute in your component. Then you have to write this component's Notification method, in which the removed component is the component referred to. In the preset, when the component is removed, all other components on the same table will receive a message if the reference component is on another table, and your components cannot know this. Delphi 2.0 introduces TDATAMODULE, the reference component is in another table, so you should use the FreeNotification method to determine when the reference component is removed, you must get a message.

If you don't change the NOTIFICATION method to handle the message removed by the reference component, this will cause the Delphi integrated environment to fall in a very unstable state. It may not be turned off immediately, but you can't continue other work normally.

Below is an example, when your component refers to other components, you must do the following processing:

TMYComponent = Class (Tcomponent)

Private

FDataSource: TDataSource;

Procedure setDataSource (Value: tdataasource);

protected

Procedure Notification; Operation: TOPERATION; OVERRIDE;

Published

Property DataSource: TDataSource ReadDataSource;

END;

Procedure Tmycomponent.setDataSource (Value: tdataasource);

Begin

IF value <> fdataserce

Begin

FDataSource: = Value;

// Tell the reference component saying that when it is removed, remember to inform me.

If fdataserce <> nil damifics (Self)

END;

END;

Procedure Tmycomponent.notification (ACOMPONENT: TComponent; Operation: TOperation);

Begin

Inherited NOTIFICATION (ACOMPONENT, OPERATION);

// If it is removed is a reference component, clear the fdataSource field.

IF (Operation = OPREMOVE) and (Acomponent = fdataserce) THEN

FDataSource: = NIL

END;

5.3 What is the component message?

What is the component message? It is very similar to Windows window messages, only a point difference: Component messages are only available for VCL components; and window messages can be used in all Window Handle controls or windows in the system. If you have a component with a font property (such as TLabel components), when we change its Font property, there is no window message (the translation: TLABEL component is not a window control, and there is no window handle to let us send window messages). But the control still knows that the word change has changed, so he wants to call yourself. Why? Because we have component messages. Component messages cannot be processed by virtual methods, which may be considered when designing VCL, which is probably because of the cause of virtual method table (Virtual Method Table).

"Secrets of Delphi 2.0" This book has a detailed explanation of all component messages.

Next we list some of the more common component messages and their roles. A message indicating "Notification Only" means that this message is only to inform the component, and it is not incoming any parameters and does not need to return value.

CM_ACTIVATE (Notification ONLY)

This message is passed to itself when the form becomes a focus window.

CM_CTL3DCHANGED (Notification ONLY)

This message is passed to itself when the CTL3D attribute change is changed.

Cm_designhittest parameters: tcmdesignhittest pass-back value: 0 or 1

When the mouse moves to the component during the design period, the integration environment will give this component. The purpose of this message is used to determine whether the component is to handle mouse messages during the design period. If the return value is 1, the integrated environment allows the component to handle the mouse message itself; if the transmission value is 0, the integration environment will help you handle the mouse message. If the return value is always 1, then the fast function menu of the component will never appear; if the component does not process this message or pass back 0, then this component will not be able to do any response to the mouse message during the design period.

CM_FONTCHANGED (Notification ONLY)

The type of control of the control is changed to itself.

CM_FONTCHANGE (Notification ONLY)

This message is given to itself when the control receives the WM_FONTCHANGE window message.

CM_ParentctL3DChanged (Notification Only)

This message is received when the CTL3D property of the component parent control changes or sets a new parent control.

CM_ParentColorChanged (Notification Only)

This message is received when the Color property of the component parent control changes or sets a new parent control.

CM_ParentFontChanged (Notification Only)

This message is received when the Font property of the component parent control changes or sets a new parent control.

CM_ParentShowhintChanged (Notification Only)

This message is received when the ShowHint property of the component parent control changes or sets a new parent control.

CM_WININICHANGE Parameters: TwMwiniChange Passage: None

This message is given to itself when the control receives the WM_WININICHANGE window message.

5.4 My components still cannot accept keyboard messages after entering the focus, why?

If your components have a DragMode property and set it into DMautomatic, it is likely to make your components to think that it is being dragged but actually does not have. There is a region variable DragControl in the Controls unit points to components currently being dragged. The situation you have encountered is likely to be clearly unmoving, but the Dragcontrol variable points to your components. In TwinControl's WndProc methods, when the DragControl variable points to the component itself, all keyboard messages are ignored, this is the reason! -------------------------------------------------- ------------------------------

Part 6 other information

6.1 What books do you introduce or explain how to write components?

"Standard" reference books for writing components:

"Developing Delphi Components" Author: Ray Konopka published: Coriolis Group

Below this book does not focus on component writing, but it will be referred to in many components writers inherent:

"Secrets of Delphi 2" Author: Ray Lischner published: Waite Group

Another book written in the component, it has many information that is not found in "developing delphi components":

"Programming Delphi Custom Components" Author: Fred Bulback publishing: M & T Books

6.2 What Web platforms can I get information about writing components?

The world's largest Delphi Web Station "Delphi Superpage"

(Translation: Users in Asia can be nearly Mirror Site in Japan)

I found the original program code of many components in these platforms:

Temple of Delphi

Delphi free stuff

(Translation: "Your Delphi Programming Resource" organizes components are also very useful!)

(Translation: Taiwan's currently maintaining the best Delphi station is "32 Bit Delphi Deep Adventures" and Mirror Site

You can also use some search engines to find platforms for Delphi:

Yahoo

Alta Vista

(Translation: Excite Search Engine Don't miss it!)

-------------------------------------------------- ------------------------------

Seventh part of the storage and loading of components

7.1 How do I store the object containing other objects into the DFM file?

I have tried many methods, including the defineproperties and WriteComponents methods of rewriting components, but they still have failed. So I can only say that if I want to solve this problem, I only use the Delphi original method.

The step of storing the object containing other objects is approximately as follows:

Make sure all objects you want to store are derived from the Tcomponent category.

Announce all variables that need to be stored in the Published section.

Call the RegisterComponents program in the register program of the component to register all the categories you want to store.

Each category of child control must override the getChildren method to store each sub-control. (In Delphi 1.0, you must rewrite the WriteComponents method and call the WriteComponent method for each sub-control). Use the method of loading the object with a little tip. You must rewrite the GetIldowner and getChildParent methods of the component, otherwise Delphi sets all the owners of all objects to the form where the component is located. (You must rewrite the ReadState method in Delphi 1.0).

7.2 How do I know if the component is reading from the stream?

When the component is read from the data stream, its ComponentState property contains the CSLoading banner.

Constructor TMYCLASS.CREATE (AOWNER: TComponent);

Begin

IF cslineing in aowner.componentstate Then

Begin ... End

Else

Begin ... End;

END;

7.3 How do I determine if the property of the component is properly stored?

There are many very simple ways to verify that the attribute is properly stored in the archive:

Use the mouse button to select the table in the integrated environment and select "View AS Text". However, if there is any mistake in the DFM file, you will not see anything.

Opening a DOS window, convert the DFM file into a text format using the "Convert" program attached to Delphi.

Stefan Hoffmeister stated that after copying or clipping the component, you will be posted on any instrument editor (such as Notepad), you can see the text of this component. You can even edit these text representations, then post it back to the Delphi integration environment.

-------------------------------------------------- ------------------------------

Part 8 Delphi tools

8.1 Is there a delphi version of YACC and LEX?

Have. Albert Graef This friend wrote the Turbo Pascal version of Yacc and Lex, you can also use Delphi.

You can

FTP: //ftp.simtel.net/pub/simtelnet/msdos/turbopas gets the two files of TPLY30A1.ZIP and TPLY30A2.zip, which also contains the original program of these two tools!

8.2 How to show a JPEG format graphic file?

Jacques Nomssi Nzali rewrites the free JPEG link library developed by Independent Jpeg Group into a Pascal version. You can get from now on:

Pasjpg10.zip

INDEPENDENT JPEG Group for free JPEG Funct Library Rev 6a Pascal version (version 1.0).

-------------------------------------------------- ------------------------------

Ninth Part Basic Program Design Skills

9.1 How to build an unprivific number of object arrays?

The easiest way is to use the TList category. I found that it is useful to derive a new category from TLIST. The next program code demonstrates how to write a special TList category for a specific type and add basic error checks.

TLISTOFMYOBJECT = Class (TLIST)

Private

Function GetItems (INDEX: Ordinal): TMYObject;

public

Property Items [Index: Ordinal]: TMYOBJECT Read GetItems;

Procedure Add (AObject: TmyObject);

Function TlistofmyObject.getItems (INDEX: Ordinal): TMYOBJECT;

Begin

IF index> = count kil

Raise Exception.createfmt ('Index (% d) Outside Range 1 ..% d', [INDEX, Count-1]);

Result: = inherited items [index];

END;

Procedure TlistofmyObject.add (AObject: TmyObject);

Begin

Inherited Add (AOBJECT);

END;

9.2 Where is the WinCRT unit of Delphi 2.0?

Delphi 2.0 does not have a WinCRT unit. Don't be sad, this is because we can replace it with other methods. Open the "Generate Console Application" option in Project | Options, you can write programs like the WinCRT unit before using the WinCRT unit!

9.3 Which category is inherited when the homemade component is inherited?

There are some "self-order" categories in the VCL, and there are many controls that are directly inherited by these "self-order" categories. For example, TMEMO is directly inherited from the TCUSTomMemo category. These self-subscription categories write all the functions owned by the control, but did not open the attributes. In most cases, you should inherit from those self-binding categories rather than the control category.

If you want to write your own components from your head, it is a good idea from the TCUSTOMControl class. The composed components will have Window Handle and can accept input focus.

In addition, according to your needs, you can inherit from these categories:

TGRAPHICCONTROL: Visual components, but there is no Window Handle, and cannot accept input focus.

Tcomponent: Unconventional components, you can't see it during the execution period.

TwinControl: Pack the existing window components such as Windows standard controls or VBX components.

-------------------------------------------------- -----------------------------

Part 10 advanced programming skills

10.1 Delphi has the same I / O Stream class like C ?

The answer can be said that there is no. Delphi allows you to build your own "text file driver", which allows you to use the Delphi standard I / O library to handle non-standard I / O, such as handling text files in UNIX format or processing Socket . Although there is no power like the I / O Stream category of C , it should be used in general use.

The method of establishing the "text file driver" is explained in "Object Pascal Language Guide". You can also refer to the VCL's Printer unit.

Delphi has TSTREAM categories, but it is designed to write objects to data streams, unlike C I / O Stream category is elastic.

10.2 How to get the text representation of the type variable?

Use the getenumName in the Typinfo unit:

Type

Tmytype = (value1, value2);

VAR

TYPEVALUE: TMYTYPE;

Begin

Writeln (GetenumName (TypeInfo (TmyIType), ORD (TypeValue);

END;

There are also many functions related to the type information in the Typinfo unit. "Secrets of Delphi 2.0" This book has many information about Typinfo units, which is worth reference.

-------------------------------------------------- ------------------------------

Part 11 component virtual method

11.1 How do I know when the component's Window Handle is established?

The control's Window Handle is created in the CreateWnd method. If you want to make some action after building a Window Handle, then you should rewrite the CREATEWND:

PROCEDURE TMYCLASS.CREATEWND;

Begin

// I haven't obtained Window Handle yet.

Inherited CREATEWND;

// Call inherited to get Window Handle

/ / Write here to write the action you want to perform

END;

11.2 How do I know if all components on the table have been loaded?

The loaded method is to be called after loading is completed.

Procedure TMYCLASS.LOADED;

Begin

inherited loading;

// Clear the CSLoading state in ComponentState

/ / Write here to write the action you want to perform

END;

11.3 Where to draw components?

You should intercept the WM_Paint window message and use Canvas to draw components. However, VCLs have been stopped by helping you, you only have to write the components' Paint method.

PROCEDURE TMYCLASS.PAINT;

Begin

// If your component is the component that is emerging, then you must call inherited Paint here.

Inherited paint;

/ / Write here to write the action you want to perform

END;

11.4 How to change the window style of the component?

The CreateParams method is used to set the window model of the component and other parameters that must be passed to the CreateWindowEx API. To change the window style of the component, for example, increase or take the vertical scroll bar of the component to overwrite the CreateParams method:

Procedure Tmycontrol.createParams (Var params: TcreateParams);

Begin

Inherited Createparams (params);

IWANTASCROLLBAR THEN

Params.Style: = params.style or ws_vscroll

Else

Params.Style: = params.style and not ws_vscroll;

END;

-------------------------------------------------- ------------------------------

12th part of Windows API

12.1 When the component is rolled, it is very powerful. How to overcome this situation?

The easiest way to roll the component itself is to change its coordinates and then redraw components, but this party will cause the component to flash very powerful.

A better way is to call the scrollwindow or scrollwindowex windows API.

Another reason for flashing may come from WM_PAINT and WM_ERASEBKGND. You can trial to intercept the WM_RASEBKGND and WM_PAINT messages then handle drawings, including the action of drawing the background, maybe improve flash.

12.2 How to reactivate Windows?

Use the ExitWindowsex Windows API.

12.3 How to change the component information quickly?

Before and after making a lot of information, you can use the WM_SETREDRAW message to control your components to temporarily do not call, which can not only make the data set speed and prevent the component to flash. -------------------------------------------------- ------------------------------

Section 13 Control Border

13.1 Why is the CTL3D property of my component set to True, does it still have a 3D border?

If there is no CSFramed banner in the ControlStyle property, then the CTL3D property will have no effect. In the constructive function of the component:

ControlStyle: = ControlStyle [csframed];

13.2 How to do a BorderStyle property?

Re-create Window Handle after the control settings are available.

FBORDERSTYLE: TBORDERSTYLE;

Procedure setBorderstyle (style: tborderstyle);

Property Borderstyle: TBorderstyle Read Fbeorderstyle Write SetBorderstyle;

Procedure CreateParams (Var params: TcreateParams); OVERRIDE;

Procedure Tmycontrol.createParams (Var params: TcreateParams);

Begin

Inherited Createparams (params);

IF fborderstyle = bssingle kil

Params.Style: = params.style or ws_border

Else

Params.Style: = params.style and not ws_border;

END;

Procedure TmyControl.SetBorderstyle (style: tborderstyle);

Begin

IF Style <> fborderstyle Then

Begin

FBorderstyle: = STYLE;

/ / Re-establish Window Handle

RECREATEWND;

END;

END;

-------------------------------------------------- ------------------------------

Part 14 Control type

14.1 How to prevent flashing when the component is redraw?

If the component's ComponentStyle property does not include a CSOPAQUE flag, the background of the component will cause the component to be removed and redrawn first. If you draw a background in a Paint method, you should add:

ComponentStyle: = ComponentStyle [csopaque];

Max Nilson's answer:

Another reason for flashing may be the processing of the WM_ERASEBKGND message. When the VCL control receives a WM_ERASEBKGND message, it wipes the background of the component and sets it into a preset color. If your components are derived from TwinControl, and the color of the component is different from the background color (for example, graphics), the components will be first cleared before re-painting each time you call, which is caused by flashing!

The method of solving is not difficult, you must tell Windows you have to solve the "all" drawings. However, there is a premise that you must make sure your PAINT method will draw the entire component. If you miss anything, the information will be composed of random numbers, can you want to see this situation? Use this method to accelerate your component to draw actions (a little bit a little bit), because there is less actions that fill the background color. Type

TMYComponent = Class (TwinControl)

...

protected

Procedure WmeraseBkGnd (Var Message: TwmeseBkgnd); Message WM_ERASEBKGND;

...

END;

Procedure TBMYComponent.wmesebkgnd (var message: twmesebkgnd);

Begin

// Don't re-draw background, this will cause the component to flash

Message.Result: = 0

END;

-------------------------------------------------- ------------------------------

Section 15 Window Message

15.1 Why do I have a message that I can't get the direction key?

You must intercept the message of WM_GETDLGCODE to handle the direction button, and pass back DLGC_WANTARROWS in the message handler of WM_GETDLGCODE. If you don't do this, the function of the direction button can only be used to move the window focus.

Max Nilson's answer:

If you want your component to handle the arrow keys, you have to intercept the CM_WANTSPECIALKEY component message. The CM_WANTSPECIALKEY component message provides you more easily and flexible judgment methods than to intercept the WM_GETDLGCODE window message to determine if some special key messages are required. The CM_WANTSPECIALKEY component message is sent to the control when the control receives any special key.

Special keys include: VK_TAB, VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_RETURN, VK_EXECUTE, VK_ESCAPE, and VK_CANCEL. If the message return value is a non-zero value, this button will be sent to the KeyPress method for processing, otherwise the message of this button will be sent to the component's parent control, and process it in a preset method.

A simple example:

Type

TMYComponent = Class (TwinControl)

...

protected

Procedure Cmwantspecialkey (var message: tcmwantspecialkey; message cm_wantspecialkey;

...

END;

Procedure Tmycomponent.cmwantspecialkey (var message: tcmwantspecialkey); Begin

inherited;

/ / We just want to handle the left direction key, and the other special keys are handled by Windows.

IF message.charcode = vk_left then

Message.Result: = 1;

END;

The CM_WANTSPECIALKEY component message is more flexible than WM_GETDLGCODE messages. We can even decide whether to handle this button according to which special key is pressed. For example, your controls have three images, you can use the left and right direction keys to check them, if you turn to the last image, press the right button, the focus will let it leave the component, and all of the rest will make Delphi deal with.

15.2 Is there a function of the same function as Visual Basic "Doevents"?

Have. Application.ProcessMessages method.

转载请注明原文地址:https://www.9cbs.com/read-22656.html

New Post(0)