Deep Delphi Programming

zhaozj2021-02-11  184

Deep Delphi Programming

Zuo Wei

Friends who have just been in contact with Delphi may be most interested in it is rich, powerful VCL (visual components). Just throw a few components on the form, even if you don't want to write code, you can easily make a practical value, which is exciting. However, VCL is only a small part of Delphi, and Delphi's excellence is far from being expressed on the VCL. If you only stay in the stage of using VCL, then you will never be a real Delphi master. Remember, you must exceed VCL to come into contact with the core of Delphi. So, what is hidden behind the VCL of Delphi? This article will discuss two relatively advanced Delphi topics: OOP and database programming. This article assumes the reader already has the basics of Delphi programming, for example, familiar with the general grammar of the Pascal language, master simple VCL use, will write basic database programs using the Data-Ware component, and so on. This article does not repeat the use of the use of the VCL. 1. OOP OOP English full name is Object Oriented Programming, translated is object-oriented programming. OOP is a very important programming idea. Maybe you will not be interested in this abstract thing, but almost any master will tell you: "The language is not important. It is important to program ideas." Everyone knows that Delphi's language basis is Object Pascal. This is Borland to increase the development of object-oriented characteristics in traditional Pascal language, and special crowns use Object's words to show the difference between the traditional PASCAL language, which can be seen to object technology. It can be said that Delphi builds on the Object Pascal, while Object Pascal is built on top of object-oriented technologies. In fact, not only Delphi, OOP is also the foundation of many other modern programming languages ​​such as C , Java (Visual Basic not fully supports OOP). Skilled OOP technology is to grasp the necessary conditions of Delphi, it is the way to enter the realm of the master, and is also one of a mature programmer. After understanding OOP technology, many things that have made you confused will be solved. Interestingly, although Delphi is completely OOP, a programmer that is completely not understanding OOP can also write programs using Delphi, because Delphi will automate the vast majority of work. When you start learning Delphi, you may not be able to imagine that when you add a button simply on the form, Delphi will do how complicated work! But since it is interested in deep into Delphi, becomes a real programmer, we should have curiosity to Delphi's details. These theories may make people feel boring and daunting. In fact, when you master it, you will feel nothing. Of course, you need enough perseverance. OOP has three main features: 1.1 Data package let us first see a code: type tdate = Class Mout, day, year: integer; procedure setValue; function leapyear: boolean; end; we first Will see the class key, its Chinese is called "class". Category is a very important concept. Depending on the authority, the class is: a user-defined data type, which has its own instructions and some operations.

A class contains some internal data and some process or function forms, usually describes the common features and behaviors of some very similar objects. This definition may be more embarrassed. You can imagine the class imagination as a special RECORD type, which may not only contain data, but may contain functions and processes (known in OOP). These data and methods are collectively referred to as class members. The above class is obviously a date type, which includes the three data members of Mouth, Day, Year, and two methods of SetValue, Leepyear. By the way, in Delphi, the habit is used as the prefix of each class as a letter T, as in Viusal C , is used as the prefix of each class as each class in VIUSAL C . Mout, Day, Year These three data members specify the year, month, day of the date. The setValue method assigns these three data members, and Leepyear checks if the year is a leap year. Here we give the implementation of these two methods: Procedure Tdate.SetValue (M, D, Y): Integer; Begin mout: = m; day: = d; year: = Y; End; function tdate.LeApyear: boolean Begin if (Year Mod 4 <> 0) THEN LEAPYEAR: = False Else IF (Year Mod 100 <> 0) Leepyear: = True Else IF (Year Mod 400 <> 0) Leepyear: = false else Leepyear: = true; End; After these definitions can be called, they can call them: var aday: tdate; begin // build an object aday: = tdate.create; // Used ADAY.SETVALUE (1, 1, 2000); if aday. Leepyear Then ShowMessage ('leap year:' inttostr (aday.year)); // Release the object aday.free; end; let's explain the meaning of these code line by line. The line behind VAR declares a variable of a TDATE class. How do we use it after declaring a variable? Use the CREATE method of the TDATE class to create an object of this class and give it an ADAY variable. Now we have also contacted another important concept in OOP: object. What is an object? In short, the object is an example of a class, or that it is a variable of a class defined data type. When a class object is established, the system assigns a piece of memory. For example, we define a variable A as an Integer type, then Integer is a data type, A is an instance. The relationship between classes and objects is similar to the relationship between the two. Difference classes and objects are very important, and even some professional programmers often get them. Careful readers may notice that in the definition of the TDATE class, there is no CREATE method. So where is this Create method? The CREATE method is that each class has an implicit method, and its role is to establish an instance of this class. Note that here, class and other data types are different. Other data types can be used directly after declaring variables, and class types must be used after using the CREATE method to create its instance (object).

