Delphi code writing standard guide

zhaozj2021-02-12  161

· Sun Moonlight Essence Essence Article Reading

Sender: delphii (Delphi), the letter area: VCL Title: Delphi Code Rules Send Station: Sun Moon Guanghua Station (Fri Sep 7 12:03:07 2001), station letter

Delphi code writing standard guide ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ 1, preamble 2, universal source code format rule 2.1 dividing 2.2 page space 2.3 Begin ... END pairing three, Obje CT Pascal3.1 Brand 3.2 Reserved Words and Keywords 3.3 Processes and Functions (routines)

3.3.1 Naming / Format 3.3.2 Form Parameters 3.3.2.1 Format 3.3.2.2 Name 3.3.2.3 Sorting 3.3.4 Constant Parameters 3.3.2.4 Conflict 3.4 Variables 3.4.1 Names and Format of Variables 3.4. 2 Local variables 3.4.3 Global variables 3.5 Type 3.5.1 capitalization agreed 3.5.1.1 Floating point pointer type 3.5.1.2 Enumeration Type 3.5.1.3 Variables and OLE Variable Type 3.5.2 Structure Type 3.5.2.1 Arrange Type 3.5. 2.2 Recording Type 3.6 Statement 3.6.1 IF Statement 3.6.2 Case Statement 3.6.2.1 General Topic 3.6.2.2 Format 3.6.3 While Statement 3.6.4 for Statement 3.6.5 REPEAT Statement 3.6.6 with Statement 3.6.6.1 General Topics 3.6.6.2 Format 3.7 Structure Abnormal Process 3.7.1 General Topics 3.7.2 Try ... Finally 3.7.3 Try ... Except for use 3.7.4 Try ... Except ...

ELSE 3.8 Type 3.8.1 Names and Format 3.8.2 Domain 3.8.2.1 Named / Format 3.8.2.2 Visualization 3.8.3 Method 3.8.3.1 Name / Format 3.8.3.2 Use Static Method 3.8.3.3 Use Virtual / Dynamics Method 3.8.3.4 Using Abstract Method 3.8.3.5 Attribute Access Method 3.8.4 Properties 3.8.4.1 Name / Format 3.8.4.2 Using Acquisition Method 4, File 4.1 Project File 4.1.1 Name 4.2 Form file 4.2. 1 Name 4.3 Data Template File 4.3.1 Name 4.4 Remote Data Template File 4.4.1 Name 4.5 Unit File 4.5.1 Universal Unit Structure 4.5.1.1 Unit Name 4.5.1.2 Uses clause 4.5.1.3 Interface 4.5.1.4 Implementation Section 4.5.1.5 Initialization section 4.5.1.6 Finalization section 4.5.2 Forms 14.5.2.1 Name 4.5.3 Data Template Unit 4.5.3.1 Name 4.5.4 General Destination Unit 4.5.4.1 Name 4.5.5 Components Unit 4.5.5.1 Name 4.6 File Head 5, Forms and Data Templates 5.1 Form 5.1.1 Form Type Name Standard 5.1.2 Form Instance Naming Standard 5.1.3 Automatically Create Form 5.1.4 Mode Form Instantiation Function 5.2 Data Template 5.2. 1 Data Template Naming Standard 5.2.2 Data Template Instance Name Standard Six, Package 6.1 Comparison 6.2 File Naming Base 7.2 Members 7.3 User Custom Members 7.2 Members 7.5 Using Registration Unit 7.4 Components Instances 7.5 Member prefix 7.6 Standard Page 7.7 Additional Page 7.8 WIN32 Page 7.9 System Page 7.10 Internet Page 7.11 Data Access Page 7.12 Data Controls Page 7.13 Decision Cube 7.14 QReport Page 7.15 Dialogs Page 7.16 WIN3.1 Page 7.17 Samples Page 7.18 ActiveX Page 7.19 Midas Page ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ preamble ■■■■■■■■■■■■■■■■■■■■■■■■ this document details the programming code in Delphi 4 Developer's Guide to write standards. Under normal circumstances, this document follows the guidelines of the "cancel" format, which is used by Borland International. In the Delphi 4 Developer Guide, the purpose of this document is to illustrate a method. By this method, the development team can maintain a consistent style in the code they have. The purpose of this is to make each programmer in the development group can understand the code of other programmers. This helps to increase the conception and use of code written.

This document does not mean all standards existing in the code. However, its content is enough to help you get a good head. You can add these criteria to meet your needs. We don't agree that you have deviated from these standards used by Borland developers too far. We recommend this because there is a new programmer to join your development team, and their favorite and most familiar is Borland's standard. This document will also be changed as needed in most code standard documents. So you can find the latest update version in www.xapware.com/ddg. This document does not include the user interface standard. This document is independent but equally important. There is already enough third-party books and Microsoft documents including some other guidelines, and we decide not to copy this information, but we will guide you to Microsoft Developers Network and some resources, where you can find what you need. ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■ There are two spaces at each level. Do not keep TAB characters in the source code, because Tab characters represent different widths with different settings of different users and different resource management tools (print, document, version control, etc.). You can prohibit saving Tab characters from the "Use Tab Character" and "Optimal Fill" check box on the Editor page in the ENVIRONMENT option dialog box (via OOLS | Environment). 2.2 Page Space Page Spaces will be set to 80 characters wide. Usually, the source code will not exceed this boundary, but this policy will have some flexibility. Regardless of whether it is possible, those statements that exceed another line will be connected to the previous statements after a comma or other operator. When a statement is interrupted, it should indumb to two characters than the original line statement.

2.3 Begin ... END pairing Begin clause should be written in an independent line. For example, the first line below is the wrong way of writing and the second line is correct. For i: = 0 to 10 do begin // error, Begin with for i: = 0 to 10 do // correctly, Begin appears in an independent side of the BEGIN this rule is the appearance of the Begin clause is As part of an else clause, reference example: if Some Statement Thenbegin ... endelse begin sometherstatement; end; End statement always appears in a separate line. When the Begin statement is not part of an ELSE clause, the corresponding End statement is always indentation to a location corresponding to the Begin section. ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ 3.1 Brackets Never leave spaces in the middle of the characters between brackets and parentheses. The following example demonstrates erroneous and spaces that correctly use parentheses: CallProc (APARETER); // Error CallProc (APARAMETER); // Do not use unnecessary parentheses in one statement. Brackets should only be used in places they need in the source code. The following example demonstrates errors and correct use: if (i = 42) THEN // Error - Excess parentheses IF (i = 42) or (j = 42) THEN // correct - need brackets 3.2 reserved words and keywords Object Pascal reserves the words and keywords are always lowercase. 3.3 Processes and Functions (routines) 3.3.1 Named / format routines The names of the renovation should always be at the beginning of the uppercase letters and the intermediate misses are distinguished to facilitate readability. Here is a process name in incorrect format: Procedure thisisapoorlyformattedRoutinename; the following is an example of a suitable case routine name: Procedure thisismuchmorereadableRoutineName; the name of the routine should match its content. A routine that can lead to a behavior should begin with the verb. For example: Procedure Formatharddrive; a routine for setting input parameters should be used as a prefix as a prefix, for example: procedure setUserName; a routine for receiving a value should be prefixed as a word GET, for example: procedure getUsename: string; 3.3.2 Form Parameters 3.3.2.1 Format If any, the same type of shape is merged in one statement: Procedure Foo (Param1, Param2, Param3: Integer; param4: string; 3.3.2.2 Name all ginseng The name should be very in line with the meaning representative, especially the name of the flag transmitted to the routine. A good parameter name should be prefixed as a character A - for example: procedure: string; meanserage: integer; "a" prefix indicates that the name of this parameter is the name of a property or domain in the class type. corresponding.

3.3.2.3 Sort of parameters The order of the description of the parameters will explain the benefits of the registrant call convention call. - The most common parameters should be placed first, and other parameters should be arranged in the order from left to right. - The input parameter list should be placed on the left of the output parameter list. - Place the general parameters on the left side of the special parameters, for example: Procedure SomeProc (Aplanet, ACONTINENT, ACOUNTRY, ASTATE, ACITY) - Sort may be some exception, such as the process of the event. The Sender parameter for TOBJECT is often placed first. 3.3.2.4 Conveying parameters When a parameter is a record type, an array type, shortstring, or an interface type and these parameters should be tagged in the routine. This will make the compiler more efficiently generate code related to these non-changing parameters. Other non-variable parameters in the routine can also be transmitted. Although there is no effect and improve efficiency, this will provide more information to the user of the modified routine. 3.3.2.5 Conflicts Conflicts When using two units with two names of the routines, if you call this routine, the routines in the end of the unit in the Uses clause will be called. In order to solve this "blurred in the USES clause" conflict, you must write the prefix on the associated unit when calling the routine, for example: sysutile.findclose (SR); or Windows.FindClose (Handle); 3.4 Variables 3.4 .1 Named naming and format variables of variables should be used to use their purpose to cycle control variables should be used as names, such as I, J, or K, or more meaningful names, such as UserIndex. The name of the logical variable should be able to fully express the meaning of accurate or false. 3.4.2 Local variables The local variables in a process should follow all other variables and naming conventions. Temporary variables should be reasonable. If necessary, the partial variable should be initialized in one entry routine. The local ANSISTRING variable will automatically initialize an empty string. The local interface and distribution interface type variable will automatically initialize the NIL, and local variables and OLE variable type variables automatically initialize the use of global variables to use global variables for the use of global variables for UNASSIGNED 3.4.3. However, it is still necessary to use at some time, and they should only be used when they must be used. At this time, you should work hard to use global variables within a context. For example, a global variable should only be globally located in the IMPLEMNTATION section of a unit. If you intend to use global data in multiple unit classes, you should move them into a common unit and then used by all other units. Global variables can be initialized to a value directly in a VAR clause. Remember, all global data will automatically initialize 0, so do not initialize global variables to a "empty" value such as 0, nil, '', unassigned, and so on. One reason why this is because zero-initialization global data will not occupy any space in the EXE file. Zero - Initialization Data is stored in a virtual data segment, which is assigned in a period of memory after the application is started. Non-zero-initialized global data takes up in the exe file of the hard disk. 3.5 Type 3.5.1 Understand Conventions If the name of the type is a reserved word, then it should be lowercase. Win32 API types are usually all capitalized and you must follow the agreement of the detailed type name in Windows.PAS or other API units. For other variable names, one letter should be uppercase, and other letters should be missed.

Here are some examples: var myString: String; // Reserved Word WindowHandle: HWnd; // Win32 API Type I: Integer; / / Introduction Type Identifier Introduced in the System Unit 3.5.1.1 Floating point pointer type does not recommend using REAL types Because it exists just to compatibility with early Pascal code. In normal cases, use Double to implement the needs of floating point pointers. And, Double is optimized for the processor and bus, and it is also the standard data format defined in the IEEE. Extended is only used when the range is required to exceed the range defined by Double. Extended is the type of Intel definition and does not support in Java. Single is only used when the actual byte size of the floating point pointer variable has its meaning. (, For example, when using another language DLLS). 3.5.1.2 Enumeration Type Enumeration Type The name of the type needs to be used in accordance with the purpose of this type. This type of name needs to be prefixed in character T to indicate that this is a type. The identifier list in the enumeration type must contain two or three characters of the prefix corresponding to the name of the enumeration type - for example: tsongtype = (Strock, StClassical, StCountry, Stalternative, StheavyMetal, StrB); an enumeration type The name of the instance should be the same as the enumeration type of not prefix, unless there is a better reason to give this variable more special name, such as FavoritesongType1, FavoritesongType2, etc. 3.5.1.3 Variables and OLE variable types are often not recommended to use variables and OLE variable types. However, this type must be used in programs that only have time to know the data type, which appears in COM and database development. OLE variables are used in COM-based programming, such as automation and ActiveX control, and variables are used in non-COM programming, because variables can store local Delphi strings (same as the same string variable) in the same variable, but The OLE variable converts all strings to an OLE string (WideChar string) and does not instance - they will be copied forever. 3.5.2 Structure Type 3.5.2.1 The name of the array type array type needs to meet their use. The name of this type must be prefix T. If the array type pointer is required, then the pointer needs to be prefixed and should be immediately declared in front of the array declaration. For example: Type PcycleArray = ^ TcycleArray; TcycleArray = array [1 ... 100] of integer; in practical applications, the name of the variable instance of the array should be the name of its type to remove the prefix T. 3.5.2.2 Recording Type Record Type The name of the record should comply with the purpose of using them. Its type of statement should be prefix T. If you want to declare the pointer of the record type, it should be prefixed and should close to the previous declaration of the type declaration. For example: type pemploye = ^ TEPLOYEE; TEMPLOYEE = Record EmployeEname: string; EMPLOYEERATE: DOUBLE; END; 3.6 Statement 3.6.1 IF statement The most frequent behavior in the IF / THEN / ELSE statement should be placed in the THEN clause, and Other behaviors that have less likely, should be placed in the else clause.

