The Role of Class Factories

When we register the GUID of a COM object in the Registry, we can use a specific API function to create the object, such as the CreateComObject API function CreateComObject (const ClassID TGUID) IUnknown This API function will look into the Registry, find the server registering the object with the given GUID, load it, and, if the server is a DLL, call the DLLGetClassObject method of the DLL. This is a function every in-process server must provide and export function DllGetClassObject (const...

Events in Delphi

When a user does something with a component, such as clicking it, the component generates an event. Other events are generated by the system, in response to a method call or a change to one of that component's properties (or even a different component's). For example, if you set the focus on a component, the component currently having the focus loses it, triggering the corresponding event. Technically, most Delphi events are triggered when a corresponding operating system message is received,...

Exception Classes

In exception-handling statements shown earlier, we caught the EDivByZero exception, which is defined by Delphi's RTL. Other such exceptions refer to run-time problems (such as a wrong dynamic cast), Windows resource problems (such as out-of-memory errors), or component errors (such as a wrong index). Programmers can also define their own exceptions you can create a new subclass of the default exception class or one of its subclasses type When you add a new element to an array that is already...

Multirecord Grid

So far we have seen that you can either use a grid to display records of a database table or build a form with specific data-aware controls for the various fields, accessing the records one by one. There is a third alternative use a multirecord object (a DBCtrlGrid), which allows you to place many data-aware controls in a small area of a form and automatically duplicate these controls for multiple records. Here is what we can do to build the Multi1 example. Create a new blank form, place a...

Text Based Data Aware Controls

There are multiple text-oriented components DBText displays the contents of a field that cannot be modified by the user. It is a data-aware Label graphical control. It can be very useful, but users might confuse this control with the plain labels that indicate the content of each field-based control. DBEdit lets the user edit a field (change the current value) using an Edit control. At times, you might want to disable editing and use a DBEdit as if it were a DBText, but highlighting the fact...

Socket Connections

How do you start communication through a socket The server program starts running first, but it simply waits for a request from a client. The client program requests a connection indicating the server it wishes to connect to. When the client sends the request, the server can accept the connection, starting a specific server-side socket, which connects to the client-side socket. To support this model, there are three different types of socket connections Client connections are initiated by the...

The Server in a Component

When creating a client program for our server or any other Automation server, we can use a better approach, namely, wrapping a Delphi component around the COM server. Actually, if you look at the final portion of the TlibdemoLib_TLB file, you can find the following declaration OLE Server Proxy class declaration TFirstServer class(TOleServer) private function GetServerProperties TFirstServerProperties function GetDefaultInterface IFirstServer protected procedure InitServerData override function...

The WARN Directive

The WARNINGS directive (and the corresponding compiler option) allows you to turn off all the warning messages. Most programmers like to keep the messages on and tend to work with programs that compile with no hints and warnings. With the advent of the three hint directives discussed in the last section, however, there are programs specifically aimed for a platform, which cannot compile without compatibility warnings. To overcome this situation, Delphi 6 introduces the WARN directive,...

Overriding and Redefining Methods

As we have just seen, to override a late-bound method in a descendant class, you need to use the override keyword. Note that this can take place only if the method was defined as virtual in the ancestor class. Otherwise, if it was a static method, there is no way to activate late binding, other than by changing the code of the ancestor class. The rules are simple A method defined as static remains static in every subclass, unless you hide it with a new virtual method having the same name. A...

Whats Next

Borland originally introduced its multitier technology in Delphi 3 and has kept extending it from version to version. In addition to further updates and the change of the MIDAS name to DataSnap, Delphi 6 sees the introduction of XML and SOAP support, introducing an alternate and extended architecture for multitier applications. We'll fully explore this topic in Chapter 23. For the moment, we'll continue with database programming, discussing data-aware controls and custom datasets. In the next...

Object Pooling

When multiple clients connect to your server at the same time, you have two options. The first is to create a remote data module object for each of them and let each request be processed in sequence (the default behavior for a COM server with the ciMultiInstance style). Alternatively, you can let the system create a different instance of the application for every client (ciSingleInstance). This requires more resources and more SQL server connections (and licenses), potentially overloading the...

Project and Library Names in Delphi

For a library, as for a standard application, you end up with a library name matching a Delphi project filename. Following a similar technique introduced in Kylix for compatibility with standard Linux naming conventions for shared object libraries (the Linux equivalent of Windows DLLs), Delphi 6 introduced special compiler directives you can use in libraries to determine their executable filename. Some of these directives make more sense in the Linux world than on Windows, but they've all been...

Active Form Internals

Before we continue with the example, let's look at the code generated by the ActiveForm Wizard. The key difference from a plain Delphi form is in the declaration of the new form class, which inherits from the TActiveForm class and implements a specific ActiveForm interface type TAXForml class(TActiveForm, IAXForml) As usual, the IAXForm interface is declared in the type library and in a corresponding Pascal file generated by Delphi. Here is a small excerpt of the IAXForml interface from the...