In fact, in C and most other OOP languages, the variables of a class can establish objects of this class at the same time. Delphi (including its twins brothers C Builder) in this regard, must be CREATE to truly build an object. At the same time, when this object is no longer needed, you must manually call the free method to release this object (of course, the Free method is also implicit). This is related to Delphi's unique "object reference model", interested friends can check the relevant information, I will not say much. This situation has created a very interesting phenomenon, that is, programmed beginners often forget to create it before use, thus error, but from C to Delphi, the master often makes the same mistake ... Bless you a trick When the compiler appears in "Read of Address: ffffffff", most of the half is because Create before using the object, can check the code from this regard. Also, don't forget to use Free release when you don't need it, otherwise it may cause memory leakage. In the middle of the code to establish and release the object, it is the code using the object. The data of the access object is very simple, and there is no difference between the RECORD type. You can access them in some expressions: aday.year: = 2000; aday.mouth: = 1; aday.day: = 1; Similarly, you can use a point expression to call the object. If you read the code to implement some of the code, you can easily find that Aday.SetValue (1, 1, 2000) is assigned to three data members, and the ADAY.Leapyear call returns the current date. Is it a leap year. At this point, the meaning of the whole code is clear. However, the class is not just as simple. The above example is a very simple class that can directly access any members (data and methods). But some group members cannot be accessed casually. Delphi Differently distinguish these members' access: Table 1Private This type of member can only access the PUBLIC this type of member in the declaration class can be accessed from anywhere in the program to access protected that type of members can only Access in the declaration class and the declaration class

Protected types of members and what is "derived class", etc. We stay again to discuss, now we will focus on the top. The PUBLIC type is the type in the above example, this is very well understood. The private type, according to the simple explanation in the table, can only be accessed in the class (that is, the class belonging), which is not visible. So, how will the PRIVATE type member use? Simply put, it is to access it through a PUBLIC class. Let us look at a new example: Type Tdate = Class Private Mouth, Day, Year: Integer; Public Procedure SetValue (M, D, Y: Integer); Function Leapyear: Boolean; Function GetText: String; End; in this class These three members of Mouth, Day, Year are declared as Private members, so they are not accessible elsewhere. That is, if you use aday.year: = 2000; such code, the compiler will report an error. However, we can use the setValue method to assign them: aday.setValue (1, 1, 2000); this line code is legal, because the setValue itself is a member of the TDATE class, and it is a public member. The use of GetText methods can get the current date value (this is also a unique way to get the date value). Such settings make some members of the class implied, and users can only use them with some special methods. Those who can be accessed by external code are called the interface. What is the benefit of this? First, this allows the author of the class to detect the assigned content. For example, the user may give an invalid date to the object from March 40. After hidden some members, the author of the class can detect these values ​​in the code code, which greatly reduces the opportunity to generate errors. Second, use the specification class, the author can modify the code inside the class at any time, but the code used to use this class does not need any modifications! This makes the code maintenance into a relaxed event, especially for large software for multiplayer. This is called the encapsulation of data. This is the first characteristic of OOP. A excellent OOP programmer should determine which important data package will be determined when designing, and give a high efficiency interface. It should be pointed out that the discussion of the Private section in Table 1 is completely correct for "standard" OOP language (e.g., C ), but there is an exception to Delphi. In Delphi, Private members can be accessed anywhere in the declaration class (.PAS file) in the declaration class in addition to the declaration class, regardless of the relationship between the code and the declaration. Strictly speaking, this is a violation of the principle of OOP, I don't understand why Borland is doing this (it is said to be convenient). This is a problem that is often involved in the discussion of the favorable and disadvantage of Delphi.

1.2 Inherited and derived us to see a code: Type TNewdate = Class (TDATE) PUBLIC FUNCTION GETTEXTNEW: STRING; END; Function GetText: String; Begin Return: = INTOSTR (MOTH) ':' INTOSTR (DAY) ': ' INTSTOSTR (YEAR); END; It can be seen that a class name included in parentheses will appear behind the Class. This syntax indicates that the new class inherits an old class. Inherited the original class, it is called a class, also called a subclass, and is also known as the base class, also called the parent class. What is the relationship between derived classes and base classes? When derived class inherits from a base class, it automatically has all data, methods, and other types of base classes, and does not need to be described in the derived class. For example, you can use the TNewDate class like this below: Var aday: TNewdate; begin aday: = tNewdate.create; aday.setValue (1, 1, 200); if aday.Leapyear Then ShowMessage ('leap year:' INTOSTRR Aday.year); aday.free; end; and derived class can also add its own data and methods on the basis of the base class. You can see a new method GetTextNew in the TNewDATE class. The implementation part of this method is given: function getTextNew: string; begin return: = getText; end; then call it: aday.getTextNew; this new method is working very well. Why the getTextNew method must call the getText method in the base class, and cannot directly use those codes in the GetText method? The reason is that three members of Mouth, Day, Year are declared as Private members, so they can't be accessed even in derived classes, so they must call the GetText method in the base class, indirectly use them. If you want to use them directly, you can change the properties of these three members from private to protected. As can be seen in Table 1, members of the protected attribute can be accessed in the declaration class and the declarative class of the declared class, but still cannot be accessed by these two cases. Now we can finally understand that this special attribute actually provides a great convenience: it makes the members of the class to avoid confusion, while it can make the derived class easy to use them. (If you are a careful person, you may find a small leak in the middle of the above words. When you really visit the base class Private member, you may be surprised that the program can also compile By and normal operation! In fact, this problem is not related to OOP itself. I have said above, in Delphi, private members can be accessed anywhere in the declaration class, so if the TNewDate class and TDATE class In the same .PAS file, this situation is not surprising.) How is it, is it very wonderful? Through this inheritance mechanism, the class is no longer only packaged in data and methods, which provides openness.