Try to avoid using nested IF statements, using multiple IF statements in this case to judge various possibilities. Do not use the IF nested more than five depths. The code should be written clearer and clear. Do not use unnecessary parentheses in the IF statement. If there are multiple conditions in the IF statement to be tested, these conditions should be arranged from left to right from left to right by less than a few order. Doing so allows the compiler to get the shortcut of Boolerance when compiling code, making your code best optimization. For example, if the condition 1 is faster than condition 2, the condition 2 is faster 3, then the arrangement in the IF statement should be: IF condition 1 AND condition 2 AND condition 3 THEN3.6.2 CASE statement 3.6.2.1 General Topic Each independent unit in a CASE statement should be arranged in a number or alphabetical order. The action behavior of each CASE unit should be simple and should not exceed four to five lines. If the action you want is too complex, a separate process or function should be used. The else clause in the CASE statement is only used when the default behavior is required or handled. 3.6.2.2 Format The CASE statement should follow other structural miniatages and naming conventions. 3.6.3 WHILE statement does not recommend using the exit process in a while statement to jump out of the loop, try only to use the cycle condition to jump out of the loop. The initialization code used in a While cycle should close to the WHILE cycle, not being separated by other unrelated statements. Any end process should be carried out immediately after the loop. 3.6.4 for statement for statement onlys the WHILE statement is replaced when the number of cycles is known. 3.6.5 REPEAT statement The REPEAT statement is the same as the While statement, and follows the same general policy. 3.6.6 with statement 3.6.6.1 General Topic WITH sentences should save use and have a lot of warnings. Avoid excessive use of the with statement and use multiple objects, records, and more in the WITH statement. For example: with record1, Record2 Do these things will make programmers feel confused and difficult to find out. 3.6.2 Format The Statement Follow the naming agreement and dividing format rules illustrated by this document. 3.7 Structure Exception Process 3.7.1 General Topics Abnormal Topics uses a large number of incorrect corrections and resource protection. That is to say that once the resource is assigned, a try ... finally must use to ensure that the resource is released correctly. This anomalous protection also refers to the allocation and release of resources in a unit's Initialization / Finalization or an object's constructor / design. 3.7.2 Try ... Finally Use in any case, each assignment should follow a try ... finally. For example, the following code will result in possible errors: someclass1: = tsomeclass.create; somclass2; = tsomeclass.create; try or {do some code} finally someclass1.free; someclass2.free; end; a more secure and more suitable The allocation process should be: someclass1: = tsomeclass.create; try-nameclass.create; try or {do some code} finally someclass2.free; end; finally someclass1.free; end; 3.7.3 Try ... Except for use only Try ... Except is used when an exception is triggered and you want to perform some tasks.

Usually, you don't have to use the Try ... Except statement in order to display an error message simply on the screen, because this will be automatically executed by the Application object. If you want to call the default exception handler after performing some tasks in the Except clause, use Raise to re-trigger an exception to the next handle. 3.7.4 Try ... Except ... Else Using Try ... Except's Else clause is not recommended because it interrupts all exceptions include those you are not prepared. 3.8 Class Type 3.8.1 Names and Format Class Types The name of the class should meet the purpose of using them. Type names should be prefixed to indicate that this is a type of definition - for example: type tcustomer = class (TOBJECT) type instance is usually the name of the type of the prefix T, for example: VAR Customer: Tcustomer; Note: Review "Component Type Naming Standards to get more information about the component named. 3.8.2 Domain 3.8.2.1 Naming / Format Class The domain name following the variable identifier is the same as if they should be prefixed in F, indicating that this is the name of a domain. 3.8.2.2 Visualization All domains must be private. Want to access the domain outside the class to use attributes. 3.8.3 Method 3.8.3.1 Naming / Format Method Names should follow the convention and function of the process and functions in this document. 3.8.3.2 Using Static Method If a static method is used, then the method cannot be inherited by the descendum of the class. 3.8.3.3 Using Virtual / Dynamic Method If you plan to be inherited by the class of the subsequent class, you have to use the virtual method. A dynamic method is only used when the method has multiple inherits (direct or indirect). For example, a class type contains a can inherit, and 100 descendants should inherit this method, then this method dynamically generates the memory used by 100 descendants. 3.8.3.4 Using Abstract Method If you use an abstract method in a class, this class cannot be created. Only use abstract methods in classes that never be created. 3.8.3.5 Property Access Method All Access classes can only appear in the Private or Protected section of the class. Naming of attribute access methods should follow the process and function's agreed rules. Read Access Method (Method Reader) must be prefixed with a word GET. Writing Access Method (Method Writer) must be prefixed in word Set. Method The name of the parameter of the writer should be Value, and its type should be the type of attribute it operate. For example: TSomeClass = class (TObject) private FsomeField: Integer; protected function GetSomeField: Integer; procedure SetSomeField (Value: Integer); public property SomeField: Integer read GetSomeField write SetSomeField; end; 3.8.4 3.8.4.1 naming attribute / attributes format If it is an accessor to a private domain, then its name should be the name of the domain they operate to remove the explanatory F. The name of the attribute should be a noun, not a verb. The attribute is indicated by data, and the method is represented by behavior. The name of the array type should be a plural. In general, the name of the attribute should be singular. 3.8.4.2 Ease of access Although there is no requirement, it is recommended to use a write access method as much as possible to a private domain attribute. ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ 4.1 Project Document 4.1.1 Name Project Document should take a descriptive name. For example, the project name of the Delphi 4 Developer Guide Error Manager is: DDGBUGS.DPR.

The name of a program related to system information should be like sysinfo.dpr. 4.2 Form file 4.2.1 Name Name Name You should describe the purpose of using the form and suffix FRM. For example, a file name of a "about" form should be AboutFrm.dpr. The file name of the main form should be mainfrm.dpr. 4.3 Data Template Document 4.3.1 Name Name Templates You should represent the purpose of using the data template, its name should be added to the suffix DM of the two characters. For example, the file name of the custom data template should be CUSTOMERSDM.DFM. 4.4 Remote Data Template File 4.4.1 Name The name of the distal data template should indicate the purpose of using the remote data template, and its name should be the suffix RDM of three characters. For example, the file name of the custom distal data template should be CustomersRDM.DFM. 4.5 Unit File 4.5.1 Universal Unit Structure 4.5.1.1 The name Unit file should take a descriptor name. For example, the unit containing the application main form should be called mainfrm.pas. 4.5.1.2 Uses clauses in the interface section of the interface section should be included in the unit required in the Interface section. Remove those Delphi to automatically join the unit in the program. The USES clause in the Implementation section should only contain the name of the unit required for the code required in the IMplementation section. Remove unnecessary units. 4.5.1.3 Interface section The interface section should contain only those definitions, variables, procedures / functions of the access types that other units, and the like. Otherwise, it should be placed on the Implementation section. 4.5.1.4 Implementation section Part IMplementation section should include those type definitions, variables, procedures / function definitions, etc. that are only private in this unit. 4.5.1.5 Initialization section Do not put the time-long code in the Initialization section, which will make the first interface of the program slower. 4.5.1.6 Finalization section Here you must ensure that you release any resources you assigned to the Initialization section. 4.5.2 Form Unit 4.5.2.1 Name the unit file of a form should have the same name as the form file it corresponds. For example, the unit name of the "About" form should be AboutFrm.PAS, while the unit name of the main form should be Mainfrm.PAS. 4.5.3 Data Template Unit 4.5.3.1 Name the unit file of a data template should have the same name as the data template file it corresponds. For example, the name of a custom data template unit should be Customersdm.PAS. 4.5.4 General Destination Unit 4.5.4.1 Name Name Names shall comply with the purpose of using the unit. For example, a utility unit is named bugutilities.pas. A unit containing global variables is named Customerglobals.PAS. Note that the name of the unit cannot be the same as the name of the unit in all packets used in its work. Not approved with general or universal unit names. 4.5.5 Component Unit 4.5.5.1 The named component unit should be placed in a separate directory to distinguish them with the units defined by the component group or component set. They should always be in different directories. The unit name should be consistent with their content. Note: Check the "User-Defined Component" section to get more information about component naming standards. 4.6 File Header recommends using an information file header in all source files, project files, units, and the like. A good file header should include the following information: {copyright ... Works of the year, month, day ...} ■■■■■■■■■■■■■■■■■■■■■ And data template ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ The purpose of the body. Type definition should be prefix T. The prefix followed by the descriptive name. Finally, a Form suffix should be applied to describe the name.

For example, the name of the type of "About" form should be: TaboutFrom = Class (TForm); the main form is defined as: TMAINFORM = Class (TFORM); a user access form should be image: tcustomerentryform = Class (TFORM); 5.1.2 Form instance Naming Standard Form Instance should be the name of the corresponding class with a prefix T. For example, the name of the actual example should be: Type Name Instist Name Taboutform Aboutform TmainForm Inform TCUSTMERENTRYFORM CUSTOMERENTRYFORM 5.1.3 Automatic Creating Forms Only the main form can be automatically created unless otherwise reasonable Not doing this. All other forms must be removed from the automatic creation list in the Engineering Options dialog box. Check out the following sections to get more information. 5.1.4 Mode Forms All Forms All Forms should include a form instantiation function, which is used to create, set, modely display the form, and release the form. This function should return the pattern of the form. The parameters you want to pass should follow the "Parameter Pass" standard specified by this document. The functionality packaged in this way helps the reuse and maintenance of the code. The variable of the form is to be removed from the unit, and a local definition is performed in a function of the form. Note that this means that the form must be removed from the automatic creation list in the Project / Options dialog. Refer to "Automatically Create Form" later in this document. For example, the unit below shows a function in the GetUserData form. unit UserDataFrm; interface uses windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TUserDataForm = class (TForm) edtUserName: TEdit; edtUserID: TEdit; private {Private declarations} public {Public declarations} end; Function GetUserData (var auserid: integer): word; importation {$ r * .dfm} Function GetUserData (var auserid: integer): WORD;

var UserDataForm: TuserDataForm; begin UserDataForm: = TuserDataForm.Create (Application); try UserDataForm.Caption: = 'Getting User Data'; Result: = UserDataForm.ShowModal; if (Result = mrOK) then begin aUserName: = UserDataForm.edtUserName. Text; auserid: = start (userdataform.edtuserid.text); end; finally userdataform.free; end; end; end.5.2 Data Template 5.2.1 Data Template Name Standard Data Template Name To meet the purpose of using this data template . The definition of the type should be prefeded T, followed by the descriptive name, and finally add the debug word "Datamodule". For example, a custom data template is sometimes like: tcustomerDataModule = Class (TDataModule) A command of a command data template: TordersDataModule = Class (TDataModule) 5.2.2 Data Template Instance Name Standard Data Template Instance Name It is the name of the type that does not have a prefix T. For example, for the previous form type, the name of the example should be: Type Name Instist Name TcustomerDataModule CustomerDataModule TordersDataModule ORDERSDATAMODULE ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Six, package ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Or components. Additionally, the included attribute / component editor and other code to be designed should be placed in the design timing package. The registration unit should be placed in the design package. 6.2 File Naming Standard Pack The name should be in accordance with the following example: "IILIBVV.PKG" - Design Time Package "iiistdvv.pkg" - Runtime package Character "III" indicates a 3-character identification prefix. This prefix is ​​used to indicate companies, individuals, or other identified entities. Character "VV" is represented as the version number of the package that you want to correspond to a version of Delphi. Note that the name of "lib" or "std" in the name of the package is to indicate that this is a design time package or a runtime package. If it is both a design time package and a runtime package, the name of the file is the same as above, for example, the name of the package made for the Delphi 4 Developer Guide should be: ddglib40.pkg - Design Time Bag DDGSTD40.PKG - Running Pack ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ 7.1 User-defined components The name of the component named in the standard component is defined as a class type as the "class type" section definition, and the difference is that they have a 3-character indicator prefix, which can be represented. Companies, individuals or other entities. For example, a name of a clock component written for a Delphi 4 Developer Guide is defined as: TDDGCLOCK = Class (TComponent) Note that the three prefix characters are lowercase.

7.2 The component unit member unit should only contain one primary member, and a primary component is a component in the component column. The auxiliary member / object of the main component should be placed in the same unit. 7.3 The registration process using the registration unit should be removed from the unit itself, and placed into a separate unit. This registration unit can be used to register any component, attribute editor, component editor, exemption, etc. The registration of the component should only be carried out in the design clip, and the registration unit should be included in the design time package and should not be placed in the running moment. The name of the registration unit recommended is: 3 prefix characters "XXX" above XXXREG.PAS is used to represent a company, individual or any other entity. For example, the name of the registration unit in the Delphi 4 Developer Guide should be DDGREG.PAS. 7.4 Components Instance Naming Convention All components should take a descriptive name. The components of the default name created by Delphi are not abandoned. A lowercase prefix should be designed when the design component type is designed. The reason why the prefix does not use the suffix is ​​when searching, the name of the search component in the Object Check and the Code Explorer is more easily implemented than the type of search member. 7.5 The prefix of the component The prefix below the component can be used to design the standard components in Delphi 4. Please join the prefix of a third party component in this list.

7.6 Standard Page member prefix mm TMainMenupm TPopupMenummi TMainMenuItempmi TPopupMenuItemlbl TLabeledt TEditmem TMemobtn TButtoncb TCheckBoxrb TRadioBoxlb TListBoxcb TComboBoxscb TScrollBargb TGroupBoxrg TRadioGrouppnl TPanelcl TCommandList7.7 Additional pages prefix member bbtn TBitBtnsb TSpeedButtonme TMaskEditsg TStringGriddg TDrawGridimg TImageshp TShapebvl TBevelsbx TScrollBoxclb TCheckListboxspl TSplitterstx TStaticTextcht TChart7.8 Win32 page prefix member tbc TTabControlpgc TPageControlil TImageListre TRichEditthr TTrackBarprb TProgressBarud TUpDownhk THotKeyani TAnimatedtp TDateTimePickertv TTreeViewlv TListViewhdr THeaderControlstb TStatusBartlb TToolBarclb TCoolBar7.9 System page prefix member tm TTimerpb TPaintBoxmp TMediaPlayerolec TOleContainerddcc TDDEClientItemddci TDDEClientItemddsc TDDEServerConvddsi TDDEServerItem7.10 Internet page prefix member csk TClientSocketssk TServerSocketwbd TWebDispatcherpp TPageProducertp TQueryTableProducerdstp TDataSetTableProducernmdt TNMDayTimenec TNMEchonf TNMFingernftp TNMFtpnhttp TNMHttpnMsg TNMMsgnmsg TNMMSGServnntp TNMNNTPnpop TNMPop3nuup TNMUUProcessorsmtp TNMSMTPnst TNMStrmnsts TNMStrmServntm TNMTimenudp TNMUdppsk TPowerSockngs TNMGeneralServerhtml THtmlurl TNMUrlsml TSimpleMail7.11 Data Access pages prefix element ds TDataSourcetbl