Managing Projects

Delphi's multitarget Project Manager (View Project Manager) works on a project group, which can have one or more projects under it. For example, a project group can include a DLL and an executable file, or multiple executable files. In Delphi 6, all open packages will show up as projects in the Project Manager view, even if they haven't been added to the project group. In Figure 1.9, you can see the Project Manager with the project group for the current chapter. As you can see, the Project...

Web Snap Data Module

As an example, I've built a new WebSnap application (called WSnapTable) with an Adapter-PageProducer as its main page to display a table in a grid and another AdapterPageProducer in a secondary page to show a form with a single record. I've also added to the application a WebSnap Data Module, as a container of the dataset components. The data module has a ClientDataSet wired to a dbExpress dataset through a provider and based on an InterBase connection, as shown here object ClientDataSetl...

Logging Errors

Most of the time, you don't know which operation is going to raise an exception, and you cannot (and should not) wrap each and every piece of code in a try except block. The general approach is to let Delphi handle all the exceptions and eventually pass them all to you, by handling the OnException event of the global Application object. This can be done rather easily with the ApplicationEvents component. In the ErrorLog example, I've added to the main form a copy of the ApplicationEvents...

Using Inter Base Express

The examples built in the last chapter either still used the BDE or were done with the new dbExpress database engine. Using this server-independent engine could allow you to switch the database server used by your application, although in practice this is often far from simple. You might decide that an application you are building will invariably use a given database server, possibly the internal server of the company you are working for. In this case, you can decide to skip any database engine...

Using the Font Combo

Now you can create a new Delphi program to test the Font combo box. Move to the Component Palette, select the new component, and add it to a new form. A traditional-looking combo box will appear. However, if you open the Items property editor, you'll see a list of the fonts installed on your computer. To build a simple example, I've added a Memo component to the form with some text inside it. By leaving the ChangeFormFont property on, you don't need to write any other code to the program, as...

The User Interface of a Wizard

Just as you can use a TabControl without pages, you can also take the opposite approach and use a PageControl without tabs. What I want to focus on now is the development of the user interface of a wizard. In a wizard, you are directing the user through a sequence of steps, one screen at a time, and at each step you typically want to offer the choice of proceeding to the next step or going back to correct input entered in a previous step. So instead of tabs that can be selected in any order,...

Type Safe Containers and Lists

Containers and lists have a problem They are not type-safe, as I've shown in both examples by adding a button object to a list of dates. To ensure that the data in a list is homogenous, you can check the type of the data you extract before you insert it, but as an extra safety measure you might also want to check the type of the data while extracting it. However, adding run-time type checking slows down a program and is risky a programmer might fail to check the type in some cases. To solve...

The Border Style

Another important property of a form is its BorderStyle. This property refers to a visual element of the form, but it has a much more profound influence on the behavior of the window, as you can see in Figure 9.2. Sample forms with the various border styles, created by the Borders example At design time, the form is always shown using the default value of the BorderStyle property, bsSizeable. This corresponds to a Windows style known as thick frame. When a main window has a thick frame around...

Simple HTTP Server

The situation with the development of an HTTP server is quite different. Building a server to deliver static pages based on HTML files is far from simple, although one of the Indy demos provides a rather good starting point for this. A custom HTTP server, instead, might be interesting when building a totally dynamic site, something I'll focus on in more detail in the next chapter. To show you how you can start the development of a custom HTTP server, I've built the HttpServ example. This...

Refreshing Data

You can obtain an updated version of the data, which other users might have modified, by calling the Refresh method of the ClientDataSet. However, this operation can be done only if there are no pending update operations in the cache, as calling Refresh raises an exception when the change log is not empty if cds.ChangeCount 0 then cds.Refresh If only some records have been changed, you can refresh the others by calling RefreshRecords. This method refreshes only the current record, but it should...

Event Driven Programming

The basic idea behind event-driven programming is that specific events determine the control flow of the application. A program spends most of its time waiting for these events and provides code to respond to them. For example, when a user clicks one of the mouse buttons, an event occurs. A message describing this event is sent to the window currently under the mouse cursor. The program code that responds to events for that window will receive the event, process it, and respond accordingly....

Figure

The second toolbar of the OleCont example (top) is replaced by the toolbar of the server (bottom). You can see an example of the resulting standard OLE dialog box in Figure 20.12. Obviously, this dialog box changes depending on the nature of the active OLE object in the container. The last feature of the OleCont program is support for files this is actually one of the simplest additions we can make, because the OLE container component already provides file support.

Scaling Forms

When you create a form with multiple components, you can select a fixed size border or let the user resize the form and automatically add scroll bars to reach the components falling outside the visible portion of the form, as we've just seen. This might also happen because a user of your application has a display driver with a much smaller number of pixels than yours. Instead of simply reducing the form size and scrolling the content, you might want to reduce the size of each of the components...