You can easily inherit a powerful class, then add the features you need, and you don't need any modifications to the base class. Instead, the original author can reflect it immediately in your new class. This is very compliant with the reuse of the code. This inheritance mechanism is also very conforming to the situation in the real world. It is conceivable that "animals" in general is a class, with some of its own characteristics (members); "dog" is a derived class of "animals", which has all characteristics of animals, and also has its own unique features (Four legs, Wang Wang, etc.). This class of "dog" can continue to derive, such as "Black Dog" "White Dog", which has its own characteristics (black color, white color, etc.) in addition to the full characteristics of the dog. Specific to a living dog, you can think it is an example (object) of "Black Dog" or "White Dog" (or other dog). OOP This simulation of the real world is not only greatly simplified by code maintenance, but also makes revolutionary changes in the entire programming idea, and the modular programming has a flying progress. If you have read the VCL's information or even its source code, you can find that the entire VCL is built on this powerful package-inheritance. You can see a detailed VCL hierarchy, like a huge family spectrum, and various VCL components are inherited by layers. For example, a simple TForm class, is a product after many times Inheritance: TObject - TPersistent - TConponent - TControl - TWinControl - TScrollingWinControl - TCustomForm - TForm not only Delphi's VCL, Visual C in the famous MFC (Microsoft Foundation Class, Microsoft Basic Category Library), as well as OWL (Object Window Library, Obage, Object Window Category) in Borland C , is built on this mechanism. Different, for the first two languages, you have to spend a few months of Kung Fu to basically master the comparative classes, in order to write a more practical value, and in Delphi, most of the work Delphi Already have been automatically completed. For example, each time you add a form to the program, Delphi automatically derives a new class from TForm (default to tform1) and creates an instance for this new class. You have changed this form (add components and code), nothing to add some new features for this derived class; you can also use your own way to maximize, minimize, and change the size. Because these codes are implemented in the base class, they are inherited by the derived class. This is the greatness of Delphi. Of course, the VCL of Delphi is not inferior to MFC or OWL (in fact it is evolved by the latter). (Some people may ask the situation of VB. VB does not support inheritance, so there is no complex class library, and its own control is also very poor, mainly using the ActiveX control.). Maybe you have realized, itchy is itchy. However, what we want to discuss is of course not just simple.

At the 1.1 section ("Data Pack"), we told the "CREATE method to have an implicit method for each Class." In fact, this statement is inaccurate. The truth is that in Delphi, all classes inherit the most basic class toject, even in the name of the class name you did not specify. The CREATE method is a method of TOBJECT classes, so it is, for all classes, all classes automatically obtain the CREATE method, whether you have implemented it. Think about it, I will know: If there is no Create method, how do I build an object? You may notice that the CREATE method is a special method. Nice, the Create method is really very special, even its "title" is no longer function or procedure, but a constructor. You can see some examples in the source code of the VCL: Constructor Create; constructor is not only a Delphi keyword, but also a noun for OOP methodology. Correspondingly, there is a DESTRUctor. The former is responsible for completing the work of creating an object, assigns memory for it, the latter is responsible for the release of this object, reclaiming its memory. What should be noted is that the name of the Constructor is generally CREATE, but the name of Destructor is not Free, but Destroy. For example: deStructor Destroy; then, why use Free to release the object in the previous code? The difference is that DESTROY will directly release the object, and free will now check if the object exists. If the object exists, or the object is not NIL, it will call DESTROY. Therefore, the program should be used to use Free to release the object, which is more secure. (But note, free will not automatically set objects to NIL, so after calling Free, it is best to manually place the object to be set to NIL.) Like a general function or process, it is also possible to transfer parameters to the constructor. : Type Tdate = Class Private Mouth, Day, Year: Integer; Public Function Leepyear: Boolean; Function GetText: String; Constructor Create (M, D, Y: Integer); End; Procedure Tdate.create (M, D, Y) : Integer; begin mouth: = m; day: = d; year: = y; END; call: aday: tdate; begin aday: = tdate.create (1, 1, 2000); if adayapyear thn showmessage 'Leap year:' INTOSTR (ADAY.YEAR)); aday.free; end; This, in the Create method, the initialization of the data is completed without having to call the setValue method. Next, we will involve another important, and it is also a very interesting question: the virtual and overloaded of the method.

