This chapter provides an overview of how to use Delphi to create applications, libraries, and components.
The main use of Delphi is designing and building Windows applications. There are three basic kinds of Windows application:
When you compile a project, an executable (.EXE) file is created. The executable usually provides the basic functionality of your program, and simple programs often consist of only an EXE. You can extend the application by calling DLLs, packages, and other support files from the executable.
Windows offers two application UI models:
In addition to the implementation model of your applications, the design-time behavior of your project and the runtime behavior of your application can be manipulated by setting project options in the IDE.
Any form can be implemented as a multiple document interface (MDI) or single document interface (SDI) form. In an MDI application, more than one document or child window can be opened within a single parent window. This is common in applications such as spreadsheets or word processors. An SDI application, in contrast, normally contains a single document view. To make your form an SDI application, set the FormStyle property of your Form object to fsNormal.
For more information on developing the UI for an application, see "Developing the application user interface."
To create a new SDI application,
By default, the FormStyle property of your Form object is set to fsNormal, so Delphi assumes that all new applications are SDI applications.
To create a new MDI application,
MDI applications require more planning and are somewhat more complex to design than SDI applications. MDI applications spawn child windows that reside within the client window; the main form contains child forms. Set the FormStyle property of the TForm object to specify whether a form is a child (fsMDIForm) or main form (fsMDIChild). It is a good idea to define a base class for your child forms and derive each child form from this class, to avoid having to reset the child form's properties.
Use Project|Project Options to specify various options for your project. For more information, see the online Help.
To change the default options that apply to all future projects, set the options in the Project Options dialog box and check the Default box at the bottom right of the window. All new projects will now have the current options selected by default.
Programming templates are commonly used "skeleton" structures that you can add to your source code and then fill in. For example, if you want to use a for loop in your code, you could insert the following template:
for := to do begin end;
To insert a code template in the Code editor, press Ctrl-j and select the template you want to use. You can also add your own templates to this collection. To add a template:
Console applications are 32-bit Windows programs that run without a graphical interface, usually in a console window. These applications typically don't require much user input and perform a limited set of functions.
To create a new console application, choose File|New and select Console Wizard from the New Items dialog box.
Service applications take requests from client applications, process those requests, and return information to the client applications. They typically run in the background, without much user input. A web, FTP, or e-mail server is an example of a service application.
To create an application that implements a Win32 service, Choose File|New, and select Service Application from the New Items page. This adds a global variable named Application to your project, which is of type TServiceApplication.
Once you have created a service application, you will see a window in the designer that corresponds to a service (TService). Implement the service by setting its properties and event handlers in the Object Inspector. You can add additional services to your service application by choosing Service from the new items dialog. Do not add services to an application that is not a service application. While a TService object can be added, the application will not generate the requisite events or make the appropriate Windows calls on behalf of the service.
Once your service application is built, you can install its services with the Service Control Manager (SCM). Other applications can then launch your services by sending requests to the SCM.
To install your application's services, run it using the /INSTALL option. The application installs its services and exits, giving a confirmation message if the services are successfully installed. You can suppress the confirmation message by running the service application using the /SILENT option.
To uninstall the services, run it from the command line using the /UNINTALL option. (You can also use the /SILENT option to suppress the confirmation message when uninstalling).
Example: This service has a TServerSocket whose port is set to 80. This is the default port for Web Browsers to make requests to Web Servers and for Web Servers to make responses to Web Browsers. This particular example produces a text document in the C:\Temp directory called WebLogxxx.log (where xxx is the ThreadID). There should be only one Server listening on any given port, so if you have a web server, you should make sure that it is not listening (the service is stopped).
To see the results: open up a web browser on the local machine and for the address, type 'localhost' (with no quotes). The Browser will time out eventually, but you should now have a file called weblogxxx.log in the C:\temp directory.
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, ScktComp; type TService1 = class(TService) ServerSocket1: TServerSocket; procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); procedure Service1Execute(Sender: TService); private { Private declarations } Stream: TMemoryStream; // Add this line here public function GetServiceController: PServiceController; override; { Public declarations } end; var Service1: TService1;
procedure TService1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var Buffer: PChar; begin Buffer := nil; while Socket.ReceiveLength > 0 do begin try Buffer := AllocMem(Socket.ReceiveLength); Socket.ReceiveBuf(Buffer^, Socket.ReceiveLength); Stream.Write(Buffer^, StrLen(Buffer)); finally FreeMem(Buffer); end; Stream.Seek(0, soFromBeginning); Stream.SaveToFile('c:\Temp\Weblog' + IntToStr(ServiceThread.ThreadID) + '.log'); end; end;
procedure TService1.Service1Execute(Sender: TService); begin Stream := TMemoryStream.Create; try ServerSocket1.Port := 80; // WWW port ServerSocket1.Active := True; while not Terminated do begin ServiceThread.ProcessRequests(False); end; ServerSocket1.Active := False; finally Stream.Free; end; end;
When writing your service application, you should be aware of:
Each service has its own thread (TServiceThread), so if your service application implements more than one service you must ensure that the implementation of your services is thread-safe. TServiceThread is designed so that you can implement the service in the TService OnExecute event handler. The service thread has its own Execute method which contains a loop that calls the service's OnStart and OnExecute handlers before processing new requests. Because service requests can take a long time to process and the service application can receive simultaneous requests from more than one client, it is more efficient to spawn a new thread (derived from TThread, not TServiceThread) for each request and move the implementation of that service to the new thread's Execute method. This allows the service thread's Execute loop to process new requests continually without having to wait for the service's OnExecute handler to finish. The following example demonstrates.
Example: This service beeps every 500 milliseconds from within the standard thread. It handles pausing, continuing, and stopping of the thread when the service is told to pause, continue, or stop.
TSparkyThread = class(TThread) public procedure Execute; override; end;
var SparkyThread: TSparkyThread;
procedure TSparkyThread.Execute; begin while not Terminated do begin Beep; Sleep(500); end; end;
procedure TService1.Service1Start(Sender: TService; var Started: Boolean); begin SparkyThread := TSparkyThread.Create(False); Started := True; end;
procedure TService1.Service1Continue(Sender: TService; var Continued: Boolean); begin SparkyThread.Resume; Continued := True; end;
procedure TService1.Service1Pause(Sender: TService; var Paused: Boolean); begin SparkyThread.Suspend; Paused := True; end;
procedure TService1.Service1Stop(Sender: TService; var Stopped: Boolean); begin SparkyThread.Terminate; Stopped := True; end;
When developing server applications, choosing to spawn a new thread depends on the nature of the service being provided, the anticipated number of connections, and the expected number of processors on the computer running the service.
The VCL provides classes for creating service applications. These include TService and TDependency. When using these classes, the various name properties can be confusing. This section describes the differences.
Services have user names (called Service start names) that are associated with passwords, display names for display in manager and editor windows, and actual names (the name of the service). Dependencies can be services or they can be load ordering groups. They also have names and display names. And because service objects are derived from TComponent, they inherit the Name property. The following sections summarize the name properties:
The TDependency DisplayName is both a display name and the actual name of the service. It is nearly always the same as the TDependency Name property.
The TService Name property is inherited from TComponent. It is the name of the component, and is also the name of the service. For dependencies that are services, this property is the same as the TDependency Name and DisplayName properties.
TService's DisplayName is the name displayed in the Service Manager window. This often differs from the actual service name (TService.Name, TDependency.DisplayName, TDependency.Name). Note that the DisplayName for the Dependency and the DisplayName for the Service usually differ.
Service start names are distinct from both the service display names and the actual service names. A ServiceStartName is the user name input on the Start dialog selected from the Service Control Manager.
The simplest way to debug your service application is to attach to the process when the service is running. To do this, choose Run|Attach To Process and select the service application from the list of available processes.
In some cases, this may fail, due to insufficient rights. If that happens, you can use the Service Control Manager to enable your service to work with the debugger:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
Dynamic link libraries (DLLs) are modules of compiled code that work in conjunction with an executable to provide functionality to an application.
Packages are special DLLs used by Delphi applications, the IDE, or both. There are two kinds of packages: runtime packages and design-time packages. Runtime packages provide functionality to a program while that program is running. Design-time packages extend the functionality of the IDE.
For more information on packages, see "Working with packages and components".
For most applications written in Delphi, packages provide greater flexibility and are easier to create than DLLs. However, there are several situations where DLLs would be better suited to your projects than packages:
One of Delphi's strengths is its support for creating advanced database applications. Delphi includes built-in tools that allow you to connect to Oracle, Sybase, Informix, dBASE, Paradox, or other servers while providing transparent data sharing between applications. The Borland Database Engine (BDE) supports scaling from desktop to client/server applications.
Tools, such as the Database Explorer, simplify the task of writing database applications. The Database Explorer is a hierarchical browser for inspecting and modifying database server-specific schema objects including tables, fields, stored procedure definitions, triggers, references, and index descriptions.
Through a persistent connection to a database, Database Explorer lets you
See "Developing database applications" in this manual for details on how to use Delphi to create both database client applications and application servers.
Distributed applications are applications that are deployed to various machines and platforms and work together, typically over a network, to perform a set of related functions. For instance, an application for purchasing items and tracking those purchases for a nationwide company would require individual client applications for all the outlets, a main server that would process the requests of those clients, and an interface to a database that stores all the information regarding those transactions. By building a distributed client application (for instance, a web-based application), maintaining and updating the individual clients is vastly simplified.
Delphi provides several options for the implementation model of distributed applications:
TCP/IP is a communication protocol that allows you to write applications that communicate over networks. You can implement virtually any design in your applications. TCP/IP provides a transport layer, but does not impose any particular architecture for creating your distributed application.
The growth of the Internet has created an environment where most computers already have some form of TCP/IP access, which simplifies distributing and setting up the application.
Applications that use TCP/IP can be message-based distributed applications (such as Web server applications that service HTTP request messages) or distributed object applications (such as distributed database applications that communicate using Windows sockets).
The most basic method of adding TCP/IP functionality to your applications is to use client or server sockets. Delphi also provides support for applications that extend Web servers by creating CGI scripts or DLLs. In addition, Delphi provides support for TCP/IP-based database applications .
Two VCL classes, TClientSocket and TServerSocket, allow you to create TCP/IP socket connections to communicate with other remote applications. For more information on sockets, see "Working with sockets."
To create a new Web server application, select File|New and select Web Server Application in the New Items dialog box. Then select the Web server application type:
CGI and Win-CGI applications use more system resources on the server, so complex applications are better created as ISAPI or NSAPI applications.
For more information on building Web server applications, see "Creating Internet server applications".
Selecting this type of application sets up your project as a DLL. ISAPI or NSAPI Web server applications are DLLs loaded by the Web server. Information is passed to the DLL, processed, and returned to the client by the Web server.
CGI Web server applications are console applications that receive requests from clients on standard input, processes those requests, and sends back the results to the server on standard output to be sent to the client.
Win-CGI Web server applications are Windows applications that receive requests from clients from an INI file written by the server and writes the results to a file that the server sends to the client.
COM is the Component Object Model, a Windows-based distributed object architecture designed to provide object interoperability using predefined routines called interfaces. .COM applications use objects that are implemented by a different process or, if you use DCOM, on a separate machine.
Delphi has classes and wizards that make it easy to create the essential elements of a COM, OLE, or ActiveX application. Using Delphi to create COM-based applications offers a wide range of possibilities, from improving software design by using interfaces internally in an application, to creating objects that can interact with other COM-based API objects on the system, such as the Win95 Shell extensions and DirectX multimedia support.
For more information on COM and Active X controls, see "Overview of COM technologies," "Creating an ActiveX control," and "Distributing a client application as an ActiveX control".
For more information on DCOM, see "Using DCOM connections".
The Microsoft Transaction Server (MTS) is a an extension to DCOM that provides transaction services, security, and resource pooling for distributed COM applications.
For more information on MTS, see "Creating MTS objects", "Using MTS".
Common Object Request Broker Architecture (CORBA) is a method of using distributed objects in applications. The CORBA standard is used on many platforms, so writing CORBA applications allows you to make use of programs that are not running on a Windows machine.
Like COM, CORBA is a distributed object architecture, meaning that client applications can make use of objects that are implemented on a remote server.
For more information on CORBA, see "Writing CORBA applications".
For instructions on distributing applications using CORBA, see "Deploying CORBA applications".
Delphi provides support for creating distributed database applications using the MIDAS technology. This powerful technology includes a coordinated set of components that allow you to build a wide variety of multi-tiered database applications. Distributed database applications can be built on a variety of communications protocols, including DCOM, CORBA, TCP/IP, and OLEnterprise.
For more information about building distributed database applications, see "Creating multi-tiered applications".
Distributing database applications often requires you to distribute the Borland Database Engine (BDE) in addition to the application files. For information on deploying the BDE, see "Deploying database applications".
pubsweb@borland.com
Copyright
© 1999, Inprise Corporation. All rights reserved.