Grabbing HTTP Content

As an example of the use of the HTTP protocols, I've decided to write a very specific search application. The program simply hooks onto the Google Web site, searches for a keyword, and retrieves the first hundred sites found. Instead of showing the resulting HTML file, the program parses it to extract only the URLs of the related sites to a list box. The description of these sites is kept in a separate string list and is displayed as you click a list-box item. So the program demonstrates two...

The Units of the RTL

As I mentioned above, in Delphi 6 the RTL (run-time library) has a new structure and several new units. The reason for adding new units is that many new functions were added. In most cases, you'll find the existing functions in the units where they used to be, but the new functions will appear in specific units. For example, new functions related to dates are now in the DateUtils unit, but existing date functions have not been moved away from SysUtils in order to avoid incompatibilities with...

Direct XSL Transformations with the DOM

Using the XSLPageProducer can certainly be handy, but generating multiple pages based on the same data just to handle different possible XSL styles with WebSnap doesn't seem to be the best approach. I've rather built a plain CGI application, called CdsXstl, that can transform a ClientDataSet data packet into different types of HTML, depending on the name of the XSL file passed as parameter to it. The advantage is that I can not only modify but even add new XSL files to the system without having...

COM Events

Client applications that use traditional COM objects and Automation servers can call methods of those servers, but this is not an efficient way to check whether the server has updated data for the client. For this reason, it is possible for a client to define a COM object that implements a callback interface, pass this object to the server, and let the server call it. Traditional COM events (which use the IConnectionPoint interface) are simplified by Delphi for Automation objects, but are still...

An Overview of Isapinsapi

A completely different approach is the use of the Web server APIs, the popular ISAPI (Internet Server API, introduced by Microsoft) and the less common NSAPI (Netscape Server API). These APIs allow you to write a DLL that the server loads into its own address space and usually keeps in memory for some time. Once it loads the DLL, the server can execute individual requests via threads within the main process, instead of launching a new EXE for every request (as it must in CGI applications). When...

Abstract Methods

The abstract keyword is used to declare methods that will be defined only in subclasses of the current class. The abstract directive fully defines the method it is not a forward declaration. If you try to provide a definition for the method, the compiler will complain. In Object Pascal, you can create instances of classes that have abstract methods. However, when you try to do so, Delphi's 32-bit compiler issues the warning message Constructing instance of < class name> containing abstract...

Read Write Track Bar

The next step is to write a component that allows a user to modify the data in a database, not just browse it. The overall structure of this type of component isn't very different from the previous version, but there are a few extra elements. In particular, when the user starts interacting with the component, the code should put the dataset into edit mode and then notify the dataset that the data has changed. The dataset will then use an event handler of the FieldDataLink to ask for the updated...

Secrets of the Component Palette

The Component Palette is very simple to use, but there are a few things you might not know. There are four simple ways to place a component on a form After selecting a control in the palette, click within the form to set the position for the control, and press-and-drag the mouse to size it. After selecting any component, simply click within the form to place it with the default height and width. Double-click the icon in the palette to add a component of that type in the center of the form....

Using the Jet Engine

Now that you have some of the MDAC and ADO basics under your belt, we can take a moment out to look at the Jet engine. This engine is of great interest to some and of no interest to others. If you're interested in Access, Paradox, dBase, text, Excel, Lotus 1-2-3, or HTML, then this section is for you. If you have no interest in any of these formats, you can safely skip this section. The Jet database engine is usually associated with Microsoft Access databases, and this is, indeed, its forte....

What About Currency Conversions

Converting currencies is not exactly the same as converting measurement units, as currency rates change at very high speed. In theory, you can register a conversion rate with Delphi's conversion engine. From time to time, you check the new rate exchange, unregister the existing conversion, and register a new one. However, keeping up with the actual rate means changing the conversion so often that the operation might not make a lot of sense. Also, you'll have to triangulate conversions you have...

Excel

Excel is easily accessed using the Jet OLE DB Provider. Once again, we use the Extended Properties property and set it to Excel 8.0. Assume that we have an Excel spreadsheet called ABCCompany.xls that, in Excel, looks like Figure 16.4. File- Edit View Insert Format Tools Data Window Help File- Edit View Insert Format Tools Data Window Help Notice that the sheet is called Employees. Our mission is to open and read this file using Delphi. You can, of course, solve this problem by automating Excel...

Simple Delphi DLL

As a starting point in exploring the development of DLLs in Delphi, I'll show you a very simple library built in Delphi. The primary focus of this example will be to show the syntax you use to define a DLL in Delphi, but it will also illustrate a few considerations involved in passing string parameters. To start, select the File New command and choose the DLL option in the New page of the Object Repository. This creates a very simple source file that starts with the following definition library...

The Object Repository