Maybe you have a little dizzy ... or first look at a new example: Type Tmyclass = Class Procedure One; Virtual; End; Type TNewclass = Class (TMYCLASS) Procedure One; Override; End; Virtual; Begin ShowMessage (') Method of TMYCLASS!'); End; procedure tnewclass.one; override; begin inherited; showMessage ('Call TNewClass method!'); END; You can see that a new class TNEWClass is derived from TMYCLASS. . Both classes declare the same method one. Different, in TMYCLASS, there is a Virtual key in the one method, indicating that this method is a virtual method (Virtual Method). In TNEWCLASS, the one method has more override keywords, indicating that the method is overridden (OVERRIDE). Overloading technology enables many special functions. Let's take a closer analysis of their implementation. In the implementation section of the TMYCLASS.One method, call the showMessage process to pop up a dialog, indicating that the method has been called; there is no special place here. In the TNewclass.one method, there is a statement that has never been seen before: inherited; the Chinese meaning "inheritance". We don't temporarily talk about too complicated OOP concept, just know the function of this statement. Its function is to call the code in the virtual method in the base class. For example, if you use the following code: var Aobject: TNewclass; begin AObject: = TNewclass.create; AObject.one; abject.free; end; then the program will pop up two dialogs, the first time is one in the TMYCLASS class Method, the second time is the code in the TNewClass.one method. Overloading technology allows us to add data and methods that are not available in derived classes, but also inheritably inheriting the code in the original class in the base class, just simply adding inherited. If you don't join the inherited statement, the corresponding method of the base class will be overwritten by the new method. However, it must be noted that overloading can only be performed when the method of the base class is marked as Virtual, and the overloaded method must have the same parameter type as the virtual method. There is also a special example of the virtual method, that is, the abstract method: procedure one; override; abstract; behind the one method, not only the Override keyword, but also an Abstract keyword (meaning abstract). This method is called an abstract method (called a pure virtual function in C ). Classs containing abstract methods are called abstract classes. The uniqueness of the abstract method is that it only has a statement, and it does not have a part, if you try to call an abstract method of an object, you will get an exception. Only when this class is derived, it can be called after the method is implemented. (In C , an example of an abstract class cannot be created at all.) In this case, what is the use of this abstract method? This issue we will discuss the next "Polymorphism" section.

1.3 Polymorphism is relatively complicated. But don't worry, it's less content, and if the previous knowledge is relatively firm, the concept of polymorphism is water to the stream. Let's discuss the type of compatibility problem. Here is an example: type TAnimal = Class Procedure Voice; virtual; ... end; TDog = Class (TAnimal) Procedure Voice; Override; ... end; implementation Procedure TAnimal.Voice; virtual; Begin PlaySound ( 'Anim.wav ', 0, SND_ASYNC); End; Procedure Tdog.voice; Virtual; Begin Plays (' Dog.wav ', 0, SND_ASYNC); END; TDOG class inherits the Tanimal class and overloads the Voice method. Playsound is a WIN API function that can play the specified WAV file. (The definition of this function can be found in the mmsystem.pas file.) First see this code: var myanimal1, myanimal2: tanimal; begin myanimal1: = tanimal.create; myanimal2: = tdog.create; ... in implementation In the first line, a TANIMAL type object is established and gives it to Tanimal type variables myanimal1. This is very normal. But in the second line, a TDOG type object is established and gives it to the Tanimal type variable myanimal2. This looks surprising, but these codes are completely legal. It is well known that Pascal and Object Pascal are a type defined stringent language that you cannot assure a type value to different types of variables, such as imparting a full value to a Boolean variable, which will result in an error. However, this rule has an important exception to the OOP field, that is: allowing a sub-class value to a variable of a parent class. But it is not possible, and the value of a parent class cannot give a variable of a subclass type. If this principle is placed in the real world, it is easy to understand: "Dog" inherits from "Animals" because the dog is also an animal. Therefore, a "animal" type variable can be assigned to "Dog" type, because "dog" has "animal" all characteristics. However, in turn, "animal" does not have all characteristics of "dog", so the reverse assignment is not. So, what is the use of this compatible rule? Please pay attention to this code: var myanimal1, myanimal2: tanimal; begin myanimal1: = tanimal.create; myanimal2: = tdog.create; myanimal1.sound; myanimal2.sound; ... myanimal1 and myanimal2 are Tanimal variables, and All calling the Sound method. However, the result of the execution is completely different: the former executes the tanimal.voice code, and the latter executes the tdog.voice code! It is very simple because MyanImal1 is given the Tanimal type object, and MyanImal2 is given the TDOG type object.

That is, a Tanimal type variable, when it calls the Sound method, the code executed is uncertain: the code that may perform Tanimal.voice, or the code that is TDog.voice is depends on it. What kind of object is a like. Look at: myanimal1: = tanimal.create; myanimal1.sound; myanimal1.free; myanimal1: = tdog.create; myanimal1.sound; ... The same variable myanimal1, when calling the Sound method for the first time, Tanimal is executed The .voice code is executed in the second time is the code of TDog.voice. Myanimal1.sound This line code does not need to change, and the program can give this variable different objects depending on the case, so that it performs different code. This is the definition of polymorphism. This very important feature greatly increases the reuse of the code. As mentioned earlier, you only need to write a row of code simply, you can perform different features, because this virtual method is compatible with any part of Tanimal, and even those classes that have not been written are the same. The programmer does not need to understand the details of these derived classes. The use of polymorphisms is written out, and it also has a simple and maintenance. Now we can return to the problem of this article. The abstract method itself cannot do anything, must be overloaded and implemented in subclasses to complete meaningful work. However, the existence of abstract methods is equivalent to leaving an interface for the parent class. When the program gives a sub-class object to the variable of the parent class, the parent class can call this method, of course, it runs accordingly. The code of the method is overloaded in the subclass. If there is no such abstract method, the parent class's variable cannot call it because it cannot call a method that only in the subclass, and in the parent class! This is here about OOP. In these parameters, it is only some of the basic concepts of OOP, so that readers have certain system awareness of OOP, and also lay the foundation for the discussion below. More, more deeper things are waiting for yourself to discover. This article has repeatedly emphasized the importance of OOP. Here we need to emphasize: the level of the OOP, in a sense, you determine your ability to understand the world of Delphi. 2. After the database is relatively boring, we finally have to start contacting some actual applications that are more exciting. Database programming is one of the most powerful advantages of Delphi, I am afraid there are very few Delphi programmers have not come into contact with database programming. Delphi unique Data-Aware component makes many people who first do Delphi stunned. You don't need to write any code, you can make a quite exquisite database program within a few minutes, and you can see the results of the running period during the development period. This is not a thorough! However, Delphi's powerful database development capabilities are not limited to, but also manipulate DBFs or Access databases with several components. You see just a horn of the iceberg. Let us say it carefully. Although the database is huge, it can be divided into two: file databases and C / S databases. The following is discussed below. 2.1 File Database So-called File Database, as the name suggests, file-based, data is stored in a certain format, and reads the application by the application through the corresponding driver even directly by the application. That is, this database has a passive, as long as you know its file format, any program can be read directly, so that its security is quite bad.