TTableqry TQuerysp TStoredProcdb TDataBasessn TSessionbm TBatchMoveusql TUpdateSQL7.12 Data Controls page prefix member dbg TDBGriddbn TDBNavigatordbt TDBTextdbe TDBEditdbm TDBMemodbi TDBImagedblb TDBListBoxdbcb TDBComboBoxdbch TDBCheckBoxdbrg TDBRadioGroupdbll TDBLookupListBoxdblc TDBLookupComboBoxdbre TDBRichEditdbcg TDBCtrlGriddbch TDBChart7.13 Decision dcb TDecisionCubedcq TDecisionQuerydcs TDecisionSourcedcp TDecisionPivotdcg TDecisionGriddcgr TDecisionGraph7.14 QReport member Cube page page prefix prefix member qr TQuickReportqrsd TQRSubDetailqrb TQRBandqrcb TQRChildBandqrg TQRGroupqrl TQRLabelqrt TQRTextqre TQRExprqrs TQRSysDataqrm TQRMemoqrrt TQRRichTextqrdr TQRDBRichTextqrsh TQRShapeqri TQRImageqrdi TQRDBMImageqrcr TQRCompositeReportqrp TQRPreviewqrch T The QrChart7.15 Dialogs page dialog feature is a real form packaged by the component, so they should follow the form of naming conventions. The type has been defined by the name of the component. The name of its instance is the type instance name that Delphi automatically generated removes the digital suffix. For example as follows: Example Name Type TOpenDialog OpenDialog TSaveDialog SaveDialog TOpenPictureDialog OpenPictureDialog TSavePictureDialog SavePictureDialog TFontDialog FontDialog TColorDialog ColorDialog TPrintSetupDialog PrintSetupDialog TFindDialog FindDialog TReplaceDialog ReplaceDialog7.16 Win3.1 page prefix member dbll TDBLookupListdblc TDBLookupCombots TTabSetol TOutlinetnb TTabbedNoteBooknb TNoteBookhdr THeaderflb TFileListBoxdlb TDirectoryListBoxdcb

TDriveComboBoxfcb TFliterComboBox7.17 Samples page prefix member gg TGaugecg TColorGridspb TSpinEditspe TSpinEditdol TDirectoryOutlinecal TCalendaribea TIBEventAlerter7.18 ActiveX page prefix member cfx TChartFXvsp TVSSpellf1b TF1Bookvtc TVTChartgrp TGraph7.19 Midas page prefix member prv TProvidercds TClientDataSetqcds TQueryClientDataSetdcom TDCOMConnectionolee TOleEnterpriseConnectionsck TSocketConnectionrms TRemoteServermid TMidasConnection - ※ Source : · Sun and Moonlight Station bbs.fudan.edu.cn · [from: 61.170.136.227]

[return to previous page]

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>

Good Delphi object-oriented programming rules 20

Rule 1: Create a unit for each class (One Class, One Unit)

Always keep this: private (Private) and protection (Protected) only hide for classes and processes in other cells. So if you want to get effective encapsulation, you should be A class uses a different unit. For some simple classes, such as those that inherit other classes, you can use a shared unit. However, the number of classes that share the same unit is limited: don't place more than 20 complex classes in a simple unit, although Borland's VCL code has been doing so. If you use a form, Delphi will default to follow the rules of "a class using a unit", which is also very convenient for programmers. When you add a class without a form to your project, Delphi creates a new independent unit.

Rules 2: Name the component (Name Components)

It is very important to give each form and unit. The names of the form and unit must be different, but I tend to use similar names for them, such as using AboutForm and About.PAS for them, using the descriptive name for the component. It is also very important. The most common naming method is to start using the lowercase of the class, plus the components, such as btnadd or editname. With this naming method, there will be a lot of similar names for component naming, and there is no best name. In the end, it should be chosen that should be based on your personal hobbies.

Rules 3: Name Event is more important for event processing methods to give appropriate names. If you give a proper name for the component, the system default name ButtonClick will turn btnaddClick. Although we can guess the function of this event handler from this name, I think it is a better way to use a name that describes the role of the method, not the name of Delphi attached is a better way. For example, the BTNADD button's onclick event can be named ADDTOLIST. This will make your program more readable, especially when you call this event handler in other methods of this class, and this helps programmers use the same way to similar events or different components. But I have to declare that the action (Actions) is my favorite approach when developing important procedures.

Rules 4: Using Form Method (Use Form Methods)

The form is some class, so the code of the form is organized. You can add event handlers to the form that completes some special features, and they can be called by other methods. In addition to the event handling method, you can add a specially defined method for the form and a method of accessing the form state. Add some public (public) methods to other forms to other forms to do his components directly than other forms.

Rules 5: Add Form Constructure (Add Form Construction)

The second form created at runtime will provide other special constructors in addition to a default constructor (inherited from the Tcomponent class). If you don't need to consider compatibility with Delphi4 previous version, I suggest you overload CREATE method to add the necessary initialization parameters. Specific code can be found in the following code:

Publicconstructor create (Text: string): reintroduce; overload; constructor tFormDialog.create (Text: string); begininherited create (Application); edit1.text: = text;

Rules 6: Avoid global variables (Avoid Global Variables)