Delphi has menu commands you can use to create a new form, a new application, a new data module, a new component, and so on. These commands are located in the File New menu and in other pull-down menus. What happens if you simply select File New Other Delphi opens the Object Repository, which is used to create new elements of any kind forms, applications, data modules, thread objects, libraries, components, automation objects, and more. The New dialog box (shown in Figure 1.11) has several...

Using Plain Forms

Generally, Delphi developers tend to create forms at design time, which implies deriving a new class from the base one, and build the content of the form visually. This is certainly a reasonable standard practice, but it is not compulsory to create a descendant of the TForm class to show a form, particularly if it is a simple one. Consider this case you have to show a rather long message (based on a string) to a user, and you don't want to use the simple predefined message box, as it will show...

Importing and Exporting

The Jet engine is particularly adept at importing and exporting data. The process of exporting data is the same for each export format and consists of executing a SELECT statement with a special syntax. Let's start with an example of exporting data from the Northwind Access database to a Paradox table. You will need an active TADOConnection, called ADO-Connectionl in our example, that uses the Jet 4.0 OLE DB Provider to open the North-wind.mdb Access database. The following code exports the...

The Definition of the Classes

The starting point, as usual, is the declaration of the two classes discussed in this section, the generic custom dataset I've written and the specific component storing data in a stream. These declaration of these classes is available in Listing 18.2. Besides virtual methods, the classes contain a series of protected fields used to manage the buffers, track the current position and record count, and handle many other features. You should also notice another record declaration at the beginning,...

Section II Movement and Bookmark Management

As mentioned earlier, one of the things every dataset must implement is bookmark management,, which is necessary for navigating through the dataset. Logically, a bookmark is a reference to a specific record of the dataset, something that uniquely identifies the record so that a dataset can access it and compare it to other records. Technically, bookmarks are pointers. You can implement them as pointers to specific data structures that store record information, or you can implement them as...

Using Field Objects

Before we look at an example, let's go over the use of the TField class. The importance of this component should not be underestimated. Although it is often used behind the scenes, its role in database applications is fundamental. As I already mentioned, even if you do not define specific objects of this kind, you can always access the fields of a table or a query using their Fields array property, the FieldValues indexed property, or the FieldByName method. Both the Fields property and the...

Mail In and

To showcase the development of simple e-mail management programs, I could build an example of how you can send and receive mail. The Indy components, though, include a rather complete set of examples, and I don't see any reason to duplicate those, as using the mail protocols means placing a message component (IdMessage) in your application, filling it with data, and then using the IdSMTP component to send the mail message. To retrieve a mail message from your mailbox, use the IdPop3 component,...

The Tool Bar Control

In early versions of Delphi, toolbars had to be created using panels and speed buttons. Starting with version 3, Delphi introduced a specific ToolBar component, which encapsulates the corresponding Win32 common control or the corresponding Qt widget in VisualCLX. This component provides a toolbar, with its own buttons, and it has many advanced capabilities. To use this component, you place it on a form and then use the component editor (the shortcut menu activated by a right mouse button click)...

Hierarchy of Field Classes

There are several field class types in VCL. Delphi automatically uses one of them depending on the data definition in the database, when you open a table at run time or when you use the Fields editor at design time. Table 13.1 shows the complete list of subclasses of the TField class. TABLE 13.1 The Subclasses of TField TDateField TDateTimeField TFloatField TFMTBCDField TGraphicField TBlobField TGuidField TStringField An ADT (Abstract Data Type) field, corresponding to an object field in an...

The Client DataSet Component

Finally, there is a component derived from TDataSet that has a peculiar behavior and can be combined with other data-access components. The ClientDataSet component, in fact, is a dataset accessing data kept in memory. The in-memory data can be totally temporary (lost as you exit the program), saved to a local file as a snapshot, and imported by another dataset using a Provider component. This last situation is certainly the most common You can hook a ClientDataSet to any other local dataset, or...

Ni ti a i zati on