At the same time, in the booming network application, the file-type database is more difficult to use the land: low efficiency, no support, no support, trigger, stored procedures, etc. These characteristics determine it is not suitable for large projects. The most familiar filed database may be the DBF (DBASE / FOXBASE / FOXPRO) database, in the DOS era, I believe many people have a memories of a manual backfoxbase command! It is characterized by that each Table or Index is a separate file, which is quite simple, performance is OK, the security is very poor, but the application is very broad (mainly the DOS era left, which unit does not use this What about the old antique procedures from Southam?). It can also occupy a place today. One of the main reasons is that it is because it is simple and wide, which makes it easier to access it. Even without third-party interfaces, it can directly perform byte level. Read. In addition, there is a famous Access database. This is one of the components in the MS Office. Unlike the DBF database, all files are integrated in one .mdb file, which avoids the trouble after the database changes. At the same time, it also provides password protection, and security is much better than the DBF database. In addition to the general text data, the Access database is also good at processing of multimedia data. When processing sound, image or even OLE-based objects, the DBF database looks like. With the step by step by the Microsoft Strategy, the Access database has also been developed. With excellent performance and the seamless combination with MS Office, it has already surpassed the DBASE series, which has become the most powerful file database. Paradox included in Delphi is also a file type database. It is Inprise's own products. Therefore, it is very good to match the series of development tools of Inprise. It supports password protection, supporting standard SQL, performance is not bad, but applications are not so extensive. Like the DBF database, each Table of its table is a separate file, so there is also the same management issue. The above can be read directly to the file type database, but there are very few people in actual programming. Because the simple database is actually quite complicated, step by step analysis, all database applications are implemented from the underlying, and if you have to write, you may die. So the developer of the database will be encapsulated by these access code, open to programmers, and programmers only need to call the corresponding interface. Take DBF as an example, use the DBASE / FOXBASE / FOXPRO series development tool, you can use its own syntax to develop applications. The specific operation of the DBF file is packaged. For the Access database, Microsoft announces a DAO (Database Access Object), consisting of a series of DLL files, encapsulated access to the .mdb file. Readers using VB may be more familiar with DAO, as long as the DAO object is embedded in VB, it can easily access the Access database. ODBC (Open Database Connection) is also a package, which is intended to provide a unified interface to developers. You can access any database supporting ODBC through this interface as long as the database provides the corresponding ODBC driver. From this point, ODBC is a more advanced package. At present, almost all mainstream databases can be supported by ODBC.

Open your Windows control panel, you can see the ODBC icon. Write a database program with the Delphi written by the Delphi to deal with BDE. BDE (BORLAND DASEBASE Engine, Borland Database Engine) is something similar to ODBC, Borland / Inprise is trying to use it to unify database interfaces. But later Inprise lost in the war of Microsoft (ODBC is Microsoft), it refused to abandon BDE, but bundled it in the Delphi / C Builder series development tool, the result is like these A accessory of the development tool. Developing database programs with BDE is quite easy. Many Delphi textbooks are always telling you to set an alias for a DBF or Paradox database in BDE, then put a TTable component on the form, then point DatabaseName points to the corresponding alias. ...... Then, the content of a table in this database is displayed in the corresponding Data-Aware component. But what do they work? Delphi is actually accessed by the database, in fact, many levels of connection. As shown below: Figure 1 DataAware Components-DataSource Parts -Dataset Components-BDE- Database As you can see that BDE is responsible for dealing with specific databases, while the DataSet component is connected to BDE, and the DataSource component is connected to the DataSet component, and finally connect to The Data-Aware component of the specific data is displayed. On the Delphi component panel, the components in the Data Access page are generally a DataSet component, such as TTABLE, TQuery, as long as they specify their DatabaseName properties, you can establish them with a database. The components in the Data Control page are generally a Data-Aware component, such as TDBGRID, TDBEDIT, TDBIMAGE. Their role looks similar to the general Delphi components, and the difference is that the DataSource component can be connected to the DataSet component, and the corresponding data can be automatically displayed. Establishing an app with Delphi's database components is so convenient, but if you go deep, you will find things not simple. You can try yourself to write code, access fields in the database, rather than editing by the user through the Data-Aware component. How to do this? The secret is the Field member. It can be said that the Field member is the basis of the Delphi database application. When a DataSet component is turned on, the corresponding data is read and stored in the fields attribute of the TTable or TQuery component. This property is defined as a Field array. By direct access arrays, you can use them, for example: table1.fields [0] .asinteger; this code accesses the first field of current record in Table1, the type of this field is Integer. You can also use them using the fieldByname attribute: table1.fieldbyname ('last name'). Asstring; this code accesses the field named Last Name in Table1, which is String. In fact, the Data-Aware component uses data by accessing the fields attribute of the DataSet component. After you understand this, you can also try to rewrite a conventional display component to make Data-Aware's nature.