It should be avoided using global variables (that is, those defined in the unit's interface part). There will be some suggestions to help you do it.

If you need to store additional data for the form, you can add some private data to the form class. In this case, each form instance has its own copy of the data. You can use unit variables (variables defined in units of the unit) declare those shared by multiple instances of the form.

If you need to share data between different types of forms, you can define them in the main form to achieve sharing, or use a global variable, how to use methods, or attributes to get data.

Rule 7: Never use Form1 in TFORM1 class (Never USE Form1 in TFORM1)

You should avoid using a specific object name in the class method, in other words, you should not use Form1 directly in the TForm1 class. If you really need to use the current object, you can use the Self keyword. Keep in mind: Most of you don't have to use the method and data of the current object directly.

If you don't follow this rule, when you create multiple instances for a form class, you will fall into trouble.

Rules 8: Try to avoid using Form1 in other forms (SELDOM USE FORM1 IN Other Forms)

Even in the code of other forms, you should try to avoid direct use of global variables, such as Form1. Define some local variables or private domains to use other forms better than direct call global variables. For example, a program's main form can define a private domain for a dialog. Obviously, this rule will be very useful if you plan to create multiple instances for a derived form. You can keep a list within the code range of the main form, or you can easily use the form an array of global SREEN objects.

Rules 9: Remove Form1 (Remove Form1)

In fact, my suggestion is to remove the global form object that Delphi automatically created in your program. This is also possible even if you prohibit the automatic add function of the form, because this form may still be added in Delphi. The suggestion for me to give you should try to avoid using a global form object.

I think it is useful for Delphi's newcomers, which is useful to remove global form objects so that they are not confused about the relationship between classes and global objects. In fact, the rule 10: Add Form Properties

As I have already mentioned, add a private domain when you need to add data for your form. If you need to access other classes, you can add properties to your form. Using this method You can change the code and data of the current form (included in its user interface) without having to change the code of other forms or classes.

You should also use attributes or methods to initialize the partial form or dialog, or access their final state. As I said earlier, you should use the constructor to complete the initialization work.

Rules 11: Display Component Properties (Exponents Properties)

When you need to access the status of other forms, you should not access its components directly. Because this will combine other forms or other classes and user interfaces, and the user interface is often the most prone to change in an application. The best way is to define a form properties for the component properties you need to access. To achieve this, you can implement the set method of the component state and the set method of setting component status.

If you need to change the user interface now, replace existing components with another component, then you only need to modify the GET method and SET method related to this component properties, do not have to look up, modify all references to this component. Source code for class. See the code below for details:

privatefunction GetText: String; procedure SetText (const Value: String); publicproperty Text: String; read GetText write SetText; function TformDialog.GetText: String; beginResult: = Edit1.Text; end; procedure TformDialog.SetText (const Value: String) Beginedit1.text; = value;

Rule 12: ARRAY Properties

If you need to handle a series of variables in the form, you can define an attribute array. If these variables are some information about the form, you can also define them to form an array of properties of the form, so you can use Specialform [3] to access their values ​​directly.

The following code shows how to define an item of a ListBox component into a form default attribute array.

typeTformDialog = class (TForm) privatelistItems: TlistBox; function GetItems (Index: Integer): String; procedure SetItems (Index: Integer: const Value: String); publicproperty Items [Index: Integer]: string; end; function TFormDialog.GetItems ( Index: Integer): string; begin if Index> = ListItems.Items.Count then raise Exception.Create ( 'TformDialog: Out of Range'); Result: = ListItems.Items [Index]; end; procedure TformDialog.SetItems (Index : Integer; const alue: string; begin if index> = listitems.items.count thenraise exception.create ('tformdialog: out of range'); ListItems.Items [index]: = value; end; rule 13: Using properties Additional Side-Effects in Properties

Remember: One of the benefits of using attributes rather than accessing global variables (see Rule 10, 11, 12) is that when you set or read the value of the property, you may not intentionally harvest.

For example, you can directly drag the components directly on the form interface, set the value of multiple properties, call special methods, change the state of multiple components, or revoke an event (if needed), etc..

Rule 14: Hide Components (Hide Components)

I often hear those mad pursuits that are object-oriented to complain that the Delphi form contains some components declared in the Published part, which is not in line with the encapsulation principles for object-oriented ideas. They did put forward an important topic, but most people in them did not realize that the solution was actually on their hand, without rewriting the Delphi code, nor will they turn to other languages.

The components added to the form can be moved to the Private section such that other forms cannot access them. If you do this, you will need to set some form properties to the component (see Rule 11) and use them to access the status of the component.

Delphi puts all of these components in the Published section, because this way can ensure that these domains must be created in the .dfm file. When you change the name of a component, VCL can automatically associate this component object with it in the form. Because Delphi uses the RTTI and TOBJECT methods to implement this function, if you want to use this automatic implementation, you must place the reference to the Published section (this is why Delphi puts all the components in the Published part. ).

If you want to know more details, please refer to the following code:

procedure Tcomponent.SetReference (Enable: Boolean); varField: ^ Tcomponent; beginIf Fowner <> nil then beginField: = Fowner.FieldAddress (Fname); If Field <> nil thenField ^: = SelfelseField ^: = nil; end; end;

The above code is the SetReference method for the Tcomponent class, which can be called by INSERCOMPONENT, REMOVAMPONENT, and SETNAME. When you understand this, you should not think that if you move the component reference from the Published section to the privated segment, you will lose the automatic accessibility of the VCL. In order to solve this problem, you can add the following code from the oncreate event in the form:

Edit1: = findcomponent ('edit1') as tedit;

What you should do next is to register these component classes in the system. When you register for them, you can enable RTTI to be included in the compiler and can be used by the system. When you move these types of components to the Private section, you only need to register them once for each component class. Even when registration is not necessarily necessary, you can do this because additional calls for RegisterClasses are beneficial. Usually you should be responsible for generating the initialization section of the form to add the following code:

RegisterClass ([TEDIT]);

Rule 15: Object-Oriented Form Wizard (The OOP FORM WIZARD)

Repeat the two operations for each component of each form not only very annoying, but also quite wasting time. In order to avoid additional burden, I have written a simple wizard program for this. This program will generate some code that can complete the above two steps, and you need to do it several times to copy and paste it.

Unfortunately, this wizard program cannot automatically place the code in a suitable place in the unit. I am currently modifying this wizard, I hope to implement this feature. You can find more complete programs to my website (www.marcocantu.com).

Rules 16: Visual Form Inheritance

This will be a powerful tool if it is applied. According to my experience, the bigger the project you have developed, the more it can reflect its value. In a complex program, you can use the different level of relationship of the form to process a polymorphism of a group of related forms (Polymorphism).

Visual form inherits allows you to share some public actions of multiple forms: You can use shared methods, common properties, even event handlers, components, component properties, component event processing methods, and more.

Rules 17: Limit the use of domain data (Limit Protected Data)

Some programmers tend to use protected domains when creating classes with different classification systems, as private data cannot be accessed by subclavab. I can't say this doesn't matter, but this is definitely incompatible with encapsulation. The implementation of the protection data can be shared by all inherited forms, and once the original definition of this data changes, you must change all related parts.

Note that if you follow a rule such as hidden components (Rule 14), inheriting the form is impossible to access the private component of the base class. In a inheritance form, the code like edit1.text: = '' will not be compiled. Although this is quite inconvenient, at least in theory this is worthy of affirmation, not a negation. If you feel that the encapsulation is the most important, you need, please refer to the private segment of the base class.

Rules 18: Access Method in Protection Domain (Protected Access Methods)

Place component reference in the base class in private domain, and add some access functions to these components to get their properties, which will be a better way. If these access functions are only used inside these classes and is not part of the class interface, you should declare them in the protection domain. For example, the GetText and SetText methods described in Rule 11 can be declared as protected and we can edit text by calling setText (''). In fact, when a method is mirrored to an attribute, we can simply use the following code to reach the editorial purpose:

TEXT: = '';

Rules 19: Protected Virtual Methods

Another key point to implement a flexible grading system is to define some virtual methods you can call from external classes to get polymorphism. If this method is used, it will raise a situation in which other public methods call the virtual method in the protected domain. This is an important trick because you can customize the virtual method of the party to modify the action of the object.

Rules 20: Virtual Method for Properties (Virtual Methods for Properties)

Even the way to access the property can be defined as Virtual, which derived class can change the actions of the attribute without having to define them. Although this method is rarely used in VCL, it is indeed very flexible and powerful. In order to achieve this, just the need to define the GET and SET methods among Rule 11 as Virtual. The code of the base class is as follows:

typeTformDialog = class (TForm) Procedure FormCreate (Sender: Tobject); PrivateEdit1: Tedit; Protected function GetText: String; virtual; procedure SetText (const Value: String); virtual; publicconstructor Create (Text: String): reintroduce; overload; property TEXT: STRING read GetText Write setText; End;

In inherited forms, you can add some additional actions to overload virtual methods setText:

Procedure tForminherit.Settext (const value: string); begininherited settext (value); if value = '' Thenbutton1.enabled: = false;

summary

To do a good Delphi object-oriented programmer far non-I mention these rules mentioned above is so simple. There are some of these 20 rules that may require enough tolerance and time, so I can't force you to follow all of these rules. But these rules should be applied to your program by appropriate, and the more programmers who have developed, the more important participants, the more important these rules. However, even some small procedures, remember these rules and use them in the right place will also help you.

Of course, there are many other experience rules I have not involved, especially memory handling and RTTI issues, because they are very complicated, requires special descriptions.

My conclusion is to follow the rules I have listed above will pay a certain price, especially the extra code, but these costs will make you get a more flexible and strong program. I hope that the subsequent version of Delphi can help group we reduce these costs.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>

*********************************************************** *************** * Four, some elements of writing code * ********************************* ***************************************** A. Don't be in (for new hands) It is never necessary) TMYFORM = Class (TFORM) ..... ..... ..... End; define variables, try to define its own variables and procedure, etc. B. Under any circumstance, no matter how difficult the debugging situation, after the Begin carries back, first play two spaces and write program code. END must echo and the corresponding Begin echo on the same column. C. Delphi is case insensitive, but there is a number of quotes to keep the same spelling. D. Don't delete the code automatically generated by yourself, and let the bell, if you don't care, DELPHI generated programs automatically delete when Save Project and Build. (As long as Begin ... End does not write your own code) E. Formcreat, the control it contains is not established, it is not a reference. When Form1onCreat, you can't use form1.listbox1 ... but you can write: Listbox1 ......... This is Delphi's agreement, so don't ask me why. F. Form1 If it is Mainform, it is not possible to reference the form2 variable when OnCreat, because Form2 does not exist. After G. Form2.ShowModal, the program will execute the following code after Form2, and use Show is not the case. H. Do not perform too long, if it is no longer, in the gap of the big loop, you must call Application.ProcessMessages or the program will like a crash. *********************************************************** *************** * 5, Windows programming reward issues * *********************** ***************************************** TTIMER is used to perform some repeatedly Code, but if the execution time is too long, the next time Timer trigger will re-entry this code, that is, if there is no Timer1.enabled: = false; if there are two processes, there may be two processes in execution. This code, if you have access to a variable, one may be changed, one may be read, then there is unexpected problem. Similar to the issue, it will also encounter at other times. For example, when you are Show (not ShowModal), the two Visible FORMs will have some strange phenomena in common access to the same variable.

The newcomer is best to avoid such problems first, save trouble. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>

A habit of developing a Delphi programmer

Author:? Musicwind some ideas about developing habits, such as stuck in my throat to speak. The motivation will certainly do not exclude the possibility of defrauding participation, but on the other hand, I hope to provide some suggestions for the peers (the XING), or reference (hope is not a misunderstanding). At the same time, I hope that you can publish a point of view of my bad habits, and give criticism and adequate views. Thank you. One. Establishing a project catalog First, the first step is to do, of course, build a separate directory (don't laugh) for the new project. The directory name is the same name with the project name, or can be taken one, as long as it is clear, concise. Then create the following directorys in this directory:

: Use to store the project related development document (required description, summary design, detailed design, etc.);

: Use files such as ".dpr", "pAS", ". Dfm" in the Delphi source program;

: The ".dcu" file is stored in this directory, and the '.pas' and '.dcu' file are stored simply to make the Source directory more clearly;

: Storage project output file, such as ".exe", "DLL" or ".ocx", etc.

: Used to store log files; usually in this directory I will put a " programmer log .txt" file.

: Of course, it is the directory of the picture used in the storage project. In general, this directory is less. If other resources are used, they are also established, such as WAV, such as AVI, and more.

two. Set the project option

Create a new project in Delphi, save this project into the Source directory, while:

a. Choose an icon for this project as an icon for this project. Of course, this icon may be just temporary use, but it is always better than Delphi's default. Otherwise, how can you get yourself?

b. Set the Output Directory in the Project Options -> Directories / Conditionals page to bin directory;

c. Set the Unit Output Directory as the DCU directory.

three. Add a constant unit

Add a new Unit, saved as "Unt Consts.PAS" to save the constant used in the project.

four. About Forms (FORM) and Unit (Unit)

According to the Hungarian nomenclature, give the form, a form used to log in can be named 'frmlogin', and its cell name can be 'unlogin'. Typically, the names of the two corresponding FORMs and Unit should be consistent after removing the abbreviation of 'FRM' or 'Unt'. Adding this unit's annotation, the format of the comment can be referred to the source code of Delphi, but at least the following items should be included: function description; author; copyright; create time; final modification time; modification history, etc..

Set the newly created Form's CAPTION to the name of the Form class, instead of using Delphi default. For example, after the Form1 is renamed frmlogin, we got TFRMLogin's new form class, and Delphi automatically updated the CAPTION 'of' frmlogin '. According to me, the CAPTION should be 'tfrmlogin' is because we are designing a form TFRMLOGIN instead of only FRMLogin.

Many people have a habit of setting their CAPTION as the name of "operator login" in the design period. My habit is that constants such as "operator login" are usually stored in the UN Consts.PAS, defined by resourceString, or using const. As for the naming of the form's CAPTION, it should be a running period. So, I often operate CAPTION when TForm.onCreate event is triggered, such as:

Procedure tfrmlogin.formcreate (sender: TOBJECT);

Begin

Caption: = CSLogintitle;

....

END;

Fives. Using the Format function

There are three data in Iyear, IMONTH, IDAY, to show information such as "birthday: 1976/3/18", what do you usually do? Use s: = 'birthday:' INTOSTR (IYEAR) '.' INTOSTR (iDAY);? This is really too tired. My habit is to add a constant csbirthDayformat = 'birthday:% D /% D /% d' to save the display format in the UN Consts.PAS, then use S: ​​= Format, [Iyear, IMOMONTH , iDay]); This statement completes the assembly of data. The benefits of doing this are obvious, that is, you only need to maintain data in a local maintenance display format.

The Format function is powerful, I am very respect for it, what about you?

six. Storage about registry or INI file

I originally accessed the Registry I usually use Tregistry, and the access INI file usually uses TiniFile. The use of these two classes is different, so it is almost impossible to use the same code to access the registry and access the INI file. Really hurt!

I finally found the savior! That is the TregiStryiniFile class. View the Registry unit, we found that TregistryInifile inherits from TcusominiFile. TiniFile is also inherited in TcusominiFile. Therefore, using abstract class TCUSominiFile to achieve access to the registry or INI file is two. such as:

VAR

CSMINIFILE: TCUSominiFile; Begin

If bluSeinifile the// If INI file is used

CSMINIFILE: = TiniFile.create (CSRootKey)

Else

CSMINIFILE: = TregiStryiniFile.create (CSRootKey);

/ / Next, you can use CSMINIFILE to access the INI file.

/ / Access the registry with a similar access to the INI file.

Seven. About TSTREAM stream and TFileStream, TmemoryStream, etc.

TFileStream and TMemoryStream are inherited from abstract class TSTREAM, which means we can use a set of code to complete access to files and memory. Therefore, when some interfaces are defined, I tend to define the type of parameters as an abstract class, not a specific class. For example, to complete a function of the save function, define

Function Save (ASTREAM: TSTREAM): Boolean;

Comparison

Function Save (ASTREAM: TFileStream): Boolean;

To be more flexible.

The previous definition is forward-looking because it can be applied to the flow of new types that may occur later. The latter definition only applies to TFileStream this stream (of course, including TFileStream's subclasses), and more.

My habits: If there is an abstract class, try to define the parameters as the type of abstract class. After all, we cannot foresee the future.

Eight. Use more TACTION

Delphi 4 introduces the concept of Action, and add TACTIONLIST components in the Standard component column. The benefits of using Action is that the troubles of the status synchronization of the control status are swept away!

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>

Delphi programming skills highlights (1)

Dong Zhanshan

(Cotton Institute, Chinese Academy of Agricultural Sciences, Anyang, Henan 455112)

The famous American "Delphi Developer Magazine" is a professional magazine that many Delphi programmers must read in the world. We rarely read this excellent professional publication in China, but we can be in Inprise ( Http://www.inprise.com's web page see some excellent articles published by the magazine. At the same time, you can also subscribe to the Delphi usage skills provided by email, the subscription URL is http://www.zdtips.com/ddj/bor-f.htm. The author has filter out some very useful Delphi skills and articles, compiled, share with the vast Delphi enthusiast. What comments and suggestions can be sent directly to the author (dzs@126.com). Readers Please note that in this article, more content is described as an example, please use other versions of readers to be flexible according to the actual situation.

First, Delphi integrated environment and code debugging

A modify system information of Delphi

The default Delphi message, warnings, and exception description are English, translating these contents into another language or modifying them to make it suitable for your needs to edit resource files and change the corresponding string, these files are located BIN directory. The main resource files are: Sysutils unit information (files are not found, converted error messages, etc.) In sysutils.res, database error messages in dbconsts.res, VCL information in consts.res. Note that some strings use format characters, such as% s or% d, to generate the final string, in which case these characters should be retained in the appropriate location. B How to clear the useless code

Delphi provides powerful features of automatic code in the source code. In general, when you save a file, Delphi automatically deletes the type method in the source code to ensure the cleanliness of the source code. Under the premise of compiling and saving files, you can also clear the useless code, the method is: click "File" * "Save as ..." menu command in Delphi 3/4 (click "in Delphi 1/2" File "*" Save File As ... "menu command), open the" Save As ... "dialog window, click the" Cancel "button.

C Do not use floating function in the Delphi 4 integrated environment

You have no doubt that the Delphi 4 integration environment supports the floating function of most windows. However, sometimes you don't want a window to float. The floating window is very useful when needed, but it is very annoying when not needed. There are two ways to change the floating properties of a window.

The first method is: Each float window has a local menu item - Dockable, if you don't want a specific window with floating functions, simply right-click the window, select the Dockable menu item. The floating function of this window is closed until you select the Dockable item.

This technology can prevent specific windows from being stopped. But sometimes you just want to temporarily turn off the floating function, at this time, just press the key to drag the window.

D Add a project in the Tools menu

Press the F1 key in the Delphi integrated environment to open most Delphi Help headers, which can quickly open the help window of the relevant title. However, this quick way is unavailable to third-party tools and common questions (FAQs), Delphi provides a variety of methods that make it possible to quickly open these tools in an integrated environment.

The method of adding user projects in the Tools menu is: Click the "Tools" * "configure tools" command, open a dialog window containing all available Tools list, click the "Add" button, open the "Tool Properties" dialog window, set separately 4 edit box, then click the "OK" button, then click the "Close" button to complete the settings.

E set the condition breakpoint

In general, everyone will use breakpoint to debug the program, but how to use the condition breakpoint to debug the program? The condition breakpoint, as the name suggests, means that the breakpoint when you need to meet certain conditions. This breakpoint is very useful when debugging for a long for for or while cycle. When you only want to see the execution of a specific loop, you need to set a condition breakpoint in the loop. Delphi stops the implementation of the application when the conditions are met.

The method of setting the condition breakpoint is to create a breakpoint according to the regular method, click the "View" * "debug windows" * "breakpoints" command, pop up a breakpoint list window, right-click, want to set it to condition breakpoint Breakpoint, click the "Properties" command in the shortcut menu, open a breakpoint editing window, enter a logical expression in the condition domain of this window. When debugging, Delphi determines that this logical expression. When the logical expression is true, the interrupt program is run, returns the code window. F Don't let the integrated debugger interrupt the debugging process

When debugging, Delphi's integrated debugger monitors all runtime errors. When the debugger found a runtime error, the Delphi interrupt the application and returned to the design status and displays an error message window. When the error message window is turned off, you need to restart the launcher by , or press to continue the program. Undoubtedly, the Delphi integration debugger is very useful, but sometimes people are still troublesome. Can I temporarily turn off the integrated debugger? can. Use the following method to prevent the integrated debugger interrupt application:

1 Click the "Tools" * "Environment Options ..." menu command;

2 Click the "Preferences" dialog page label;

3 Short empty "Integrated Debugging Option" checkbox;

4 Click "OK" to complete the action.

This way when you debug an application in an integrated environment, the Delphi's integrated debugger detects the runtime error, no longer switches to the design status and displays the error message.

G debugging Delphi 3/4 integrated environment plug-in

In Delphi 1, the plug-in / experts who want to debug the integrated environment are very difficult. Delphi 3/4 provides the ability to debug DLL to simplify this work.

The first step is to ensure that the plug-in / expert does not include in the plugin / expert list of the Windows registry, then start Delphi 3/4 and load the expert DLL that needs to be debugged, modify the registry, so that Delphi 3/4 can call this DLL;

Step 2, click the "Run" * "parameters" menu command, open the "Run Parameters" dialog window, click the "Browse" button on the "Host Application" edit box on the "local" dialog page to find "Delphi32. Exe "program position (this example is C: / Program files / borland / delphi4 / bin / delphi32.exe);

In the third step, run the DLL to be debugged, start the second instance of Delphi, and load the DLL to be debugged, allowing it to debug it.

Second, the relevant skills for form design

A transparent pixel point

When an Image image is generally BMP file, a pixel point in the lower left corner of the picture determines which color in the lower left corner of the picture is transparent color. Any pixel point with this color is transparent on the button. If you don't want any pixel points on the picture, you need to set the color of this pixel point in the lower left corner of the image to a color different from any pixel point on the image.

B Automatically adjust the resolution of the form

When creating an application, it is always based on the resolution of the monitor. It is: if the application is designed at higher resolution, it may be greater than the user's valid screen size, when the user uses the program, it cannot be displayed. All form content brings inconvenience to users. A simple solution is to let Delphi automatically add scroll bars to solve this problem when running.

However, the automatic adjustment ratio process using Delphi will produce more professional results. At runtime, Delphi obtains the screen resolution of the system and saves the result in the Pixelsperinch property of the application's Screen object, and then adjusts the form to the current resolution using the value of this attribute. Remember, in order to effectively use this technology, you need to set the schela of the form as true, and only use the TrueType font. If the developer, use the small font of Windows, you should set the form's autoscroll property to false ( False).

C Set a custom color for the control

Forms and various controls have a color property that when you select their Color properties, you can select a Windows system default in the list box, or create a custom color so that they look Different. The steps for setting custom colors for forms or controls are as follows:

1 Double-click the component's Color property, pop up the color dialog window;

2 Select a base color that is closest to you;

3 Click the "DEFINE CUSTOM Colors >>" button, the color dialog window will extends and display a chromatographic area;

4 Use the Cross Cursor to select the color you want in this chromatogram, then click the "Add to Custom Colors" button; so your selected colors are added to the color dialog window;

5 Click the "OK" button to apply the colors that just defined to the selected control.

D shrinks the steps

Most programmers are watching the "(relying on the grid) Snap to Grid" feature when designing the form, saving the time of resettlement components, however, sometimes you need to fine tune its location and size.

First: Move the components on the form moving a pixel point. First, select the component you want, then press the key, press the cursor key, select the control to move a pixel point once, the direction is the same as the direction of the cursor keys.

2: Each time a pixel point adjusts the size of the control. Check the control, press the button, press the cursor key, depending on the direction of the cursor keys, the selected control is enlarged or narrows a pixel point each time.

E Control the effective method of the scroll bar

TFORM's HorzscrollBar and VertscrollBar properties use Tracking sub-properties to manage formal display, and the tracking property is a Boolean properties. If this property is set to true, the form moves with the user drags the scroll bar; if this property is set to the false, the form does not move with the user to drag the scroll block, only when the user releases the scroll block. This difference is important for users who view lists and images. If you want to smoothly display the list and image, set the tracking property to true, but when the image or list information is particularly complex, the scrolling of the window is particularly slow. If you want to quickly display the list and image information, set the tracking property to false, so that the scrolling of the window will speed, but because the actual position cannot be seen, it is difficult to master when used. In addition to TFORM, TscrollBox components also use Tracking properties to manage their display content.

F Select the appropriate combination box

Delphi provides a 5-class combo box that has the same characteristics, but there are also different features. Understand the difference between it, help programmers choose the appropriate combination box type as needed.

All combo boxes are a combination of a list box and an edit box, and the user can select or enter the value directly in the edit box. This entry will appear in the edit box when the user selects from the list box. Different features of the 5-class combo box determine their display and how to interact with the user. The following table lists the unique features of the five types of combo boxes. Table 1 format description

Format Description Simple This format is a list box to display an edit box, and the user can select the entry from the list box, or enter the text DROP-DOWN directly in the edit box, other features are similar to SIMPLE format. There is a drop down button on the left side of the edit box, click the list box, select the entry from it; you can also enter the project directly in the Edit box. Drop-Down List This is one of the most limited conditions in the combo box. The display format is similar to Drop-Down, and the list box is not displayed. The user clicks the drop-down button opens the list box and selects the entry from it, but cannot enter the text directly in the edit box. OwnerDrawFixed This combo box is similar to the Simple class, which is different from the entry height in its list box is set according to the value defined by the user at the ItemHeight. The OwnerDrawVariable This combo box is similar to the OwnerDrawFixed class, which is characterized by the height of the list entry.

When there is enough space and a short list on the form, it is more appropriate to use the combination box in the Simple format. Otherwise, use the combo box in the Drop-Down format. When you want users to select the entries from the predefined items, use the combo box in the Drop-Down List format. When a variable height list item is required, the latter is used.

G makes non-visual components easy to identify

Non-visual components have no title attributes, when multiple similar non-visual components in a form, because they look exactly the same, it is difficult to identify. Delphi provides a variety of ways to place the name of the non-visual component under the component icon, making them easy to identify. The setting method is as follows:

1 Click "Tools" * "Environment Option", pop up a dialog window;

2 Click the "Preferences" tab, switch to the Preferences dialog;

3 Select the "Show Component Captions" checkbox;

4 Click "OK" to complete.

At this time, on the current design form, you can see a label under each non-visual component. After this option is set, all forms are valid.

H tag accelerator

For components containing the CAPTION attribute, adding a shortcut is easier, just add "&" symbols before the specific character in the CAPTION property. So, how do I add a shortcut to the control without the CAPTION attribute? Taking a TMEMO Control Add Express as an example: Place a TMEMO control on the form, then place a TLABEL control next to it, set its CAPTION property to "& Memo1", set the TLabEl's FocusControl property to " Memo1. Compile and run this program, press shortcut to quickly access the contents of MEMO1 control. This technology does not require any code, which can be applied to all controls without CAPTION properties.

I Select the parent components of the component and multiple components

In the Delphi integrated environment, when the form is designed, if the parent component is invisible, it is more difficult to select a parent component. In fact, there is a simple method: Select a sub-component that is invisible, press the key to select its parent components.

When there are multiple components on the form, you can easily select them by pressing the left mouse button to drag the mouse. However, if you want to choose a set of components placed on a panel class component (such as TPANEL), click and drag the parent components under this component to achieve the expected results. In order to avoid this, you need to press the key and then perform the above operation. Also, press the key, click a component, you can select or deselect one component. This is very useful when you need to choose submas on different panel components.

J Move the component or adjust its size

Move the component or adjust its size on the form, sometimes you want to perform one pixel point once. This can be done using Object Inspector to modify the Left, Top, Width, and Height properties of the component. But there is a simpler way to use the and keys to add arrow keys. Press the The combination key adjusts the size of the component in the direction pointing to the arrow; press the The combination key is moved in the direction pointing to the arrow. These two combinations are effective at the selected plurality of components.

K Display components on all pages of TNotebook components

If you want to display some components (for example, browse the database list box) on all pages of TNotebook or TPAGEControl components, you don't need to set these components on each page, just create them first, then add TNotebook or TPAGEControl. Controls, adjust their size and position, right-click the TNotebook or TPAGEControl component, click the "Send to Back" property in the pop-up menu, then the first added control is displayed on the TNotebook or TPAGEControl control, press The usual method adds other components to TNotebook or TPAGEControl components.

This method is only valid for the control, so TDBText needs to replace TDBEDIT and set it to read-only, the boundary property setting is empty, and the Ctrl3D property is set to false. Similarly, you need to replace TLABEL components with TPANEL components.

Another more effective way is to write a piece of code to dynamically change the location of the component, which is valid for all components. Take TPAGEControl as an example, insert the following code in its onchange event handler:

Procedure TFORM1.PAGECONTROL1CHANGE (Sender: TOBJECT);

Begin

Panel1.parent: = PageControl1.activePage;

// Other Code Follows

END;

When actually use, use your own components instead of Panel1. Remember: When you place the component to run on the program run, on the dialog box first displayed on the dialog page to avoid writing code in the oncreate event handler in the form.

L cancel the drag operation

When designing a form, if you move a component when moving a component, what should I do? Undoubtedly, you want to cancel this step of drag operation, in fact, it is very simple. Press key until the mouse button is not released, this component will return to the original position.

M is formatted by Y2K format TDATETIMEPICKERS display

Use TDATETIMEPICKER.DATEFORMAT in Delphi to specify the date format, DateFormat is the TDTDATEFORMAT type property, which is Dfshort or DFLONG. If DFSHORT is taken, the date format is similar to "3/21/97"; if DFLONG, the date format is similar to "Friday, March 21, 1997". In order to be compatible with the Y2K format, you need to set the date format to YYYY-MM-DD. According to the above explanation, the TDATETIMEPICKER component is not applied when set to a short date format. However, if you set a short date (using area setting) in the control panel, TDATETIMEPICKER will use Windows settings, so it can still be used.

Delphi programming skills highlights (2)

Dong Zhanshan

(Cotton Institute, Chinese Academy of Agricultural Sciences, Anyang, Henan 455112)

Third, the relevant skills for code design

A use special characters

The application sometimes needs to use characters from keyboards, for example, copyright symbols (?), £ 5, and yet (¥), etc. To enter these characters, you need to use a Windows word mode mapping program.

Open the word mode mapping program, select the appropriate font from the Fonts list box, select a character in the following list, and the ASCIii code value of this character will be displayed in the lower right corner of the window. For example, the ASCII code of the pound is 0163. When pressing the key on the keyboard, press 0163, you can enter the pound. You can also use the selection and copy buttons of the Word Mode Map to copy the selected character to the Windows clipboard, and then paste the characters into the target program code using the "Paste" command or press the keyboard command.

B Setting position tag in your code

The Delphi Code Editor allows some location tags to be placed in the source code, which is the kind of the kind of WordStar. The purpose of using the location tag is to quickly switch between the document different locations. For example, when you create a class function, I hope to look at its declaration part, the location mark is sent to the field. Setting the shortcuts of the location mark in the code editor to: <1-9, any number>, mobile to the shortcut key of the existing location tag is: <1 Arbitrary numbers between -9>. In the default, Delphi does not save the location tag set in the code, in order to save Delphi to the file, the next time you use it, you need to "Preferences" on the "Environment Options" dialog window. "Dialog page selection" AutoSave "multiplex option, so Delphi saves the location tag information into the project's DSK file.

C Use the keyboard shortcut to quickly make code block indent

When editing the program source code, the different calibration distances are maintained between different blocks, which can make the code easy to read. After the program structure is adjusted, you need to adjust the amount of code of the code, usually we switch between different code lines using the upper and lower sponsor keys, add or reduce indent space with , , and keys. Old users who have used Turbo Pascal may still remember that its integrated editor provides a set of shortcuts to quickly switch the calibration of the code block, which is very convenient to use. In fact, the Delphi Integration Editor also provides two combinations to quickly increase or reduce the amount of multiplexed code. First, select the code block to be changed, and press the key combination to extend the amount of the code block, and press the key combination to reduce the amount of the code block.

D Select a rectangular area in the Code Editing window. You know that you can select a rectangular area in Microsoft Word 97, which also has similar functions in the Delphi integrated editor. In order to select a rectangular area, press the button to do not place, then select the text with the mouse and keyboard.

E jumps to the VCL source code

By the following method, you can jump to the source code of the VCL library routine:

3 Press the key;

3 Make the mouse light to the name declared by the type declaration you want to see its source code;

3 Click it to adjust the VCL source code code for viewing.

F record keys and play back in an integrated environment

When using the Delphi writing program, you may want to record this code's hit button, you can rely on it, reducing it, reducing ineffective labor when needed. Just like a group of commands just entered by the F3 key in the DOS era. The Delphi Integration Editor also provides this feature: Press Start Recording Key, then type the keys you want to record, then press to stop recording. Press to play back the hit just recorded. Note: This feature is only valid in the default editor keyboard mode. To find you using the editor keyboard mode, click the "ENVIRONMENT OPTIONS" menu item, click the Editor tab, you can see the currently used editor keyboard mode in the Editor Settings combo box. .

G code template

Delphi's code template (Code Template) can reduce your input. In the Delphi editor, press the key to open the template selection list box; or type a template name, then press to extend the template.

Select the "Tools" * "Environment Options" menu command, click the Code Insight tab, you can add your own code template. Users can enter any code, not just an array, a loop, and the like. The template is useful in the following cases: the standard initialization code, comment block, or other use for the standard, function, and method.

H use the code to complete the function

One of Delphi 3/4 is a function of code to complete the characteristics. This feature pops up a list box and lists all possible assignments. The following example demonstrates this feature.

Start a new project, double-click the form, switch to the code window, write the form's oncreate event handler, as follows:

Procedure TFORM1.FormCreate (Sender: TOBJECT);

VAR

Temp: String;

Temp2: integer;

Begin

END;

At this time, "Temp: =" is entered in the process body, press Key, slightly, you can see a list containing some variables, methods, and objects, and potential effective assignments. Some of the options have an omitted number, indicating that these objects or records containing compatible methods or fields can be assigned.

Fourth, database programming skills

A Take advantage of Database Form Expert

Database Form Expert, called a wizard in Delphi 3, is valid for all versions of Delphi. Form expert's use is to help users quickly create database applications. However, it is not enough that it produces the form of control and field position, and the size is not moderate. However, its advantages are still obvious. Obviously, the programmer needs to design the form with the customer to make it more beautiful and practical. Database Forms Experts can establish a data access control and complete their basic connection properties. Although the location and size is not suitable, it can establish most data input fields and their labels, so take advantage of the database of databases to save the design of the form of the form. B Convert database to CSV format

If you want to convert the database table to a comma-divided text file (CSV format), you can use the following process code:

Procedure BackuptableTableTocsv (TableName: Ttable);

VAR

I, J: Integer; (* i-field, j-record *)

String; (* Record string *)

TheStringList: tstringlist; (* Temp Storage *)

Begin

s: = '';

TheStringList: = TSTRINGLIST.CREATE;

With Tablename Do Begin

Try

Active: = True;

Except

ShowMessage ('can't activate the database:' Name);

END;

For J: = 0 to (RecordCount-1) Do Begin

s: = '';

For i: = 1 to (Fieldcount-1) do begin

(* Add Next Field W / Comma Delimiter *)

s: = s (Fields [i] .sstring ',';

End; (* i for *)

THESTRINGLIST.ADD (S);

NEXT;

END; (* J for *)

TheStringList.Savetofile (Name '. CSV'); (* Memo1.Lines. *)

ShowMessage (Name 'has been converted.');

CLOSE;

End; (* with *)

End; (* backuptabletocsv *)

C Dynamic Update DBGRID Row Colors

DBGRID is a good control for displaying table data, this example is intended to demonstrate how to dynamically change the text color therein. For example, we want to display the country's information in dbgrid, if the country's population is more than 200 million, the data line will be a blue. Tested data in the OndrawColumnCell event handler of the DBGRID component and changing the color, the program code is as follows:

Procedure TFORM1.DBGRID1DRAWCOLUMNCELL (Sender: TOBJECT)

CONST RECT: TRECT; DATACOL: Integer; Column: tcolumn;

State: TGRIDDRAWSTATE);

Begin

If Table1.fieldbyName ('population'). Asinteger> 20000000 THEN

DBGRID1.CANVAS.FONT.COLOR: = CLBLUE

DBGRID1.DEFAULTDRAWCOLUMNCELL (Rect, Datacol, Column, State);

END;

This is a simple and practical technology, in addition to displaying the data content, you can also display the meaning of information, such as too many people, account overdraft, part arrival, etc. D Create a report when running

Use the QRCREATELIST function provided by Quick Report to establish a report at runtime. Here is an example:

QRCREATELIST (Areport, Self, Qrycountry, 'Country Report', FieldList);

Among them, the name of the report is the name of the report; QRYCOUNTRY is a data table name; 'Country report' is the report title; FieldList is a list of fields included in the report, if this list is equal to NIL or contains 0 items, all fields will be used.

The code to establish a report at runtime is as follows:

{Default field list is nil}

Fieldlist: = nil;

{Make sure the new report object points to NIL, otherwise, when using the qrcreatelist function to establish a report, it will be wrong.

Areport: = NIL;

{Call the QRCREATELIST function to establish a report, will automatically establish a report containing the column headband and the detailed belt,

Users can add a group with a group, summary belt before preview or printing}

QRCREATELIST (Areport, Self, Qrycountry, 'Country Report', FieldList);

E use field editor

Field editor (Fields Editor) In addition to the permanent field object, you can help programmers quickly place the database control into the form. Methods as below:

Drag and drop a field name from the field editor to the form, when you release the mouse button, Delphi adds a TLABEL and a TDBEDIT control to the form. These established controls use the properties set in the field editor: including Alignment, DisplayLabel, DisplayWidth, and EditMask properties. Of course, DBEDIT's DataSource and DataField properties are also set.

F Accelerate the search process of the database

Want to increase the retrieval of the database? Call the DISABLECONTROLS method of the data table before performing data retrieval, disconnecting the DataSet and DataSource components. When the retrieval ends, call the ENABLECONTROLS method of the data table, re-establish contact between DataSet and DataSource components, so that you can save Update the time of data control, thus accelerate the speed of the retrieval. Here is an example:

Unit unit1;

.

.

Type

TFORM1 = Class (TFORM)

DataSource1: TDataSource;

Table1: TTable;

Button1: tbutton;

.

.

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

VAR

SeekValue: STRING;

Begin

Table1.disableControls;

Table1.FindKey ([SeekValue]);

Table1.enableControls;

END;

End.

G enhances the processing power of data sheets

How to add program performance while reducing code maintenance using an application using a data sheet? This can be done using the Delphi data module. Methods as below:

1 Add a data module (Data Module) in the program plan;

2 Place a data sheet access component on the data module form: Add a TTable and TDataSource components to the data module form for each data sheet used by the application and set their DatabaseName, TableName, and DataSet properties correctly. 3 Add the application of the data module unit on each form using the data table so that the data control assembly can be used on these forms, and the DataSource of these components is set to the appropriate TDataSource component of the data module.

After using the Data Module Form, there is three advantages to all data sheets: First, avoid adding data table access components to each form; second, if the same data fields are different windows Use and modify in the body, such modifications are shared between different forms, and do not need to add any code; third, since the program reduces the code of the same data table, the program performance Reach a certain improvement.

Delphi programming skills highlights (3)

Dong Zhanshan

(Cotton Institute, Chinese Academy of Agricultural Sciences, Anyang, Henan 455112)

V. Skills related to operating systems

How how to determine the version of Windows

Windows has multiple versions, an application or flexibility to run in multiple Windows versions, or compiles the instructions to compile into one operating platform.

Here is a method to enable the application to dynamically determine the version of the Windows operating system. The application can obtain Windows version information by calling the Windows API function GetversionEx, which uses a TOSVERSIONIC variable ginseng, all Windows version information is included, the structure is as follows:

Typedef struct _OSVersionInfo {

DWORD dwosveionsInfosize; // Structure size

DWORD DWMAJORVERSION; // Main version

DWORD dwminorversion; // Deputy Version

DWORD dwbuildnumber; // Establish a version

DWORD DWPLATFORMID; // Operating Platform Identification

TCHAR SZCSDVERSION [128]; // version identity string

} Osversioninfo;

Below is an example of using this function:

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

VAR

.IonInfo: tosversioninfo;

Begin

VersionInfo.dwosveionsInfosize: = Sizeof (TOSVersionInfo);

GetversionEx (VersionInfo);

Case VersionInfo.dwplatformID of

VER_PLATFORM_WIN32S:

Do_something;

VER_PLATFORM_WIN32_WINDOWS:

DO_SOMEOTHING;

VER_PLATFORM_WIN32_NT:

Do_somethingelse;

END;

END;

How much is B memory?

The following describes how many methods can determine how much system memory, use states, etc. More importantly, the application can utilize this technology to determine the size of the client's available memory, using this information, the application can dynamically optimize the performance of the program. For example, if there is enough memory to utilize a dual cushion optimization bitmap operation.

The above features can be done using the Windows API function GlobalMemorySTATUS. GlobalMemoryStatus receives a change in TMEMORYSTATUS that you can get Windows current memory status by this parameter. The structure of TMemoryStatus is as follows:

Typedef struct _MemoryStatus {// mstdword dwlength; // sizeof (memorystatus), the size of the record structure

DWORD dwmemoryload; // Percentage of memory

DWORD dwtotalphys; // Physical memory bytes

DWORD dwavailphys; // Free physics available memory byout

DWORD DWTOTALPAGEFILE; / / Page file byte

DWORD dwavailpagefile; // Freedom bytes of page files

DWORD DWTOTALTUAL; / / User byte number of users in address space

DWORD dwavailvirtual; // Free user byte

MemoryStatus, * lpMemoryStatus;

Below is an example of using the GlobalMemoryStatus function:

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

VAR

MemoryStatus: TMEMORYSTATUS;

Begin

MemoryStatus.dwlength: = SizeOf (MemoryStatus);

GlobalMemoryStatus (MemoryStatus);

Label1.caption: = 'Total Physical Memory:' INTOSTR (MemoryStatus.dwtotalphys);

END;

C gains a lost time

When testing hardware or software efficiency or when tracking the user's response speed, you need to measure the time. Most programmers use a TDATETIME variable and the NOW function to achieve the purpose of determination of the time.

However, a simpler way is to use the Windows API function GetTickCount. The GetTickCount function returns milliseconds from starting Windows. If the function is successfully returned, the return value is from the number of milliseconds that caused Windows. Below is a usage example:

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

VAR

i: longint;

StartTime, EndTime: Double;

Const

Clock_Tick: double = 1000;

Begin

I: = 0;

StartTime: = GetTickCount;

While (I <10000000) DO i: = i 1;

EndTime: = gettickcount - starttime;

ShowMessage (Format); [endtime / clock_tick]);

END;

D Hidden / Display Windows 95 taskbar

I don't want to let you write the Delphi program that hides / displays the Windows 95 taskbar, which can be implemented in the program.

Procedure hidetaskbar;

Var WNDHANDLE: THANDLE;

WNDCLASS: Array [0..50] of char;

Begin

Strpcopy (@wndclass [0], 'shell_traywnd');

WndHandle: = FindWindow (@WndClass [0], NIL);

// Hidden taskbar

ShowWindow (WndHandle, SW_HIDE);

END;

Procedure showtaskbar;

Var WNDHANDLE: THANDLE;

WNDCLASS: Array [0..50] of char;

Begin

Strpcopy (@wndclass [0], 'shell_traywnd'); WNDHANDLE: = FINDWINDOW (@WndClass [0], NIL);

// Display taskbar

ShowWindow (WNDHANDLE, SW_RESTORE);

END;

E Capture Date and Time Sign

Want to display the date and time sign of the file? There is no simple function in Delphi to complete this feature, but we can combine the two functions to achieve this.

First, the filegetdate function returns the DOS date and time of the file, then the FileDateTodateTime function converts the date and time to the TDATETIME type variable, and finally, the DateTimetostr process converts the TDATETIME type variable into a string. Examples are as follows:

Procedure tform1.button1

VAR

Thefiledate: String;

FHANDE: Integer;

Begin

Fhandle: = fileopen (YourFileName, 0);

Try

ThefileDate: =

DateTimetostr (FilegetTodateTime (FilegetDate (Fhaandle));

Finally

FileClose (Fhaandle);

END;

END;

The formatting parameters using DateTimetostr can adjust the output of the output. Even if you don't need to display the date and time, you can also use this technology to compare and calculate the date of calculation.

F avoiding the drive A is not ready for error (Not Ready Error)

When your program access A driver, it may be interrupted by the 'Drive Not Ready' system error, you can use the following function to test the drive to avoid this, the code is as follows:

Function Diskindrive (Drive: char): boolean

VAR

ERRORMODE: WORD;

Begin

Drive: = Upcase (Drive);

IF not (Drive in ['a' .. 'Z']).

Raise EconvertError.create ('NOT A Valid Drive ID ";

ErrorMode: = setErrorMode (SEM_FAILCRIRALRORS);

Try

IF Disks Re (Ord (Drive) - $ 40) = -1 THEN

Diskindrive: = FALSE

Else

Diskindrive: = TRUE;

Finally

SetErrorMode (ERRORMODE);

END;

END;

The working principle of this function is: First convert the drive to uppercase letters, then turn off the system error report function, perform disk operations, the operation successfully returns True, indicating that there is a disk in the drive; the operation failed to return false, indicating an error, the function ends Open the system error report function.

G hide the app

If you not only want the app to hide the form, do not want the application to display on the taskbar, you can use the following command:

ShowWindow (Application.handle, Sw_hide);

This command is useful for applications that activate using the System TRAY icon.

H Redirect DOS Application

Sometimes you need to redirect a DOS application. The following code can help you complete this work:

{--------------------- created ------------------ Description: Executes a (dos!) App Defined in the commandline

Parameter Redirected to Take Input from InputFile

And Give Output to Outputfile

Result: True on SUCCESS

Parameters:

CommandLine: The Command Line for the app,

INCLUDING ITS FULL PATH

InputFile: The Ascii File Where from the app

Takes INPUT

OutputFile: The Ascii File to Which the app.

Output is redirected

Errmsg: additional error message.

Can Be EMPTY

Error Checking: YES

Target: Delphi 2, 3, 4

Author: Theodoros Bebekis, Email Bebekis@otnet.gr

NOTES:

Example Call:

CreatedSprocessRedirected ('c: /mydosapp.exe ",

'C: /inputput.txt',

'C: /output.txt',

'Please, Record this Message')

-------------------------------------------------- ----------------}

Function CreatedSprocessRedirected (const commandline, inputfile,

Outputfile, errmsg: string): boolean;

Const

Routine_id = '[function: createDosprocessredirected]';

VAR

Oldcursor: TCURSOR;

PCOMMANDLINE: ARRAY [0..max_path] of char;

Pinputfile,

Poutputfile: array [0..max_path] of char;

Startupinfo: TStartupinfo;

PROCESSINFO: TPROCESSINFORMATION;

SecaTRRS: TsecurityAttribute;

HappProcess,

Happthread,

Hinputfile,

HOUTPUTFILE: THANDLE;

Begin

Result: = FALSE;

{Check for InputFile EXISTENCE}

IF not fileexists (InputFile)

THEN

Raise Exception.createfmt (routine_id # 10 # 10

'Input file *% s *' # 10

'Does not exist' # 10 # 10

Errmsg, [InputFile]);

{Save the cursor}

Oldcursor: = Screen.cursor; Screen.cursor: = CRHOURGLASS;

{COPY THE Parameter Pascal strings to null terminated

Strings}

Strpcopy (PCommandline, CommandLine);

Strpcopy (PinputFile, InputFile);

Strpcopy (PoutputFile, OutputFile);

Try

{Prepare SecaTRRS Structure for the createfile calls.

THIS SECATTRS STRUCTURE IS NEEDEDITS CASE BECAUSE

WE Want The Returned Handle Can Be inherited by Child

THIS TRUE WHEN RUNNING Under Winnt.

As for win95, the documentation is quite ambiguous}

Fillchar (SecaTRRS, SIZEOF (SECATRS), # 0);

SecaTrrs.nlength: = Sizeof (SecaTRRS);

SecaTrrs.lpsecurityDescriptor: = nil;

SecaTrrs.binherithandle: = true;

{Create the appropriate handle for the input file}

HinputFile: = CREATEFILE

Pinputfile,

Pointer to Name of the file}

Generic_read or generic_write,

Access (read-write) mode}

FILE_SHARE_READ OR File_SHARE_WRITE,

Share mode}

@Secatrrs,

Pointer to security attributes}

Open_ALWAYS,

{how to create}

FILE_ATTRIBUTE_NORMAL

OR file_flag_write_through,

{File Attributes}

0); Handle to File with Attributes to COPY}

{Is HinputFile a Valid Handle?}

IF hinputfile = invalid_handle_value

THEN

Raise Exception.createfmt (routine_id # 10 # 10

'WinApi Function CreateFile Returned An'

'Invalid Handle Value' # 10

'for the input file *% s *' # 10 # 10

Errmsg, [InputFile]);

{Create the appropriate handle for the output file}

HOUTPUTFILE: = CREATEFILE

Poutputfile,

Pointer to Name of the file}

Generic_read or generic_write,

Access (read-write) mode}

FILE_SHARE_READ OR File_SHARE_WRITE,

Share mode}

@Secatrrs,

Pointer to security attributes} Create_Always,