Now that we have an interface we can expose to the public, we have to provide an implementation for it, again by means of the standard Pascal code (and with the help of the predefined TInvokab1eC1ass class type TConvert c1ass (TInvokab1eC1ass, IConvert) protected function ConvertCurrency (Source, Dest string Amount Doub1e) Doub1e stdca11 function ToEuro (Source string Amount Doub1e) Doub1e stdca11 function FromEuro (Dest string Amount Doub1e) Doub1e stdca11 function TypesList string stdca11 end...

Building an Excel Table

In the case of Excel, I've used a slightly different approach and worked with the application object. The code creates a new Excel spreadsheet, fills it with a database table, and formats the result. It uses an Excel internal object, Range, which is not to be confused with a similar type available in Word (the reason this type is prefixed with the name of the unit defining the Excel type library). Here is the complete code procedure TFormOff.BtnExcelClick(Sender TObject) var RangeE...

Text Files

One of the very useful IISAM drivers that comes with the Jet engine is the Text IISAM. This driver allows you to read and update text files of almost any structured format. We will start with a simple text file to get up and running and then cover the variations later. Assume we have a simple text file called NightShift.TXT that contains the following text ,HomeTown .Cincinnati ,London .Milan Add a TADOTable to a form, set its ConnectionString to use the Jet 4.0 OLE DB Provider, and set...

The Files Produced by the System

Delphi produces various files for each project, and you should know what they are and how they are named. Basically, two elements have an impact on how files are named the names you give to a project and its units, and the predefined file extensions used by Delphi. Table 1.1 lists the extensions of the files you'll find in the directory where a Delphi project resides. The table also shows when or under what circumstances these files are created and their importance for future compilations....

Data Link Files

So a TADOConnection allows us to centralize the definition of a connection string within a form or data module. However, even though this is a worthwhile step forward from scattering the same connection string throughout all ADO datasets, it still suffers from a fundamental flaw If you use a database engine that defines the database in terms of a filename, then the path to the database file s is hard-coded in the EXE. This makes for a very fragile application. The BDE uses aliases to overcome...

Form Constraints

When you choose a resizable border for a form, users can generally resize the form as they like and also maximize it to full screen. Windows informs you that the form's size has changed with the wm_Size message, which generates the OnResize event. OnResize takes place after the size of the form has already been changed. Modifying the size again in this event if the user has reduced or enlarged the form too much would be silly. A preventive approach is better suited to this problem. Delphi...

Moving Control Grid Panels

To improve the last example, we might resize the grid using the FormResize method. We could simply write the following code in the Multi2 example procedure TForm1.FormResize Sender TObject begin DBCtrlGrid1.Height ClientHeight - Panel1.Height DBCtrlGrid1.Width ClientWidth end This works, but it is not what I want. I'd like to increase the number of panels, not enlarge them. To accomplish this, we can define a minimum height for the panels and compute how many panels can fit in the available...

Master Detail Structures

Often you need to relate tables, which have a one-to-many relationship. This means that for a single record of the master table, there are many detailed records in a secondary table. A classic example is that of an invoice and the items of the invoice another is a list of customers and the orders each customer has made. This is very common situation in database programming, and Delphi provides explicit support for it with the master detail structure. We'll see this structure for BDE Table and...

What Is Dynamic Linking

First of all, you need to understand the difference between static and dynamic linking of functions or procedures. When a subroutine is not directly available in a source file, the compiler adds the subroutine to an internal table, which includes all external symbols. Of course, the compiler must have seen the declaration of the subroutine and know about its parameters and type, or it will issue an error. After compilation of a normal static subroutine, the linker fetches the subroutine's...

Persistent Recordsets

One of the very useful features that contributes to the briefcase model is persistent recordsets. These allow you to save the contents of any recordset to a local file, which can be loaded later. Apart from aiding with the briefcase model, this feature allows developers to create true single-tier applications. It means that you can deploy a database application without having to deploy a database. This makes for a very small footprint on your client's machine. You can persist your datasets...

XSLT with Web Snap

Within the code of a program, you can execute the TransformNode method of a DOM node, passing to it another DOM hosting the XSL document. Instead of using this low-level approach, however, we can let WebSnap help us to create an XSL-based example. In fact, you can create a new WebSnap application I've built a CGI program called XslCust in this case and choose an XSLPageProducer component for its main page, to let Delphi help you start with the application code. Actually, Delphi also includes a...

Configuring a Local Network IP Addresses

If you have a local network available, you'll be able to test the following programs on it otherwise, you can simply use the same computer as client and server. In this case, as I've Foundations of Socket Programming 913 done in the examples, use the address 127.0.0.1 or localhost , which is invariably the address of the current computer. If your network is complex, ask your network administrator to set up proper IP addresses for you. If you want to set up a simple network with a couple of...

Complex Graphical Component

The graphical component I want to build is an arrow component. You can use such a component to indicate a flow of information, or an action, for example. This component is quite complex, so I'll show you the various steps instead of looking directly at the complete source code. The component I've added to the MdPack package on the CD is only the final version of this process, which will demonstrate several important concepts The definition of new enumerated properties, based on custom...

The Form Style

The FormStyle property allows you to choose between a normal form fsNormal and the windows that make up a Multiple Document Interface MDI application. In this case, you'll use the fsMDIForm style for the MDI parent window that is, the frame window of the MDI application and the fsMDIChild style for the MDI child window. To know more about the development of an MDI application, look at Chapter 10. A fourth option is the fsStayOnTop style, which determines whether the form has to always remain on...

An Overview of CGI

CGI is a standard protocol for communication between the client browser and the Web server. It's not a particularly efficient protocol, but it is widely used and is not platform specific. This protocol allows the browser both to ask for and to send data, and it is based on the standard command-line input and output of an application usually a console application . When the server detects a page request for the CGI application, it launches the application, passes command-line data from the page...

The First Thin Client

Now that we have a working server, we can build a client that will connect to it. We'll again start with a standard Delphi application and add a DCOMConnection component to it or the proper component for the specific type of connection you want to test . This component defines a ComputerName property that you'll use to specify the computer that hosts the application server. If you want to test the client and application server from the same computer, you can leave this blank. Once you've...

Late Binding and Polymorphism

Pascal functions and procedures are usually based on static or early binding. This means that a method call is resolved by the compiler and linker, which replace the request with a call to the specific memory location where the function or procedure resides. This is known as the address of the function. OOP languages allow the use of another form of binding, known as dynamic or late binding. In this case, the actual address of the method to be called is determined at run time based on the type...

List Based Data Aware Controls

For letting a user choose a value in a predefined list which reduces input errors , you can use many different components. DBListBox, DBComboBox, and DBRadioGroup are similar, providing a list of strings in the Items property, but they do have some differences The DBListBox component allows selection of predefined items closed selection , but not text input, and can be used to list many elements. Generally it's best to show only about six or seven items, to avoid using up too much space on the...

Mapping XML with Transformations

There is one more technique you can use in Delphi 6 to handle at least some XML documents. You can create a transformation to translate the XML of a generic document into the format used natively by the ClientDataSet component when saving data to a MyBase XML file. In the reverse direction, another transformation can turn a dataset available within a ClientDataSet through a DataSetProvider component into a XML file of a required format or schema . Delphi 6 includes a wizard to generate such...

Data in a Grid

The DBGrid is a grid capable of displaying a whole table at once. It allows scrolling and navigation, and you can edit the grid's contents. It is an extension of the other Delphi grid controls. You can customize the DBGrid by setting the various flags of its Options property and modifying its Columns collection. The grid allows a user to navigate the data, using the scrollbars, and perform all the mayor actions. A user can edit the data directly, insert a new record in a given position by...

Component Packages

Components are added to component packages. Each component package is basically a DLL a dynamic link library with a BPL extension which stands for Borland Package Library . Packages come in two flavors design-time packages used by the Delphi IDE and run-time packages optionally used by applications. The design-only or run-only package option determines the package's type. When you attempt to install a package, the IDE checks whether it has the design-only or run-only flags, and decides whether...

Master Detail in Web Snap

The DataSetAdapter component has specific support for master detail relationships between datasets. After you've created the relationship among the datasets, as usual, define an adapter for each dataset and then connect the MasterAdapter property of the adapter of the detail dataset. Setting up the master detail relationship between the adapters makes them work in a more seamless way. For example, when you change the work mode of the master, or enter new records, the detail automatically enters...

Monitoring the Connection

Another feature, which I've added only to the DbxSingle example, is the monitoring capability offered by the SQLMonitor component. In the example, the component is activated as the program starts. Every time there is a tracing string available, the component fires the OnTrace event to let you choose whether to include the string in the log. If the LogTrace parameter of this event is True the default value , the component logs the message in the TraceList string list and fires the OnLogTrace...

Assigning Objects

If a variable holding an object only contains a reference to the object in memory, what happens if you copy the value of that variable Suppose we write the BtnTodayClick method of the ViewDate example in the following way procedure TDateForm.BtnTodayClick Sender TObject var LabelDate.Caption TheDay.GetText end This code copies the memory address of the NewDay object to the TheDay variable as shown in Figure 2.6 it doesn't copy the data of an object into the other. In this particular...

Microsoft Data Access Components MDAC

ADO is part of a bigger picture called Microsoft Data Access Components MDAC . MDAC is an umbrella for Microsoft's database technologies and includes ADO, OLE DB, ODBC, and RDS Remote Data Services . Often you will hear people use the terms MDAC and ADO interchangeably but incorrectly because their version numbers and releases are now aligned. As ADO is only distributed as part of MDAC, we talk in terms of MDAC releases. The major releases of MDAC have been versions 1.5, 2.0, 2.1, 2.5, and 2.6....

The XMLBroker Component

Internet Express uses multiple technologies to accomplish this. The DataSnap data packets are converted into the XML format, to let the program embed this data right into the HTML page for Web client-side manipulation. Actually, the Delta data packet is also represented in XML. These operations are performed by the XMLBroker component, which can handle XML and provide data to the new JavaScript components. Like the ClientDataSet, the XMLBroker has A MaxRecords property indicating the number of...

Registering Property Categories

We've added to this component some custom properties and a new event. If you arrange the properties in the Object Inspector by category a feature available since Delphi 5 , all the new elements will show up in the generic Miscellaneous category. Of course, this is far from ideal, but we can easily register the new properties in one of the available categories. We can register a property or an event in a category by calling one of the four overloaded versions of the RegisterPropertylnCategory...

Live Queries and Cached Updates

When working with local data, it is very common to use grids and other visual controls, edit the data, and send it back to the database. We've already seen that using a DBGrid might cause problems when working with an RDBMS, as moving on the grid might send numerous data requests to the server, creating a huge amount of network traffic. When you use the Query component to connect to some data, you cannot edit the data unless its RequestLive property is set to True. If you are working with local...

Unusual Techniques Alpha Blending Color Key and the Animate API

One of the few new features of Delphi 6 related to forms is support for some new Windows APIs regarding the way forms are displayed not available under Qt CLX . For a form, alpha blending allows you to merge the content of a form with what's behind it on the screen, something you'll rarely need, at least in a business application. The technique is certainly more interesting when applied to bitmap with the new AlphaBlend and AlphaDIBBlend API functions than to a form itself. In any case, by...

The Fields of a Dataset

I mentioned earlier that a dataset has only one record that is the current, or active, one. The record is stored in a buffer, and you can operate on it with some generic methods, but to access the data of the record you need to use the field objects of the dataset. This explains why field components technically instances of class derived from the TField class play a fundamental role in every Delphi database application. Data-aware controls are directly connected to these field objects, which...

Section III Record Buffers and Field Management

Now that we've covered all the support methods, we can examine the core of a custom dataset. Besides opening and creating records and moving around between them, the component really needs to move the data from the stream the persistent file to the record buffers, and from the record buffers to the TField objects that are connected to the data-aware controls. The management of record buffers is quite complex, because each dataset also needs to allocate, empty, and free the memory it requires...

Dragging and Drawing with the Mouse

To demonstrate a few of the mouse techniques discussed so far, I've built a simple example based on a form without any component and called MouseOne in the VCL version and QMouseOne in the CLX version. The first feature of this program is that it displays in the Caption of the form the current position of the mouse procedure TMouseForm.FormMouseMove Sender TObject Shift TShiftState display the position of the mouse in the caption Caption Format 'Mouse in x d, y d', X, Y You can use this simple...

The Packets and the Cache

The ClientDataSet component reads data in packets made of the number of records indicated by the PacketRecords property. The default value of this property is -1, which means that the provider will pull all the records at once this is reasonable only for a small dataset . Alternatively, you can set this value to zero to ask the server for only the field descriptors and no actual data or use any positive value to specify an actual number. If you retrieve only a partial dataset, as you browse...

Handling Database Errors

Another important element of database programming is handling database errors in custom ways. Of course, you can let Delphi show an exception message each time a database error occurs, but you might want to try to correct the errors or simply show more details. There are basically three approaches you can use to handle database-related errors You can wrap a try except block around risky database operations, such as a call to the Open method of a Query or to the Post method of a dataset. This is...

Looking at Source Code Files

I've just listed some files related to the development of a Delphi application, but I want to spend a little time covering their actual format. The fundamental Delphi files are Pascal source code files, which are plain ASCII text files. The bold, italic, and colored text you see in the editor depends on syntax highlighting, but it isn't saved with the file. It is worth noting that there is one single file for the whole code of the form, not just small code fragments. In the listings in this...

Overriding Message Handlers The Numeric Edit

To customize an edit box component to restrict the input it will accept, all you need to do is handle the wm_Char Windows messages that occur when the user presses any but a few specific keys namely, the numeric characters . One way to respond to a message for a given window whether it's a form or a component is to create a new message-response method that you declare using the message keyword. Delphi's message-handling system makes sure that your message-response method has a chance to The...

The ToDo List

Another feature added in Delphi 5 was the to-do list. This is a list of tasks you still have to do to complete a project, a collection of notes for the programmer or programmers, as this tool can be very handy in a team . While the idea is not new, the key concept of the to-do list in Delphi is that it works as a two-way tool. In fact, you can add or modify to-do items by adding special TODO comments to the source code of any file of a project you'll then see the corresponding entries in the...

Protected Fields and Encapsulation

The code of the GetText method of the TNewDate class compiles only if it is written in the same unit as the TDate class. In fact, it accesses the fDate private field of the ancestor class. If we want to place the descendant class in a new unit, we must either declare the fDate field as protected or add a protected access method in the ancestor class to read the value of the private field. Many developers believe that the first solution is always the best, because declaring most of the fields as...

The Structure of CLX

This is the traditional subdivision of VCL, which is very common for Delphi programmers. Even with the introduction of CLX and some new naming schemes, the traditional names will probably survive and merge into Delphi programmers' jargon. Borland now refers to different portions of the CLX library using one terminology under Linux and a slightly different and less clear naming structure in Delphi. This is the subdivision of the Linux-compatible library BaseCLX forms the core of the class...

Additional and External Delphi Tools

Besides the IDE, when you install Delphi you get other, external tools. Some of them, such as the Database Desktop, the Package Collection Editor PCE.exe , and the Image Editor ImagEdit.exe , are available from Tools menu of the IDE. In addition, the Enterprise edition has a link to the SQL Monitor SqlMon.exe . Other tools that are not directly accessible from the IDE include many command-line tools you can find in the bin directory of Delphi. For example, there is a command-line Delphi...

Section I Initialization Opening and Closing

The first methods I'll examine are responsible for initializing the dataset, and for opening and closing the file stream we'll use to store the data. In addition to initializing the component's internal data, these methods are responsible for initializing and connecting the proper TFields objects to the dataset component. To make this work, all we need to do is to initialize the FieldsDef property with the definitions of the fields for our dataset, then call a few standard methods to generate...

Ole Db Providers

OLE DB providers enable access to a source of data. They are ADO's equivalent to the BDE's drivers. However, although the BDE's Driver SDK has been available for many years, there are no third-party BDE drivers. This is not the case for OLE DB providers. MDAC includes many providers that I'll discuss, but many more are available from Microsoft and, more prolifically, the third-party market. It is no longer possible to reliably list all available OLE DB providers, because the list is so large...

Using Sessions

To underline the importance of this type of support, I've built a WebSnap application with a single page showing both the total number of hits and the total number of hits for each session. The program has a SessionService component with default values for its MaxSessions and DefaultTimeout properties. For every new request, the program increases both an nHits private field of the page module and the SessionHits value of the current session procedure TObject const PageName String var Handled...

Inter Base Express IBX

Delphi includes components for native access to Borland's own open-source and free InterBase server. Unlike BDE, ADO, and dbExpress, this is not a server-independent database engine, but a technology for accessing a specific database server. If you plan using only InterBase as your back-end RDBMS, using a specific set of components can give you more control of the server, provide the best performance, and allow you also to configure and maintain the server from within a custom client...

The Status of a Dataset

When you operate on a dataset in Delphi, you can work in different states, indicated by a specific State property, which can assume several different values dsBrowse indicates that the dataset is in normal browse mode, used to look at the data and scan the records. dsEdit indicates that the dataset is in edit mode. A dataset enters this state when the program calls the Edit method or the DataSource has the AutoEdit property set to True, and the user starts editing a data-aware control, such as...

Mdac Ole Db Providers

When you install MDAC, you automatically install the OLE DB providers shown in Table 16.1 TABLE 16.1 OLE DB Providers Included with MDAC TABLE 16.1 OLE DB Providers Included with MDAC Example of an OLE DB provider for CSV files For creating your own providers for simple text data If you do not specify which OLE DB provider you are using, OLE DB defaults to the ODBC OLE DB Provider, which is used for backward compatibility with ODBC. As you learn more about ADO, you will discover the limitations...

From Primary Keys to OIDs

In a relational database, records are not identified by a physical position as in Paradox and other local databases but only by the data within the record itself. Typically, you don't need the data of all of the fields to identify a record, but only a subset of the data, forming the so-called primary key. If the fields that are part of the primary key must identify an individual record, their value must be different for each possible record of the table. Technically, many database servers add...

Form Creation Events

Regardless of the manual or automatic creation of forms, when a form is created, there are many events you can intercept. Form-creation events are fired in the following order 1. OnCreate indicates that the form is being created. 2. OnShow indicates that the form is being displayed. Besides main forms, this event happens after you set the Visible property of the form to True or call the Show or ShowModal methods. This event is fired again if the form is hidden and then displayed again. 3....

The Connection Protocol

DataSnap defines only the higher-level architecture and can use different technologies for moving the data from the middle tier to the client side. DataSnap supports most of the leading standards, including the following Distributed COM DCOM and Stateless COM MTS or COM DCOM is directly available in Windows NT 2000 and 98 Me, and it requires no additional run-time applications on the server. You still have to install it on Windows 95 machines. DCOM is basically an extension of COM technology...

Using Lookup Controls

Dblookupcombobox

If the list of values is extracted from another dataset, then instead of the DBListBox and DBComboBox controls you should use the specific DBLookupListBox or DBLookupCombo-Box components. These components are used every time you want to select for a field a record of another dataset. For example, if you build a standard form for taking orders, the orders dataset will generally have a field hosting a number indicating the customer who made the order. Working directly with the customer number is...

The Rich Bar Example

As an example of the use of a toolbar, I've built the RichBar application, which has a RichEdit component you can operate by using the toolbar. The program has buttons for loading and saving files, for copy and paste operations, and to change some of the attributes of the current font. I don't want to cover the details of the features of the RichEdit control, which are many, nor discuss the details of this application, which has quite a lot of code. All I want to do is to focus on features...

Building a Multipurpose Web Module

To demonstrate how easily you can build a feature-rich server-side application using Delphi's support, I've created the BrokDemo example. This example can be compiled as a CGI or an ISAPI application, simply by choosing the proper project file. The WebModule is shared by the two projects, without any difference in the source code, a practical proof that, using the WebBroker framework, you can move from ISAPI to CGI, from Apache to the Web App Debugger although this last step requires a little...