In fact, most database experts using Delphi do not like to use the Data-Aware component because the Data-Aware component is far from conventional components. In addition to the Fields properties, the DataSet component has a number of special properties, methods, and events, enough to cope with all applications from small text databases to large network databases. This article is not intended to discuss them one by one. If the reader can use their use to rotate, it can be said that there will be no problem with the database programming. Please set your attention again to Figure 1. At the last ring of Figure 1, you can see that BDE is connected to a specific database. In fact, there are several levels in this ring. In theory, BDE can connect to any type of database. For some relatively simple databases, such as ASCII (plain text type database), DBASE, and Delphi's own Paradox, BDE can be accessed directly. In addition, it can also access specific databases through some corresponding drives, such as accessing the Access database via DAO. For databases that cannot be directly supported, BDE can also be connected to ODBC, access through ODBC, although this is relatively low. This nature determines that BDE is a fairly huge thing. With the Delphi program of BDE, you must have BDE to work, so you must release it with BDE. This often causes such a situation: only a few hundred k applications, after adding the entire BDE, the volume is nearly 10m! This is a fatal weakness for a file type database with a thin and short-term long. And because BDE is compatible with too many databases, it also has unstable problems, often in a headache. At the same time, it is a very troublesome thing to install the BDE driver and set the database, which makes BDE very popular in the Delphi programmer. In the Delphi Technology Forum on the Internet, you can often see a curse of BDE ... So, can any way bypass BDE? Some. Currently, at least three methods: (1) use third-party components. Inprise, I also realized the problem of BDE, although they refused to abandon BDE, but from Delphi3, they still provided a good choice for programmers: Creating custom DataSet components. Delphi's developers remove all the things about BDE from the TDataSet class, put into the new TBDedataSet class (the TBDedataset class is the subclass of the TDataSet class). The TDataSet class is re-constructed, and its core function is virtualized. Therefore, you only need to derive a new class from the TDataSet class, and overload some specified virtual methods (to access specific databases), you can get your own DataSet component. It is completely independent of BDE, but it can be used like Delphi's own DataSet components, for example, to access its fields attribute, and work together with Delphi's Data-Aware unit! There is a large number of third-party components, which can access certain specific databases. Here is a relatively common third-party components that access file-type databases or ODBC: Table 2 Name Supported database type DiamondaccesshalcyondBase / FoxProapollodBase / FoxPromodbc any ODBC database ODBC Express Any ODBC database

These controls are widely used. In China, in the author's knowledge, Tongzhi family wealth management software uses Diamond, and "chasing" (shared software that shows the address location of the specified IP) uses Halcyon. After using these third-party components, the software can finally "lightly load", no longer use for BDE headaches. (2) Use ADO. In Delphi5, Inprise finally provided a relatively thorough solution, that is, the ADO component. In principle, the ADO is not much different from the third party components described above, but it is an official development of Inprise; at the same time, it is not a specific database, but the ADO object provided by Microsoft. ADO (ActiveX Data Object, ActiveX Data Object) is a new standard proposed by Microsoft, from the theory, can support any type of database (even streaming data). Microsoft draws it to the new unified database interface, boasted many of its advantages. Inprise has always been a competitor of Microsoft, and the standard of Microsoft's standard (BDE is an example), but due to various reasons, Inprise finally admitted ADO. It is certainly a good solution to replace BDE with ADO to replace BDE, and use ADO in Delphi is also quite convenient. From the situation, ADO should be the direction of the future. However, ADO itself is also quite large. (3) Develop a complete database engine from the bottom floor. This is the most thorough way. Thoroughly abandon Delphi's database support, start from bytes, develop your own database. This approach has its benefits: First, do not consider compatibility issues, such as database files that don't have to consider the user is an Access 97 format or Access 2000 format; second, you can achieve the most sufficient optimization, because you don't need Through any universal interface, the disk file is performed directly, which is useful for some programs that are demanding performance requirements; third, to minimize redundant code, because this database is often a specific format, And only need to perform some specific operations, and the access code is of course more streamlined than the general database. But the negative problems of this method are also apparent, that is, huge workload. A simple database is also quite complicated, and a complete database engine is implemented from the bottom layer, often takes a few thousand lines of code, and patient and experience. Although it sounds very extreme, there is no shortage of people. The famous Foxmail is the use of custom database formats to store information about letters, address books. Another shared software "Electronic Book" also uses custom .SRM format. The ICompanion (network partner) developed by the author is also used to store network records using custom formats. It is limited to the space, which no longer analyzes the specific procedures. One thing to add is that the author used Diamond to develop Rich Explorer, which is a reader that is specifically used to browse the offline database (Access format) of the famous Daeng Forum. On the main page of the author, you can find all the source code of Rich Explorer. It fully demonstrates a program that uses a third-party component to access a specific database (not using the Data-Aware control), the code is relatively simple, suitable for beginner analysis, Senior readers may wish to be used as a reference. 2.2 C / S Database C / S (Client / Server, Client / Server) Database is the mainstream of the current database application.