{how to create}

FILE_ATTRIBUTE_NORMAL

OR file_flag_write_through,

File attributes}

0);

Handle to File with Attributes to Copy}

{Is HoutputFile a Valid Handle?}

If houtputfile = invalid_handle_value

THEN

Raise Exception.createfmt (routine_id # 10 # 10

'WinApi Function CreateFile Returned An'

'Invalid Handle Value' # 10

'for the output file *% s *' # 10 # 10

Errmsg, [OUTPUTFILE]);

{Prepare Startupinfo Structure}

Fillchar (StartupInfo, Sizeof (Startupinfo), # 0);

Startupinfo.cb: = sizeof (startupinfo);

Startupinfo.dwflags: = startf_useshowWindow OR

STARTF_USESTDHANDLES;

Startupinfo.wshowwindow: = sw_hide;

STARTUPINFO.HSTDOUTPUT: = HOUTPUTFILE;

Startupinfo.hstdinput: = hinputfile;

{Create the app}

Result: = CREATEPROCESS (NIL,

{Pointer to Name of Executable Module}

PCOMMANDLINE,

{Pointer to Command Line String}

NIL,

{Pointer to Process Security Attributes}

NIL,

{Pointer to Thread Security Attributes}

True,

{Handle Inheritance Flag}

HIGH_PRIORITY_CLASS,

{CREATION flags}

NIL,

{Pointer to New Environment Block}

NIL,

{Pointer to Current Directory Name}

Startupinfo,

{Pointer to Startupinfo}

PROCESSINFO);

{Pointer to Process_inf}

{Wait for the app to finish its job and take the

Handles to free the later}

IF Result

THEN

Begin

WaitforsingleObject (ProcessInfo.hprocess, Infinite);

"= processinfo.hprocess;

Happthread: = processinfo.hthread;

end

Else

Raise Exception.create (routine_id # 10 # 10

'Function Failure' # 10 # 10 errmsg;

Finally

{Close the Handles.

Kernel Objects, Like The Process and The Files

WE CREATED IN THIS, Are Maintained by A Usage

Count. so, for cleaning up purposes, we have to to

Close The Handles to Inform The System That We don't

Need The Objects Anymore}

If HOUTPUTFILE <> 0 Then CloseHandle (HOUTPUTFILE);

IF hinputfile <> 0 Then CloseHandle (HINPUTFILE);

IF HAPPTHREAD <> 0 Then CloseHandle (HAPPTHREAD);

IF HapppRocess <> 0 Then CloseHandle (HAPPPROCESS);

{Restore the old cursor}

Screen.cursor: = OldCursor;

END;

End; {createdosprocessredirected}

Delphi programming skills highlights (4)

Dong Zhanshan

(Cotton Institute, Chinese Academy of Agricultural Sciences, Anyang, Henan 455112)

I Method for launching other programs in the program

Use the shellexecute function (in unit shellapi) to execute a program or transfer a file, whether this file is an executor or an image or document, etc. The method of use is as follows:

Shellexecute (Handle, 'Open', Pchar (Edit1.Text), '', ', SW_SHOWNORMAL);

Shellexecute (Handle, 'Open', 'C: /Doc/bar.doc', '', '', SW_SHOWNORMAL);

Its effect is similar to double-click a file in Windows Explorer. If the execution function is successful, the return value is the handle of the open application routine, or the handle of the DDE server application. If the execution function fails, the return value is an error number that is less than or equal to 32. Change 'Open' to 'Print', this function can print the specified file.

J Use the list of system image

If you need to access the Win95 system image list, here give a specific method. The first function saves the index of the system image list to a special type of file:

Function GetFileicoIndex (filename: string): integer;

VAR

EXT: STRING;

SHFILEINFO: TSHFILEINFO;

Begin

EXT: = filename;

ShgetfileInfo (Pchar (EXT), 0, SHFILEINFO,

Sizeof (SHFILEINFO), SHGFI_SMALLICON OR

SHGFI_SYSICIONDEX or SHGFI_TYPENAME);

Result: = shfileinfo.iicon;

END;

Connect the system image list to the TLISTVIEW control below. Note We set up the shareimages attribute of dynamically built image lists, which makes it possible to unlike the image owned by the Windows system. Add:

WITH YOURLISTVIEW DOBEGIN

SmallImages: = TimageList.createsize (16, 16);

Smallimages.ShareImages: = true;

SmallImages.Handle: = Shgetfileinfo ('*. *', 0,

SHFILEINFO, SIZEOF (SHFILEINFO), SHGFI_SMALLICON OR

SHGFI_ICON OR SHGFI_SYSICIONDEX);

LargeImages: = TIMAGELIST.CREATE (NIL);

Largeimages.shareImages: = true;

LargeImages.Handle: = shGetfileinfo ('*. *', 0,

SHFILEINFO, SIZEOF (SHFILEINFO), SHGFI_LARGEICON OR

SHGFI_ICON OR SHGFI_SYSICIONDEX);

END;

When you turn off the form, add the following code in its OnDestroy event handler, release the application system resources:

YourListView.smallImallImality.free;

YourListView.LarGeImages.Free;

K keep your form on the desktop

When we want a form to keep on the top of the desktop, you can define the FormStyle property of the form to keep the form on top. However, after using this method, the form will flash when switching the form of the form. In order to avoid flashing of the flip form mode, you can use the Windows API function setWindowPos to solve this problem, the method is as follows:

Setwindowpos (Form1.handle, Hwnd_topmost, Form1.LiD, Form1.top, Form1.Width, Form1.Height, 0);

Instead of "Form1" with the actual form name, you can set the form to keep the form to the top of the desktop. To switch the form back to the normal form, call the following command:

Setwindowpos (Form1.Handle, Hwnd_Notopmost, Form1.Width, Form1.Height, 0);

L Tracking the temporary directory of Windows

Both Window 95 and NT use a directory to save temporary files, this temporary directory is not fixed, to ensure that the application uses the correct temporary file directory, you can use the Windows API function getTemppath to get the path of this directory, using the format as follows:

DWORD GetTemppath (DWORD NBUFFERLENGTH, LPTSTR LPBUFFER);

In order to facilitate the use of this Windows API function to get the temporary file directory path, a Object Pascal function is written:

Function GetTempdirectory: String;

VAR

Tempdir: array [0..255] of char;

Begin

GetTemppath (255, @Tempdir);

Result: = STRPAS (Tempdir);

END;

Use GetTemppath to get the path indicated by TMP environment variables; if TMP is not defined, you can get the path indicated by the TEMP environment variable; if TMP and TEMP do not exist, use the current directory as a temporary directory.

M handling your own hotkey

Applications can use many Windows default hot keys. However, sometimes you need to add your own hotkey to the form. How do you capture them when users typing them? To solve this problem, you should first set the form's keypreview property to true, then add the following code in the form's onkeyDown event handler: if (ssctrl in shift) and (chr (key) in ['a', ' A ']) Then ShowMessage (' Ctrl-a ');

The onkeyDown event handler will capture the keystroke and perform the specified code.

6. Object Pascal programming skills

A Simple method for calling the base class initialization routine

If a derived initialization routine is written, it is desirable to pass the parameters to the base class, which is generally used:

TMYBUTTON.CREATE (Aowner: Tcomponent);

Begin

Inherited Create (Aowner);

{Do Custom Things ...}

END;

However, if the initialization routine of the derived class has the same parameters as the base class, it is not necessary to express the initialization methods and parameters of the base class, only need to be called as follows:

TMYBUTTON.CREATE (Aowner: Tcomponent);

Begin

inherited;

{Do Custom Things ...}

END;

B Safety array cycle

An Object Pascal array is an ordered collection of a set of similar elements. If you don't know the upper and lower bounds of the data, how can I access the elements? Using the Low and High function, you can guarantee that each element you have, please see the following instance:

VAR

MyArray: array [2..11] of integer;

Position: integer;

Begin

For Position: = Low (MyArray) To high (MyArray) do

MyArray [Position]: = 0;

END;

With this technology, the code does not contain any immediate number, the program code is relatively independent of the up and down interval of the array. In addition, since these two function calls are converted to constants when compiling, there is no cost price.

C ensures that the field is valid

Put the code that validates the validity of the Field is a natural thing in the onclick event handler of the button of the button. However, in order to ensure that the validity of the field can be verified in any case, the ONCLOSEQUERY event of the form is required. In this way, no matter how to close the program, you can guarantee the field to get verification and ensure the uniqueness of the code.

Procedure TFORM1.FORMCLOSEQUERY (Sender: TOBJECT)

Var canclose: boolean;

Begin

CANCLOSE: = FALSE;

IF (edit1.text = '') THEN Begin

{Error handling}

end

Else

IF (Radiogroup1.ItemIndex <0) THEN Begin

{Error handling}

end

Else

CANCLOSE: = True;

END;

Set the caclose property to false at the beginning of the process to ensure that OnCloseQuery does not close the form. Then, verify each field and process an error. Finally, if there is no error, set canclose is true.

D Quick Custom Program Dynamic Menu

In preparing the application, we sometimes need to dynamically customize according to the use level of the user program menus, the usual practice is to switch menu item (TMenuItem) component of the Enabled property, so as to prohibit or open a menu item, do so with a very complex and easy to make mistake. In fact, by assigning the TAG attribute of each menu item, the program menu can be quickly safely safely safely customizes based on the user's level. The method is as follows: 1 Establish a menu according to the normal method;

2 Depending on the user's level, give each menu item TAG property assignment, for example, set "File" "Open" and "File" "Off" attribute to 2, will "file" "New", "file "*" Save "and" File "*" Print "TAG property set to 3;

3 Plus the following code in the oncreate event handler:

For i: = 0 to mainmenu1.Items.count -1 do

Begin

IF Userlevel

MainMenu1.Items [i] .visible: = false

Else

MainMenu1.Items [i] .visible: = TRUE

For j: = 0 to mainmenu1.items [i] .count -1 do

IF userlevel

MainMenu1.Items [i] .Items [J] .visible: = FALSE

Else

Mainmenu1.items [i] .Items [J] .visible: = true;

END;

4 This code can dynamically determine which menu item display or which menu item is not displayed based on the user's usage level.

The above code can only dynamically switch menu entry, if you want to dynamically change the menu entry of all menus, you need to use the form's Components property, the code is as follows:

For i: = 0 to ComponentCount -1 DO

IF Components [I] is TMenuItem Then

TMenuitem (Components [i]). Visible: =

(Userlevel> = TMENUITEM (Components [i]). Tag);

This code is more compact and efficient and is a good tool for customizing the application menu.

E Verify the date of the user input

Experienced programmers know the date that should not be blindly accepted. It is true that you can check the date of the date, the month, and the day is correct. However, do you check if the date does actually exist? For example, assume that the user enters 9/31/97, month, day, and year, it is valid, but there is no 31 in September. In order to check if a date string is valid, you can use the following code:

VAR AdateTime: TDATETIME;

...

Try

AdateTime: = strtodate (InputDateString);

Except

// EconvertError error - invalid date or date format

END;

This code is equally effective to Ruitian.

F Establish a global condition definition

When compiling the program, use the condition definition to determine the included or exclude a piece of code, which block is determined by the compiler that is part of the execution file. The usual condition definition includes sending debug information to a file and optimized Windows 95 or Windows NT. Below is an instance of a conditional definition:

Unit unit1;

{$ Define mydef1} // Establish your own condition definition

{$ Ifdef mydef1} // If the condition definition is announced

/ / Update the label display

Label1.caption: = 'MyDef1 is declared.'; {$ ENDIF}

Sometimes, you need to use the same condition definition in multiple units of a project, you can use the following method:

4 Click "Project" * "Options", pop up the Project Options dialog window;

5 Click the Directories / Conditionals tab;

6 Enter myDef1 in the "Conditional Defines" edit box;

7 Click the "OK" button to return.

G to add horizontal scroll bars for TListBox components

Delphi's TListBox component automatically adds a vertical roll, that is, when the height of the list box is not covered, the vertical scroll bar is automatically displayed. However, when the width of the entry is greater than the width of the list box, the horizontal scroll bar will not be displayed automatically. Of course, you can add a horizontal scroll bar in the list box, the method is to add the following code in the oncreate event handler of the form:

Procedure TFORM1.FormCreate (Sender: TOBJECT);

VAR

I, MaxWidth: Integer;

Begin

MaxWidth: = 0;

For i: = 0 to listbox1.items.count - 1 do

If MaxWidth

MaxWidth: = ListBox1.canvas.textwidth (listbox1.items.strings [i]);

SendMessage (ListBox1.Handle, LB_SethORIZONTALEXTENT, MAXWIDTH 2, 0);

END;

This code first looks for the width of the longest entry in the list box, then uses the lb_sethorizontalExtent message to set the width of the horizontal scroll bar of the list box (represented by pixel point), plus two additional Pixel.

H Show information skills with messageDLG functions

Delphi provides a simple way to display the information dialog window --- Use the MessageDlg function to display a dialog window at the center of the screen window. The statement of the MessageDlg function is as follows:

Function Messagedlg (const msg: string; atype: tMSGDLGTYPE)

Abuttons: TMSGDLGBUTTONS; Helpctx: longint: Word;

From its function declaration, it does not show that it can display variable information. However, it is not the case, it can display variable information, by connecting variables to the display information string, and can be added to the string to the string, and the subsequent information is displayed on a new line. Please see examples:

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

VAR

ErrorDesCR: String;

Begin

ErrorDesCr: = 'Call 911';

Messagedlg ('Error Code: 123' # 13 ErrorDesCr, Mtinformation, [Mbok], 0);

END;

I Dynamic Delete Columns of TListView Components

If you have tried to delete a TLISTVIEW component at runtime, you don't allow this to do so. Can't you really? Here you will introduce the Delphi function that is not introduced in a document and use it to do this. This function is defined in the CommCtrl unit, the function declaration is as follows: function listview_deletecolumn (hwnd: hwnd; icol: integer): BOOL;

Where hwnd is the handle of the TListView component, ICOL is the index number of the column to delete, pay attention to the index number is calculated from zero. Here is a usage example:

Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

Begin

Listview_deletecolumn (MyListView.handle, 1);

END;

J Access protection class properties

Sometimes, you need to access the protection class at which you declare, the easiest way is to use the following declaration in your own unit:

Texposed = Class ();

E.g:

TexposedWincontrol = Class (TwinControl);

Because TexPosedButton is now declared in your unit, you can access all protected properties - including inherited. How to use it? Examples are as follows:

IF sender is twinControl.

With texposedwincontrol (sender) do

Begin

// Caption & text is the same in TwinControl

ShowMessage (CAPTION);

TEXT: = 'EASY, ISN'' ket IT? ';

END;

K Use format instead of the INTOSTR function when debugging the program

If you were previously a Visual Basic user, when you display debugging information, you might use format $ to display variables in the msgbox function, however, in Delphi, the format function is quite different, so many users will with the following code. :

ShowMessage ('undocumented feature in' Application.exename

'Variable now Equal to' INTOSTR (i_var));

In order to use the Format function, you need to know which Format string used. The Format string looks very complicated, but only three of them need to be known, which is equivalent to occupying symbols, will replace variables in the second parameter of the Format function. These three strings are:

% D - represents a whole number

% N - represents a floating point number

% s - represents a string

Therefore, the above example will be changed to:

ShowMessage (Format ('undocumented feature in% s. Variable is now equal to% d',

[Application.exename, i_var])))

The same is the same, but the code is clearer and easy to modify.

When you want to display a large variable, the Format function shows its true power, see the example:

ShowMessage (Format ('V1 =% D and F2 =% N in routine% s', [V1, F2, 'Unit2.Pas']));

In addition, with MessageBox instead of the MessageDlg or showMessage function can compress the size of the EXE file, you can also use the format function to do this, as follows: var sz: array [0..255] of char;

MessageBox (0, Strpcopy (SZ, Format ('v1 =% D and F2 =% n in routine% s ",

[V1, F2, 'Unit2.pas'])), 'Debug', 64);

Once you start to apply Delphi's Format function, you will get less and less use of the INTTOSTR function!

Delphi programming skills highlights (5)

Dong Zhanshan

(Cotton Institute, Chinese Academy of Agricultural Sciences, Anyang, Henan 455112)

L Use non-VCL classes

Re-use code in Delphi is very easy, but writing a VCL for accessing common code is very complicated, why not write a class unit? In a large project, maintaining and commissioning a class is relatively easy because each class is self-contained, there is no interference with global variables. Below is a class of classes:

Unit CLS_MINE;

Interface

Uses Wintypes, WinProcs, Messages, Systemils, Classes

Type

TMYCLASS = Class (TOBJECT)

Private

{Private variables and hidden functions}

FStarted: Boolean

Fflag: boolean;

Procedure setflag (TRUEFALSE: BOOLEAN);

Function getflag: boolean;

public

{Public methods and profment}

Function init: boolean;

Function getExedirectory: String

Property Started Read Fstarted Write fstarted;

Property Myflag ReadFlag Write setflag;

END;

IMPLEMentation

Function TMYCLASS.INIT: BOOLEAN;

Begin

FSTARTED: = True;

.. Initialise stuff ..

END;

Etc.etc.

When using classes, add CLS_MINE in the USES clause, declare a TMYCLASS type variable myclass, then call myclass.create to create classes (remember when calling myclass.free logout class when not using the class), you can use its method And attributes, such as evtedir: = myclass.getexedirectory or myclass.myflag: = true, just like using a VCL class, do not need to be recompiled each unit.

M Number of rows where the cursor is located in the TMEMO component

If TMEMO can tell you where the cursor is not very good? However, when you click the TMEMO component, it sets the selstart attribute as the current cursor's character position, which is a location index value of all text in TMEMO. You need to calculate the leader and test SELSTART, translate it into a line number, use The Windows API function can easily get the number of rows where the cursors in the TMEMO component are available:

LINENUMBER: = SendMessage (Memo1.Handle, EM_LINEFROMCHAR, MEMO1.SELSTART, 0);

LINENUMBER is a longint type variable that converts it to an Integer type variable. N Let users choose all items

In order to allow users to select all text in the memory component and editing component, set the keypreview property of the form to the true, and write the following handler for the form's onkeypress event:

Procedure TMYFORM.FORMKEYPRESS (Sender: TOBJECT)

Var key: char); begin

IF (ActiveControl Is TCUSTOMEDIT) and (key = # 1) THEN

Begin (ActiveControl as tcustomed) .selectall;

Key: = # 0; end

END;

Key: = # 0 statement makes it forced to make a beep when non-text input.

O How to get a piece of text in the richedit component

When using the Richedit component, I hope only some of the text, but I don't want to set the selection interval and use the SELTEXT attribute, you can use the following code implementation:

{Overrides Wrong TtextRange Definition in richedit.pas}

TTEXTRANGE = Record

CHRG: TCHARRANGE;

LPSTRTEXT: PansTRTEXT: PansChar;

END;

Function RegetTextRange (Richedit: TrichEdit; Beginpos, Maxlength: integer): String;

{Richedit - Richedit control, Beginpos - the absolute index value of the first character, maxlength - the maximum number of characters obtained

VAR

TEXTRANGE: TTEXTRANGE;

Begin

IF Maxlength> 0 THEN

Begin

SETLENGTH (RESULT, MAXLENGTH);

WITH TEXTRANGE DO

Begin

Chrg.cpmin: = beginpos;

Chrg.cpmax: = beginpos maxlength;

LPSTRTEXT: = PCHAR (RESULT);

END;

SetLength (Result, SendMessage (Richedit.handle,

EM_GETTEXTRANGE, 0, longint (@TextRange)));

end

Else Result: = '';

END;

This function can be used to extract the words under the current cursor:

Function RecharindexBypos (Richedit: TrichEdit)

X, Y: integer): Integer;

{Function returns absolute character position}

{for Given Cursor Coordinates}

VAR

P: tpoint;

Begin

P: = Point (x, y);

Result: = SendMessage (richedit.handle,

EM_CHARFROMPOS, 0, Longint (@P));

END;

Function ReextractWordFromPos (Richedit: Trichedit

X, Y: integer: string;

{X, y - point coordinates in rich edit control}

{RETURns Word, Under Current Cursor Position}

VAR

Begpos, Endpos: Integer;

Begin

Begpos: = recharindexbypos (RicheDit, X, Y); if (Begpos <0) or

(SendMessage (Richedit.handle, EM_FINDWORDBREAK,

WB_CLASSIFY, BEGPOS) and

(WBF_BREAKLINE or WBF_ISWHITE) <> 0) THEN

Begin

Result: = '';

EXIT;

END;

IF sentMessage (Richedit.handle, EM_FINDWORDBREAK,

WB_CLASSIFY, BEGPOS - 1) AND

(WBF_BREAKLINE or WBF_ISWHITE) = 0 THEN

Begpos: = sendMessage (richedit.handle,

EM_FINDWORDBREAK, WB_MOVEWORDLEFT, BEGPOS;

Endpos: = sendMessage (richedit.handle,

EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, BEGPOS;

Result: = trimright (RegetTextRange (Richedit, Begpos,

Endpos - begpos));

END;

P How to use the interface type in Delphi 3 to ask all forms

A form is a Tcomponent component that provides a COM object (Vclcomobject / COMOBJECT) package. So it doesn't need _addref / _release yourself, but you need _addref / _Release that it is parked objects. In Delphi 3, this means that the component (form) needs to implement a dumb object for reference count. In Delphi 4, there is no need to assign a dummy object because Delphi is only _addref / _Release when the object is assigned. The following example is an ISHOWME interface type asking all the forms:

Procedure ExecuteshowMeonAllForms;

VAR

IDX: Integer;

SHOWMEOBJECT: ISHOWME;

Objectassigned: boolean;

RefcountedObject: IUNKNOWN;

Begin

RefcountedObject: = TINTERFACEDObject.create;

For idx: = Screen.formcount - 1 Downto 0 DO

With screen.forms [idx] do begin

// Find Out if we need to assign a vclcomobject.

Objectassigned: = NOT assigned (vclcomobject);

IF ObjectAssigned Then

Vclcomobject: = Pointer (RefcountedObject);

Try

// GetInterface Calls ShowmeObject's _Release

// & _addref, Which IS

// Implement by RefcounTedObject.

IF GetInterface (Ishowme, ShowmeObject) THEN

ShowmeObject.showme;

Finally

IF Objectassigned Then Begin

ShowmeObject: = nil; // Calls vclcomobject._release.

Vclcomobject: = nil; // now We can Safely // Reset Vclcomobject.

END;

END;

END;

END;

Q broadcast information in the application

VCL uses TwinControl's Broadcast method to notify all classes in the application. A control must explain an event handle to respond to the message, if you want to stop this message, let message.result returns 0.

VAR i: integer;

HMESSAGE: TMESSAGE;

Begin

HMESSAGE.MSG: = WM_USER 1;

HMESSAGE.WPARAM: = 0;

HMESSAGE.LPARAM: = 0;

For i: = 0 to screen.formcount-1 do

Screen.Forms [i] .Broadcast (HMESSAGE);

END;

The Tscreen class has all the forms in the application. The event handle is as follows:

TMYBUTTON = Class (TButton)

protected

Procedure EventHandler (Var Message: TMESSAGE);

Message WM_USER 1;

END;

.

Procedure TMYBUTTON.EVENTHANDLER (VAR Message: TMessage);

Begin

// Commands

Message.Result: = 0; // Event Continues

END;

R millennium problem

In the SYSUTILS unit, there is a full-term valence TwodigityEarcenturyValue, the default is 0, and some Y2K issues can be solved. How does it work?

If today's date is 10/22/1998, the value of TwodigityEarcenturyWindow is subtracted, namely: 1998 - 50 = 1948, any date of the date between 48-98, 10/22 The '19' in / 1998.

TwodigityearCenturyWindow decided to convert the two years of the two bits of the string to the number of centuries used when numeric dates. This value is subtracted with the current year before extracting the century. This method can extend the life of software using two digits. In fact, the best solution to Y2K issues is to do not accept two-digit number, requiring 4 digits to exclude the confusion of the century. The following table lists the methods of using TwodigityEarcenturyWindow for centuries.

Current Year TwodigitcenturyWindow Take Value Century Started Strtodate Function Value '1/01/03' '1/01/68' 1/01/50 '1998 0 (Default) 1900 1903 1968 1950 2002 0 (Default) 2000 2003 2068 2050 1998 50 1948 2003 1968 1950 2002 50 1952 2003 1968 2050

S Dynamic Save Form Control

Want to dynamically save all control values ​​on a form to a file? With the initialization file (INI file) and RTTI, you only need to write a code, no matter how much control on the form, you can write their values ​​to the specified file. Similarly, write an inverse process, you can read it directly in the value of the file and set to the corresponding control.

VAR

SSECTION, SFileName, SIDENT: STRING

InImyfile: tinifile;

Begin

Try

InIMYFILE: = TiniFile.create (sfilename); for i: = 0 to (Self.componentCount - 1) DO

Begin

SSECTION: = Self.name;

IF Components [I] IS TEDIT THEN

Begin

With Components [i] as Tedit DO

Begin

Sident: = Name;

IF TRIM (Text) = '' THEN

InImyFile.WritString (SSECTION, SIDENT, '0')

Else

InImyFile.WritString (SSECTION, SIDENT, TEX);

END;

end

Else IF Components [I] is Tcheckbox Then

Begin

Sident: = Components [i] .name;

InImyFile.WriteBool (SSECTION, SIDENT, (Components [i] AS

Tcheckbox) .checked;

end

Else if {All Control Types used on the form on the form

Begin

END;

End; {for i}

Finally

InImyFile.Free;

End; {TRY..finally}

End; {end of savetofile}

The result file is similar to:

[Form Name]

Edit_ucost_c_3 = 61.80

Edit_ucost_c_5 = 66.30

Edit_ucost_c_6 = 69.90

Edit_ucost_c_7 = 64.20

Edit_ucost_c_8 = 66.30

CBShowUtilization = 1

T use long file name method

Now, the use of long text names containing spaces is very common, using Paramstr (1) function, this long text name cannot be properly obtained. For example, when you pass the "ABC Company, Inc.dat" by command line parameters, paramstr (1) only returns ABC, which is not the long text name you want. This is because Paramstr (1) stops when encountering the first space. The solution is to use the following loadcmdlinefile process:

Uses

System, SYSUTILS;

Procedure loadcmdlinefile;

VAR

SCMDline: String;

I: integer;

Begin

IF paramcount> 0 Then Begin

SCMDline: = '';

{Call paramcount time paramstr function, plus a tail space,

Ensure that the long text name with spaces correctly has been processed.

For i: = 1 to Paramcount DO

SCMDline: = SCMDLINE PARAMSTR (i) '';

{Interception tail with space}

SCMDline: = trimright (scmdline);

{Guarantee file before opening the file}

If FileExists (SCMDline) THEN Begin

{Code to open the file}

END;

END;

END;

U makes some of the content of the form visible

To make the part of the form, the relevant portion of the form is placed on a separate TPANEL component, and the Visible property of the panel assembly is set to false, remember to change the size of the form.

For example, if you put an auxiliary part on the Panel1 component, it is on the bottom of the form, and you want the user to display or hide it by pressing the Button1 button, the code is as follows: Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);

Begin

IF Panel1.Visible Then Begin

Panel1.visible: = false;

Height: = height - panel1.height;

Button1.caption: = "Show more options";

end

Else Begin

Panel1.visible: = true;

Height: = height panel1.height;

Button1.caption: = "hide more options";

END;

END;

V Make EXE programs only run once

The following code ensures that the EXE program only runs once:

Procedure TFORM1.FormCreate (Sender: TOBJECT);

Begin

{Search Database to see if the program is running}

IF GlobalFindatom ('program_running') = 0 THEN

{If you don't find it, add it to the database}

Atom: = GlobalAddatom ('program_running ")

Else Begin

{If the program has been run, display information and exit the program}

Messagedlg ('program has been run!', MTWARNING, [Mbok], 0);

Halt;

END;

END;

Procedure TFORM1.FORMDESTROY (Sender: TOBJECT);

Begin

{When you exit the program, remove the added entry from the data table}

GlobalDeleTeatom (Atom);

END;

Seven, small knot

In the information of the Internet, there are countless treasures waiting for us to discover, develop, the author is just in the internet, even if there is an ideaful to share the happiness of the people of the world, only Text.

In fact, there is a real red gold in all corners of the Internet, and the discovers can discover their experiences to publish their public, and provide you with a key to the knowledge treasure house.

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

New Post(0)