Adding a new index
There are three ways to add indexes to a client dataset To create a temporary index at runtime that sorts the records in the client dataset, you can use the IndexFieldNames property. Specify field names, separated by semicolons. Ordering of field names in the list determines their order in the index. This is the least powerful method of adding indexes. You can't specify a descending or case-insensitive index, and the resulting indexes do not support grouping. These indexes do not persist when...
Creating persistent fields
Persistent field components created with the Fields editor provide efficient, readable, and type-safe programmatic access to underlying data. Using persistent field components guarantees that each time your application runs, it always uses and displays the same columns, in the same order even if the physical structure of the underlying database has changed. Data-aware components and program code that rely on specific fields always work as expected. If a column on which a persistent field...
Defining new persistent fields
Besides making existing dataset fields into persistent fields, you can also create special persistent fields as additions to or replacements of the other persistent fields in a dataset. New persistent fields that you create are only for display purposes. The data they contain at runtime are not retained either because they already exist elsewhere in the database, or because they are temporary. The physical structure of the data underlying the dataset is not changed in any way. To create a new...
Adding actions to the dispatcher
Open the action editor from the Object Inspector by clicking the ellipsis on the Actions property of the dispatcher. Action items can be added to the dispatcher by clicking the Add button in the action editor. Add actions to the dispatcher to respond to different request methods or target URIs. You can set up your action items in a variety of ways. You can start with action items that preprocess requests, and end with a default action that checks whether the response is complete and either...
Disconnecting from a database server
There are two ways to disconnect a server using a connection component Set the Connected property to False. Call the Close method. Calling Close sets Connected to False. When Connected is set to False, the connection component generates a BeforeDisconnect event, where you can perform any cleanup before the connection closes. For example, you can use this event to cache information about all open datasets before they are closed. After the BeforeConnect event, the connection component closes all...
Creating multitiered applications
This chapter describes how to create a multi-tiered, client server database application. A multi-tiered client server application is partitioned into logical units, called tiers, which run in conjunction on separate machines. Multi-tiered applications share data and communicate with one another over a local-area network or even over the Internet. They provide many benefits, such as centralized business logic and thin client applications. In its simplest form, sometimes called the three-tiered...
Transaction timeout
The transaction timeout sets how long in seconds a transaction can remain active. The system automatically aborts transactions that are still alive after the timeout. By default, the timeout value is 60 seconds. You can disable transaction timeouts by specifying a value of 0, which is useful when debugging transactional objects. To set the timeout value on your computer, 1 In the MTS Explorer or COM Component Manager, select Computer, My Computer. By default, My Computer corresponds to the...
Marking and returning to records
In addition to moving from record to record in a dataset or moving from one record to another by a specific number of records , it is often also useful to mark a particular location in a dataset so that you can return to it quickly when desired. TDataSet introduces a bookmarking feature that consists of a Bookmark property and five bookmark methods. TDataSet implements virtual bookmark methods. While these methods ensure that any dataset object derived from TDataSet returns a value if a...
Using a client dataset to cache updates
By default, when you edit data in most datasets, every time you delete or post a record, the dataset generates a transaction, deletes or writes that record to the database server, and commits the transaction. If there is a problem writing changes to the database, your application is notified immediately the dataset raises an exception when you post the record. If your dataset uses a remote database server, this approach can degrade performance due to network traffic between your application and...
Reraising the exception
Sometimes when you handle an exception locally, you actually want to augment the handling in the enclosing block, rather than replacing it. Of course, when your local handler finishes its handling, it destroys the exception instance, so the enclosing block's handler never gets to act. You can, however, prevent the handler from destroying the exception, giving the enclosing handler a chance to respond. Example When an exception occurs, you might want to display a message to the user or record...
Using parameters at runtime
With some datasets, if the name of the stored procedure is not specified until runtime, no TParam objects are automatically created for parameters and they must be created programmatically. This can be done using the TParam.Create method or the TParams.AddParam method StoredProcName 'GET_EMP_PROJ' Params.Clear P1 TParam.Create Params, ptInput P2 TParam.Create Params, ptOutput try Params 0 .Name 'EMP_NO' Params 1 .Name 'PROJ_ID' ParamByname 'EMP_NO' .AsSmallInt 52 ExecProc Edit1.Text ParamByname...
Programming a calculated field
After you define a calculated field, you must write code to calculate its value. Otherwise, it always has a null value. Code for a calculated field is placed in the OnCalcFields event for its dataset. To program a value for a calculated field 1 Select the dataset component from the Object Inspector drop-down list. 2 Choose the Object Inspector Events page. 3 Double-click the OnCalcFields property to bring up or create a CalcFields procedure for the dataset component. 4 Write the code that sets...
Specifying a batch move mode
The Mode property specifies the operation a batch move component performs batAppend Append records to the destination table. batUpdate Update records in the destination table with matching records from the source table. Updating is based on the current index of the destination table. batAppendUpdate If a matching record exists in the destination table, update it. Otherwise, append records to the destination table. batCopy Create the destination table based on the structure of the source table....
Locking objects
Some objects have built-in locking that prevents the execution of other threads from using that object instance. For example, canvas objects TCanvas and descendants have a Lock method that prevents other threads from accessing the canvas until the Unlock method is called. The VCL and CLX also both include a thread-safe list object, TThreadList. Calling TThreadList.LockList returns the list object while also blocking other execution threads from using the list until the UnlockList method is...
Enabling Help in applications
Both the VCL and CLX support displaying Help from applications using an object-based mechanism that allows Help requests to be passed on to one of multiple external Help viewers. To support this, an application must include a class that implements the ICustomHelpViewer interface and, optionally, one of several interfaces descended from it , and registers itself with the global Help Manager. The VCL provides to all applications an instance of TWinHelpViewer, which implements all of these...
Radio buttons
Radio buttons present a set of mutually exclusive choices. You can create individual radio buttons using TRadioButton or use the radio group component TRadioGroup to arrange radio buttons into groups automatically. You can group radio buttons to let the user select one from a limited set of choices. See Grouping components on page 3-39 for more information. A selected radio button is displayed as a circle filled in the middle. When not selected, the radio button shows an empty circle. Assign...
Creating resource DLLs
Isolating resources simplifies the translation process. The next level of resource separation is the creation of a resource DLL. A resource DLL contains all the resources and only the resources for a program. Resource DLLs allow you to create a program that supports many translations simply by swapping the resource DLL. Use the Resource DLL wizard to create a resource DLL for your program. The Resource DLL wizard requires an open, saved, compiled project. It will create an RC file that contains...
Implementing unary operations
To allow the custom variant type to work with standard unary operators -, not , you must override the UnaryOp method. UnaryOp has two parameters the value of the operand and the operator. Implement this method to perform the operation and return the result using the same variable that contained the operand. For example, the following UnaryOp method comes from the TComplexVariantType defined in the VarCmplx unit procedure TComplexVariantType.UnaryOp var Right TVarData const Operator TVarOp begin...
What CLX does differently
All of the variant safe array code that was in System is in two new units The operating system dependent code is now isolated in VarUtils.pas, and it also contains generic versions of everything needed by Variants.pas. If you are converting a VCL application that included Windows calls to a CLX application, you need to replace these calls to calls into VarUtils.pas. If you want to use variants, you must include the Variants unit to your uses clause. VarIsEmpty does a simple test against...
Loading and saving custom variant values
By default, when the custom variant is assigned as the value of a published property, it is typecast to a string when that property is saved to a form file, and converted back from a string when the property is read from a form file. You can, however, provide your own mechanism for loading and saving custom variant values in a more natural representation. To do so, the TCustomVariantType descendant must implement the IVarStreamable interface from Classes.pas. IVarStreamable defines two methods,...
Customizing decision graphs
The decision graph component, TDecisionGraph, displays fields from the decision source TDecisionSource as a dynamic graph that changes when data dimensions are opened, closed, dragged and dropped, or rearranged with the decision pivot TDecisionPivot . You can change the type, colors, marker types for line graphs, and many other properties of decision graphs. 1 Right-click it and choose Edit Chart. The Chart Editing dialog box appears. 2 Use the Chart page of the Chart Editing dialog box to view...
Events with client connections
When a server socket accepts a client connection request, the following events occur An OnAccept event occurs, passing in the new TTcpClient object to the event handler. This is the first point when you can use the properties of TTcpClient to obtain information about the server endpoint of the connection to a client. If BlockMode is bmThreadBlocking an OnGetThread event occurs. If you want to provide your own customized descendant of TServerSocketThread, you can create one in an OnGetThread...
Performing complex conversions
You can also use the Convert function to perform more complex conversions between the ratio of two measurement types. Examples of when you might need to use this this are when converting miles per hour to meters per minute for calculating speed or when converting gallons per minute to liters per hour for calculating flow. For example, the following call converts miles per gallon to kilometers per liter nKPL Convert StrToFloat Edit1.Text , duMiles, vuGallons, duKilometers, vuLiter The units...
Controlling readwrite access to local tables
Like any table-type dataset, TTable lets you control read and write access by your application using the ReadOnly property. In addition, for Paradox, dBASE, and FoxPro tables, TTable can let you control read and write access to tables by other applications. The Exclusive property controls whether your application gains sole read write access to a Paradox, dBASE, or FoxPro table. To gain sole read write access for these table types, set the table component's Exclusive property to True before...
Drawing lines and polylines
A canvas can draw straight lines and polylines. A straight line is just a line of pixels connecting two points. A polyline is a series of straight lines, connected end-to-end. The canvas draws all lines using its pen. To draw a straight line on a canvas, use the LineTo method of the canvas. LineTo draws a line from the current pen position to the point you specify and makes the endpoint of the line the current position. The canvas draws the line using its pen. For example, the following method...
Creating an OnUpdateRecord event handler
When a BDE-enabled dataset applies its cached updates, it iterates through the changes recorded in its cache, attempting to apply them to the corresponding records in the base table. As the update for each changed, deleted, or newly inserted record is about to be applied, the dataset component's OnUpdateRecord event fires. Providing a handler for the OnUpdateRecord event allows you to perform actions just before the current record's update is actually applied. Such actions can include special...
Adding new records
A dataset must be in dsInsert mode before an application can add new records. In code, you can use the Insert or Append methods to put a dataset into dsInsert mode if the read-only CanModify property for the dataset is True. When a dataset transitions to dsInsert mode, it first receives a BeforeInsert event. After the transition to insert mode is successfully completed, the dataset receives first an OnNewRecord event hand then an AfterInsert event. You can use these events, for example, to...
To add new capabilities to a class
A common reason for creating new components is to add capabilities not found in existing components. When you do this, you derive the new component from either an existing component or an abstract base class, such as TComponent or TControl. Derive your new component from the class that contains the closest subset of the features you want. You can add capabilities to a class, but you cannot take them away so if an existing component class contains properties that you do not want to include in...
Editing records
A dataset must be in dsEdit mode before an application can modify records. In your code you can use the Edit method to put a dataset into dsEdit mode if the read-only CanModify property for the dataset is True. When a dataset transitions to dsEdit mode, it first receives a BeforeEdit event. After the transition to edit mode is successfully completed, the dataset receives an AfterEdit event. Typically, these events are used for updating the user interface to indicate the current state of the...
Porting your application
If you are porting an application that you want to run on both Windows and Linux, you need to modify your code or use IFDEFs to indicate sections of the code that apply specifically to Windows or Linux. Follow these general steps to port your VCL application to CLX 1 Open the project containing the application you want to change in Delphi. 2 Copy .dfm files to .xfm files of the same name for example, rename unitl.dfm to unitl.xfm . Rename or IFDEF the reference to the .dfm file in the unit file...
Animation control VCL only
The animation component is a window that silently displays an Audio Video Interleaved AVI clip. An AVI clip is a series of bitmap frames, like a movie. Although AVI clips can have sound, animation controls work only with silent AVI clips. The files you use must be either uncompressed AVI files or AVI clips compressed using run-length encoding RLE . Animation control cannot be used in cross-platform programming. Following are some of the properties of an animation component ResHandle is the...
Displaying ADT and array fields
Sometimes the fields of the grid's dataset do not represent simple values such as text, graphics, numerical values, and so on. Some database servers allow fields that are a composite of simpler data types, such as ADT fields or array fields. There are two ways a grid can display composite fields It can flatten out the field so that each of the simpler types that make up the field appears as a separate field in the dataset. When a composite field is flattened out, its constituents appear as...
Using Object Pascal or IDL syntax
The Text page of the Type Library editor displays your type information in one of two ways Using an extension of Object Pascal syntax. Note When working on a CORBA object, you use neither of these on the text page. Instead, you must use the CORBA IDL. You can select which language you want to use by changing the setting in the Environment Options dialog. Choose Tools Environment Options, and specify either Pascal or IDL as the Language on the Type Library page of the dialog. Note The choice of...
Specifying aggregates
To specify that you want to calculate summaries over the records in a client dataset, use the Aggregates property. Aggregates is a collection of aggregate specifications TAggregate . You can add aggregate specifications to your client dataset using the Collection Editor at design time, or using the Add method of Aggregates at runtime. If you want to create field components for the aggregates, create persistent fields for the aggregated values in the Fields Editor. Note When you create...
Using message parameters
Once inside a message-handling method, your component has access to all the parameters of the message structure. Because the parameter passed to the message handler is a var parameter, the handler can change the values of the parameters if necessary. The only parameter that changes frequently is the Result field for the message the value returned by the SendMessage call that sends the message. Note This information is applicable when writing VCL components only. Because the type of the Message...
Exception handling with external sources
HandleException provides default handling of exceptions for the application. Normally when developing cross-platform applications, you do not need to call TApplication.HandleException. However, you may need it when writing shared object files or callback functions. You can use TApplication.HandleException to block an exception from escaping from your code particularly when the code is being called from an external source that does not support exceptions. For example, if an exception passes...
Storing and loading unpublished properties
By default, only published properties are loaded and saved with a component. However, it is possible to load and save unpublished properties. This allows you to have persistent properties that do not appear in the Object Inspector. It also allows components to store and load property values that Delphi does not know how to read or write because the value of the property is too complex. For example, the TStrings object can't rely on Delphi's automatic behavior to store and load the strings it...
Deploying type libraries
By default, when you have a type library that was created as part of an ActiveX or Automation server project, the type library is automatically linked into the .DLL, .OCX, or EXE as a resource. You can, however, deploy your application with the type library as a separate .TLB, as Delphi maintains the type library, if you prefer. Historically, type libraries for Automation applications were stored as a separate file with the .TLB extension. Now, typical Automation applications compile the type...
Displaying and editing a subset of data using filters
An application is frequently interested in only a subset of records from a dataset. For example, you may be interested in retrieving or viewing only those records for companies based in California in your customer database, or you may want to find a record that contains a particular set of field values. In each case, you can use filters to restrict an application's access to a subset of all records in the dataset. With unidirectional datasets, you can only limit the records in the dataset by...
Finding a file
There are three routines used for finding a file FindFirst, FindNext, and FindClose. FindFirst searches for the first instance of a filename with a given set of attributes in a specified directory. FindNext returns the next entry matching the name and attributes specified in a previous call to FindFirst. FindClose releases memory allocated by FindFirst. You should always use FindClose to terminates a FindFirst FindNext sequence. If you want to know if a file exists, a FileExists function...
WideString
The WideChar type allows wide character strings to be represented as arrays of WideChars. Wide strings are strings composed of 16-bit Unicode characters. As with long strings, wide strings are dynamically allocated with a maximum length of two Gigabytes, but the practical limit is usually dependent on the amount of available memory. In Delphi, wide strings are not reference-counted. Every assignment of a wide string to a wide string var creates a copy of the string data. In Kylix, WideStrings...
The request method type
The MethodType property of an action item indicates what type of request messages it can process. The dispatcher compares the MethodType property of an action item to the MethodType of the request message. MethodType can take one of the following values Table 28.1 MethodType values Value Meaning mtGet The request is asking for the information associated with the target URI to be mtHead The request is asking for the header properties of a response, as if servicing an mtGet request, but omitting...
Responding to mousedown messages
A MouseDown method is a protected method for a control's OnMouseDown event. The control itself calls MouseDown in response to a Windows mouse-down message. When you override the inherited MouseDown method, you can include code that provides other responses in addition to calling the OnMouseDown event. To override MouseDown, add the MouseDown method to the TDBCalendar class TDBCalendar class TSampleCalendar protected procedure MouseDown Button TButton, Shift TShiftState, X Integer, Y Integer...
Using component properties and events in a data module
Placing components in a data module centralizes their behavior for your entire application. For example, you can use the properties of dataset components, such as TClientDataSet, to control the data available to the data source components that use those datasets. Setting the ReadOnly property to True for a dataset prevents users from editing the data they see in a data-aware visual control on a form. You can also invoke the Fields editor for a dataset, by double-clicking on ClientDataSetl, to...
Using packages in an application
1 Load or create a project in the IDE. 4 Select the Build with Runtime Packages check box, and enter one or more package names in the edit box underneath. Runtime packages associated with installed design-time packages are already listed in the edit box. 5 To add a package to an existing list, click the Add button and enter the name of the new package in the Add Runtime Package dialog. To browse from a list of available packages, click the Add button, then click the Browse button next to the...
Setting the response content
For some requests, the response to the request message is entirely contained in the header properties of the response. In most cases, however, action item assigns some content to the response message. This content may be static information stored in a file, or information that was dynamically produced by the action item or its content producer. You can set the content of the response message by using either the Content property or the ContentStream property. The Content property is a string....
Modifying data
You can use the following dataset methods to insert, update, and delete data if the read-only CanModify property is True. CanModify is True unless the dataset is unidirectional, the database underlying the dataset does not permit read and write privileges, or some other factor intervenes. Intervening factors include the ReadOnly property on some datasets or the RequestLive property on TQuery components. Table 18.7 Dataset methods for inserting, updating, and deleting data Method Description...
Events when establishing a connection
In addition to the BeforeConnect and AfterConnect events that are common to all database connection components, TADOConnection also generates an OnWillConnect and OnConnectComplete event when establishing a connection. These events occur after the BeforeConnect event. OnWillConnect occurs before the ADO provider establishes a connection. It lets you make last minute changes to the connection string, provide a user name and password if you are handling your own login support, force an...
Incremental fetching
By changing the PacketRecords property, you can specify that the client dataset fetches data in smaller chunks. PacketRecords specifies either how many records to fetch at a time, or the type of records to return. By default, PacketRecords is set to -1, which means that all available records are fetched at once, either when the client dataset is first opened, or when the application explicitly calls GetNextPacket. When PacketRecords is -1, then after the client dataset first fetches data, it...
Deploying an ActiveX control on the Web
Before the ActiveX controls that you create can be used by Web clients, they must be deployed on your Web server. Every time you make a change to the ActiveX control, you must recompile and redeploy it so that client applications can see the changes. Before you can deploy your ActiveX control, you must have a Web Server that will respond to client messages. To deploy your ActiveX control, use the following steps 1 Select Project I Web Deployment Options. 2 On the Project page, set the Target...