Unlike the file type database, the C / S type database application consists of two parts: server and client. The server refers to the database management system (DBMS), which is used to describe, manage, and maintain the database, which is the core component of the database system, unified management and control of the database. The client sent the user's needs to the server and returns the data from the server to the user. The C / S type database is ideal for web applications, which can be accessed by multiple users, and give different users with different security privileges. The amount of data supported by the C / S type database is generally much larger than the file type database, also supports distributed databases (ie the database of the same database is located on multiple servers). At the same time, the C / S type database generally supports SQL language (so also known as SQL database). These features determine that the C / S type database is suitable for high-end applications. Common C / S-type databases include famous Oracle, Sybase, Informix, Microsoft Microsoft SQL Server, IEM DB2, and Interbase, which comes with Delphi, and so on. The C / S type database involves a lot of advanced features, which is one of the largest applications in the entire computer. This article does not intend to introduce in detail because of the discussion in this appendix. As the technology is constantly updated, the C / S structure has also begun to gradually be replaced by a multi-tiered database model. As mentioned above, the C / S type database program consists of two parts of the server and client, thus known as a two-tie-tiered model. The file type database program is called a single-tiered model. The single layer model is the most original database model. Later, the programmer transferred the database to a powerful central server, allowing it to provide services for clients with weaker features, so that the double-layer model appeared. Double-layer models are widely used in the fields of finance, electricity, communications, and greatly promote the development of network databases. However, the double-layer model has gradually exposed the insufficient side. In this case, a three-layer model appears: The data module portion in the application is separated, transferred to a separate server, becoming an independent layer. The three-layer and three models are collectively referred to as multi-layer models. `Brief, the three-layer model consists of three levels: client-application server-database server user request first issues through the client, the application server issues a specific data access command to the database server again. (Generally SQL), the data returned by the database server is returned to the client after reorganizing the application server. It can be seen that the three-layer model is an extension of a double model. At present, we don't have to understand all technical details of the three-story model, and its advantages of double-layer models, only the structure of this model can only be generally understood. The B / S model is undoubtedly one of the most popular multi-layer database models. Maybe you have heard of this noun, which is the abbreviation of the Brower / Server (Browser / Server). Brower refers to a browser like IE / Netscape, Server includes database servers and application servers. The user returns a corresponding HTML page to the browser after a series of complex operations between the application server-database server. Is it very familiar? Yes, in fact, this is the web database that everyone is familiar with the Internet, of course it can also be used for local area networks. It can actually be a most common multi-layer model. After reviewing the development of the database, we finally catch up with the most popular pace.

However, some people may feel it here. Because he heard the current Web database programming, it is Perl, ASP, PHP, Java's world. Do we have all faithful followed Delphi, in the face of contemporary web databases, it is facing the fate of elimination? No, not. In fact, Delphi provides a very good support for the development of Web databases, especially based on powerful database support and visualization, which has other languages ​​that are unparalleled. The following will focus on developing a web database with Delphi. The first thing you have to speak from the Web itself. Usually we browsed the web page, can generally be divided into two. One is a static page that is the HTML file in the text format. However, to respond to the different needs of the user, feedback to the user's different pages, you must use dynamic page technology. For example, according to the name input by the user, quickly find the corresponding data in the database and dynamically generate a page to return to the user. How to achieve dynamic page technology? The earliest way is CGI (CommON Gateway Interface, General Gateway Interface). This interface allows the browser to send and receive data, and input and output based on the application's command line. When the browser issues a request to the application, the web server automatically launches the program and passes the input and output data between the browser and the application. There are many languages ​​that implement the CGI, which is more popular in PERL. In addition, there is also a special WinCGI. The difference between Wincgi and ordinary CGI is that it replaces the command line parameters as an input and output through the INI file, which is mainly designed for Visual Basic because VB cannot access environment variables. Delphi provides good support for both CGIs, which can be written in a very complex CGI program. The second method is to use the API interface built into the web server. The DLL file written in this interface is loaded by the web server to its own memory space. When the server receives the corresponding page request, it will start a new thread to perform the corresponding code in the DLL. This program is very fast because there is no need to perform external EXE files. This API mainly has ISAPI (Internet Server API) and NSAPI (Netscape Server API), where the former has become an actual standard. Delphi also provides good support for both APIs. It is mentioned that Delphi's C / S version provides a general class frame to eliminate the difference between CGI, WinCGi, and ISAPI, so we can easily convert an application between these three. . There is also a scripting language built into the web server, which can be simply embedded in an HTML file, and performs a dynamic page through the interpretation of the web server. The famous ASP, PHP, JSP belong to this class. This looks nothing to do with Delphi, but in fact, Delphi can provide strong support for ASP! ASP's beginners may focus on its scripting language, in fact, ASP consists of three parts: scripts, components, and HTML. The light is to master the script and the original components of the ASP are far less, only self-developing components can realize truly complex, efficient applications. Delphi is ideal for developing such components. The famous domestic manufacturer is based on the successful example of Delphi ASP, and it also publishes all source code for reference. Let us build a program first.

This program is different from the past Delphi, requiring all forms and extra code, and finally only such a paragraph: Program cgidate; {$ appty console} // This line compiler instruction indicates that this is a console program, no You need a form, output Uses sysutils in the terminal window; Begin Writeln ('HTTP / 1.0 200 OK'); Writeln ('Content-Type: Text / HTML'); Writeln; Writeln (' ') Writeln (' Time </ Title>); Writeln (' </ head> <body> '); Writeln (' <h1> time at this site </ h1>); Writeln ('<hr > '); Writeln (' <h3>); Writeln ('"Today IS" DDD, MMMM D, YYYY,' '"<br> and the time is" HH: mm: SS AM / PM' , NOW); Writeln ('<h3>); Writeln (' <hr> '); Writeln (' </ body> </ html> '); END; After compiling, place the program under the web server In the subdirectory with Scripts permissions, use the browser to access it, you can get a page about the current time and date. Analyze this code. The format is simple, all uses WriteLn to generate standard output. The first two lines generate HTML descriptions, intermediate, and then the next code generates a complete HTML file. This file is returned to the browser and displayed. Unlike the static page, there is a line HTML text dynamically generated through the FormatDataTime function, so there will be different displays depending on the current time. This is the simplest CGI program. Although it is simple, it is already possible to see the basic working principle of the CGI program: a dynamic HTML page is generated by standard input and output. On this basis, access to the database can be easily implemented, and the corresponding HTML is generated. Here is an example: var: table1: ttable; begin showheader; // showheader process Generates the header of the HTML file, the code is similar to the above example Table1: = TTable.create (nil); try table1.databaseName: = 'dbdemos'; Table1.tablename: = 'Employee.db'; table1.indexName: = 'BYNAME'; TABLE1.Open; showTabindex; // Display Table Finally Table1.Close; table1.free; end; write1.free; end; write1.free; end; write1.free; end; write1.free; > </ html> '); END; this code dynamically establishes a Table object and connects it to the table employee.db in the DBDemos database (of course these must be set in BDE).</p> <p>The ShowTabindex process shows two columns in the table: procedure showtabindex; begin table1.fristex; writeln ('<ul>'); While Not Table1.eof Do Begin Writeln (Format ('<li> s% s%), [Table1.fieldByname ('firstname'). Asstring, Table1.fieldbyName ('lastname'). Asstring]); table1.next; end; writeln ('</ ul>'); END; showtabindex function traversed the entire table, And print all of the firstname and lastname fields. On this basis, complex dynamic pages can be generated, implementing various operations for the database. Of course, problems in practice are not just as simple, for example, read related Environment variables, to generate the corresponding URL, generate the corresponding URL, generate the corresponding HTTP knowledge, generate a page for the user commit request, you need to know the format of the HTML form ... However, the purpose of this article is not to explore technical details, but Focus on the basic concepts and principles, so they are no longer detailed, please readers yourself to learn. It has been said that in Delphi can easily convert between CGI, WinCGI, and ISAPI. These two The example generated is an Exe file, so CGI (or WinCGi, depending on the environment variable or INI file) program. If you want to change to the ISAPI mode, in addition to compiling into a DLL file, the input and output is also required to be modified. Implement three special functions: The getExtensionVersion TerminateExtension HTTPEXTENSIONPROC Web server calls these three functions, and the program can interact with the browser when loading the DLL, uninstalling the DLL, and requesting DLL. Specific implementation, this is not detailed here Through the above college studies, I believe that the reader has deeper Delphi's understanding. This article aims to help readers understand some relatively advanced concepts and principles, many places just introduce the most basic things, not to start. If they are in-depth Go down, there will be a lot of chapters. Therefore, after the reader is entitled, you need more your efforts. The following is some of the author recommended: book: "Delphi5 from getting started", Marco Cantu, electronics industry Out Side. In the Delphi world, Marco Cantu as a book authors can be said to be all known, Delphi is absolutely classic from entry to proficiency series. Although this book does not face high-end users, it fully discusses all aspects of Delphi programming, like components development, multi-thread, image processing, report printing, I / O, database, Internet applications, etc. The election of the initiator is increasing. "Delphi4 programming technology insider", Charlie Calvert, Machinery Press. The author is an extremely rich senior programmer, with deep-in-depth language, one of the complex problems in Delphi, and is suddenly open. Rich content and unique style make the readers of this book not only have technical gains, but also have fun. Many people vomiting blood recommended in Dongdong, master case must have. "Delphi3 Development Manual", Machinery Industry Press.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-5201.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="5201" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.044</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'DGqNMURFLSxsRHhVHPZ92AjxQw19QV_2FV94w53RDYrhwJTkCMXnqjlfDvprb7SFvrAeXrbNH7C2mj35KBqJdl_2Fw_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>