Delphi Programming Guide
Delphi Programmer 

Menu  Table of contents
Bookmark and Share

Part I - Foundations
  Chapter 1 Delphi 7 and Its IDE
  Chapter 2 The Delphi Programming Language
  Chapter 3 The Run-Time Library
  Chapter 4 Core Library classes
  Chapter 5 Visual Controls
  Chapter 6 Building the User Interface
  Chapter 7 Working with Forms
Part II - Delphi Object-Oriented Architectures
  Chapter 8 The Architecture of Delphi Applications
  Chapter 9 Writing Delphi Components
  Chapter 10 Libraries and Packages
  Chapter 11 Modeling and OOP Programming (with ModelMaker)
  Chapter 12 From COM to COM+
Part III - Delphi Database-Oriented Architectures
  Chapter 13 Delphi's Database Architecture
  Chapter 14 Client/Server with dbExpress
  Chapter 15 Working with ADO
  Chapter 16 Multitier DataSnap Applications
  Chapter 17 Writing Database Components
  Chapter 18 Reporting with Rave
Part IV - Delphi, the Internet, and a .NET Preview
  Chapter 19 Internet Programming: Sockets and Indy
  Chapter 20 Web Programming with WebBroker and WebSnap
  Chapter 21 Web Programming with IntraWeb
  Chapter 22 Using XML Technologies
  Chapter 23 Web Services and SOAP
  Chapter 24 The Microsoft .NET Architecture from the Delphi Perspective
  Chapter 25 Delphi for .NET Preview: The Language and the RTL
       
  Appendix A Extra Delphi Tools by the Author
  Appendix B Extra Delphi Tools from Other Sources
  Appendix C Free Companion Books on Delphi
       
  Index    
  List of Figures    
  List of tables    
  List of Listings    
  List of Sidebars  

 
Previous Section Next Section

VCL versus VisualCLX

As you saw in Chapter 4, "Core Library Classes," Delphi has two visual class libraries: the cross-platform library (CLX) alongside the traditional Windows library (VCL). There are certainly many differences, even in the use of the RTL and code library classes, between developing programs specifically for Windows or with a cross-platform attitude, but the differences are most striking in the user interface portion.

The visual portion of VCL is a wrapper of the Window API. It includes wrappers of the native Windows controls (like buttons and edit boxes), the common controls (like TreeViews and ListViews), plus a bunch of native Delphi controls bound to the Windows concept of a window. In addition, a TCanvas class wraps the basic graphic calls, so you can easily paint on the surface of a window.

VisualCLX, the visual portion of CLX, is a wrapper of the Qt (pronounced "cute") library. It includes wrappers of the native Qt widgets, which range from basic to advanced controls, very similar to Windows' standard and common controls. It also includes painting support using another, similar, TCanvas class. Qt is a C++ class library developed by Trolltech (www.trolltech.com), a Norwegian company with a strong relationship with Borland.

On Linux, Qt is one of the de facto standard user-interface libraries and is the basis of the KDE desktop environment. On Windows, Qt provides an alternative to the use of the native APIs. Unlike VCL, which provides a wrapper to the native controls, Qt provides an alternate implementation to those controls. Even if each of them is based on Windows's window, a QT button isn't a Windows BUTTON class control (you can see this by running WinSight32). This allows programs to be truly portable, because no hidden differences are created by the operating system (or introduced by the operating system vendor behind the scenes). It also allows you to avoid an extra layer; CLX on top of Qt on top of Windows native controls suggests three layers, but in fact there are two layers in each solution (CLX controls on top of Qt, VCL controls on top of Windows).

Note 

Distributing Qt applications on Windows implies the distribution of the Qt library itself. On the Linux platform, you can generally take the presence of the Qt library for granted, but you still have the interface library to deploy. Also, Linux Borland's CLX is tied to a specific version of Qt (which in Kylix 3 has been specifically patched by Borland), so you'll probably have to distribute it anyway. Distributing the Qt libraries with a professional application (as opposed to an open source project) generally implies paying a license to Trolltech. If you use Delphi or Kylix to build Qt applications, however, Borland has already paid the license to Trolltech for you. You must use at least one CLX class wrapping Qt: If you use the Qt classes exclusively (no CLX at all), you still owe the license to Qt, even when using Delphi or Kylix.

Technically, huge differences exist behind the scenes between a native Windows application built with VCL and a portable Qt program developed with VisualCLX. Suffice to say that at the low level, Windows uses API function calls and messages to communicate with controls, whereas Qt uses class methods and direct method callbacks and has no internal messages. Technically, the Qt classes offer a high-level object-oriented architecture, but the Windows API is still bound to its C legacy and a message-based system dated 1985 (when Windows was released). VCL offers an object-oriented abstraction on top of a low-level API, whereas VisualCLX remaps an already high-level interface into a more familiar class library. (For more on the Qt architecture, see the following sidebar "From Qt to CLX.")

Note 

Microsoft has reached the point of starting to abandon the traditional low-level Windows API for a native high-level class library, part of the .NET architecture. You can read more about this topic in Part IV of this book.

If the underlying architectures of the Windows API on one side and Qt on the other side are relevant, the two class libraries built by Borland (VCL and CLX) flatten out most differences, making the code of Delphi and Kylix applications extremely similar. Using VisualCLX on Linux offers Delphi programmers the advantage of having a familiar class library on top of a totally new platform. From the outside, a button is an object of the TButton class for both libraries, and it has more or less the same set of methods, properties, and events. In many cases, you can recompile your existing programs for the new class library in a matter of minutes, if they don't use low-level API calls, platform-dependent features (like ADO or COM), or legacy features (like the BDE).

Delphi's Dual Library Support

Delphi has full support for both libraries at design time and at run time. As you begin developing a new application, you can use the File ® New Application command to create a new VCL-based program or File ® New CLX Application for a new CLX-based program. After you give one of these commands, Delphi's IDE will create a VCL or CLX design-time form and update the Component Palette so that it displays only the visual components compatible with the type of application you've selected (see Figure 5.1 for a comparison). You cannot place a VCL button into a CLX form, and you cannot even mix forms of the libraries within a single executable file. In other words, the user interface of every application must be built using one of the two libraries exclusively, which (aside from the technical implications) makes a lot of sense to me.

Click To expand
Figure 5.1: A comparison of the first three pages of the Component Palette for a CXL-based application (above) and a VCL-based application (below)

If you haven't already done so, I suggest you to try experimenting with the creation of a CLX application, looking at the available controls and trying to use them. You'll find few differences in the use of the components, and if you have been using Delphi for some time, you'll probably be immediately adept with CLX.

Same Classes, Different Units

One of the cornerstones of the source-code compatibility between CLX and VCL is the fact that similar classes in the two libraries have the same class name. For example, each library has a class called TButton representing a push button; the methods and properties are so similar that this code will work with both libraries:

with TButton.Create (Self) do
begin
  SetBounds (20, 20, 80, 35);
  Caption := 'New';
  Parent := Self;
end;

The two TButton classes can have the same name because they are saved in two different units, called StdCtrls and QStdCtrls. Of course, you cannot have the two components available at design time in the palette, because the Delphi IDE can register only components with unique names. The entire VisualCLX library is defined by units corresponding to the VCL units, but with the letter Q as a prefix—so there is a QForms unit, a QDialogs unit, a QGraphics unit, and so on. A few peculiar units, such as QStyle, have no corresponding unit in VCL because they map to features of Qt with no correspondence in the Windows API.

Notice that there are no compile settings or other hidden techniques to distinguish between the two libraries; what matters is the set of units referenced in the code. Remember that these references must be consistent—you cannot mix visual controls of the two libraries in a single form or even in a single program.

DFM and XFM

As you create a form at design time, it is saved to a form definition file. Traditional VCL applications use the DFM extension, which stands for Delphi form module. CLX applications use the XFM extension, which stands for cross-platform (X) form module. A form module is the result of streaming the form and its components: The two libraries share the streaming code, so they produce a similar effect. The format of DFM and XFM files, which can be based on a textual or binary representation, is identical.

So, the reason for having two different extensions doesn't lie in internal compiler tricks or incompatible formats. It is merely an indication to programmers and to the IDE of the type of components you should expect to find within that definition (this indication is not included in the file).

If you want to convert a DFM file into an XFM file, you can simply rename the file. However, expect to find some differences in the properties, events, and available components— reopening the form definition for a different library will probably cause quite a few warnings.

Tip 

Delphi's IDE chooses the active library by looking at the extension of the form module, ignoring the references in the uses statements. For this reason, you should change the extension if you plan to use CLX. On Kylix, a different extension is useless, because any form is opened in the IDE as a CLX form regardless of the extension. On Linux, there is only the Qt-based CLX library, which is both the cross-platform and the native library.

As an example, I've built two identical applications, LibComp and QLibComp, with only a few components and a single event handler. Listing 5.1 presents the textual form definitions for two applications, built using the same steps in the Delphi IDE, after choosing a CLX or VCL application. I've marked differences in bold; as you can see, there are very few, most relating to the form and its font. OldCreateOrder is a legacy property used for compatibility with Delphi 3 and older code; standard colors have different names; and CLX saves the scroll bars' ranges.

Listing 5.1: An XFM File (Left) and an Equivalent DFM File (Right)
Start example
object Form1: TForm1              object Form1: TForm1
  Left = 192                        Left = 192
  Top = 107                         Top = 107
  Width = 350                       Width = 350
  Height = 210                      Height = 210
  Caption = 'QLibComp'              Caption = 'LibComp'
 Color = clBackground              Color = clBtnFace
 VertScrollBar.Range = 161         Font.Charset = DEFAULT_CHARSET
 HorzScrollBar.Range = 297         Font.Color = clWindowText
                                   Font.Height = -11
                                   Font.Name = 'MS Sans Serif'
                                   Font.Style = []
  TextHeight = 13                   TextHeight = 13
  TextWidth = 6                     OldCreateOrder = False
  PixelsPerInch = 96                PixelsPerInch = 96
  object Button1: TButton           object Button1: TButton
    Left = 56                         Left = 56
    Top = 64                          Top = 64
    Width = 75                        Width = 75
    Height = 25                       Height = 25
    Caption = 'Add'                   Caption = 'Add'
    TabOrder = 0                      TabOrder = 0
    OnClick = Button1Click            OnClick = Button1Click
 end                               end
  object Edit1: TEdit               object Edit1: TEdit
    Left = 40                         Left = 40
    Top = 32                          Top = 32
    Width = 105                       Width = 105
    Height = 21                       Height = 21
    TabOrder = 1                      TabOrder = 1
    Text = 'my name'                  Text = 'my name'
 end                               end
  object ListBox1: TListBox         object ListBox1: TListBox
    Left = 176                        Left = 176
    Top = 32                          Top = 32
    Width = 121                       Width = 121
    Height = 129                      Height = 129
    Rows = 3                          ItemHeight = 13
    Items.Strings = (                 Items.Strings = (
      'marco'                           'marco'
      'john'                            'john'
      'helen')                          'helen')
    TabOrder = 2                      TabOrder = 2
 end                               end
end                               end
End example

uses Statements

If you look at the source code of a VCL or CLX application, the only relevant difference relates to the uses statements. The form of the CLX application has the following initial code:

unit QLibCompForm;
interface
uses
  SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs, QStdCtrls;

The form of the VCL program has the traditional uses statement:

unit LibCompForm;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

The code of the class and of the only event handler is absolutely identical. Of course, the compiler directive {$R *.dfm} is replaced by {$R *.xfm} in the CLX version of a standard program.

Disabling the Dual Library Help Support

When you press the F1 key in the editor to ask for help on a routine, class, or method of the Delphi library, you'll usually get a choice between the VCL and CLX declarations of the same feature. You'll need to make a choice to proceed to the related help page, which can be quite annoying after a while (especially because the two pages are often identical).

If you don't care about CLX and are planning to use only VCL (or vice versa), you can disable this alternative by choosing the Help ® Customize command, removing everything with CLX in the name from Contents, Index, and Link, and saving the project. Then restart the Delphi IDE, and the Help engine won't bother asking you about CLX any more. Of course, don't forget to add those help files again if you decide to begin using CLX. Similarly, you can reduce the memory occupation and load time of the Delphi IDE by uninstalling all the CLX-related packages.

Choosing a Visual Library

Because two different user interface libraries are available in Delphi, you'll have to choose one for each visual application. You must evaluate multiple criteria to come to the proper decision, which isn't always easy.

The first criterion is portability. If running your program on Windows and on Linux, with the same user interface, is a major concern to you, then using CLX will make your life simpler and let you keep a single source code file with limited IFDEFs. The same applies if you consider Linux to be (or think it possibly will become) your key platform. On the other hand, if most of your users are on Windows and you just want to extend your offering with a Linux version, you might want to keep a dual VCL/CLX system. Doing so means you'll probably need two different sets of source code files, or you may have too many IFDEFs.

Another criterion is the native look-and-feel. Is you use CLX on Windows, some controls will behave slightly differently than users expect—at least expert users. For a simple user interface (edits, buttons, grids), this probably won't matter much; but if you have many tree view and list view controls, the differences will be clear. On the other hand, with CLX, you'll be able to let your users choose a look-and-feel that's different from the basic Windows look, and use it consistently across platforms. This means that a Motif fan will be able to choose this style even when forced to use the Windows platform. While this flexibility is common on Linux, you'll seldom use a non-native look-and-feel on Windows.

Using native controls also implies that as soon as you get a new version of the Windows operating system, your application will (probably) adapt to it. This is good for the user, but might cause you a lot of headaches in case of incompatibilities. Differences in the Microsoft common controls library over the last few years have been a major source of frustration for Windows programmers in general, including Delphi programmers.

Another criterion is deployment: If you use CLX, you'll have to ship your Windows and Linux program with the Qt libraries.

I've done a little testing, and the speed of VCL and CLX applications is similar. I've tried creating 1,000 components and showing them on screen, and the speed differences are few; the VCL-based solution offered a 30 percent advantage (for what this limited benchmark is worth). You can try my tests with the LibSpeed and QLibSpeed examples for this chapter.

Another important criterion for deciding to use CLX instead of VCL is a need for Unicode support. CLX has Unicode support in controls by default (even on Win9x platforms where it isn't supported by Microsoft). VCL, however, has very little Unicode support even on versions of Windows that provide it, making it difficult to build VCL apps for countries where the local character is managed more easily when it is Unicode based.

Running It on Linux

The real issue of choosing the library resolves to the importance of Linux or Unicode for you and your users. It's important to notice that if you create a CLX application, you'll be able to recompile it unchanged (with the exact source code) with Kylix, producing a native Linux application, unless you've done any Windows API programming at all, in which case conditional compilation will be essential.

As an example, I've recompiled the QLibComp example introduced earlier. Figure 5.2 shows it running; you can also see the Kylix IDE in action on KDE.

Click To expand
Figure 5.2: An application written with CLX can be directly recompiled under Linux with Kylix (displayed in the background).

Conditional Compilation for Libraries

If you want to keep a single source code file but compile with VCL on Windows and CXL on Linux, you can use platform-specific symbols (such as $IFDEF LINUX) to distinguish the two situations in case of conditional compilation. But what if you want to be able to compile a portion of code for both libraries on Windows?

You can either define a symbol of your own and use conditional compilation, or (at times) test for the presence of identifiers that exist only in VCL or CLX:

{$IF Declared(QForms)}
  ...CLX-specific code
{$IFEND}

Converting Existing Applications

Besides starting with new CLX applications, you might want to convert some of your existing VCL applications to the new class library. You must perform a series of operations without any specific help from the Delphi IDE:

  • Rename the DFM file using the XFM extension and update all the {$R *.DFM} statements as {$R *.XFM}.

  • Update all the uses statements in your program (in the units and project files) to refer to the CLX units instead of the VCL units. If you miss even a few, you'll bump into trouble when running your application.

Tip 

To prevent a CLX application from compiling if it contains references to VCL units, you can move the VCL units to a different directory under lib and avoid including this folder in your search path. This way, leftover references to VCL units will cause a "Unit not found" error.

Table 5.1 compares the names of the visual VCL and CLX units, excluding the database portion and some rarely referenced units.

Table 5.1: Names of Equivalent VCL and CLX Units

VCL

CLX

ActnList

QActnList

Buttons

QButtons

Clipbrd

QClipbrd

ComCtrls

QComCtrls

Consts

QConsts

Controls

QControls

Dialogs

QDialogs

ExtCtrls

QExtCtrls

Forms

QForms

Graphics

QGraphics

Grids

QGrids

ImgList

QImgList

Menus

QMenus

Printers

QPrinters

Search

QSearch

StdCtrls

QStdCtrls

You might also convert references to Windows and Messages into references to the Qt unit. Some Windows data structures are now also available in the Types unit (see Chapter 3, "The Run-Time Library," for details), so you might have to add it to your CLX programs. Notice, however, that the QTypes unit is not the CLX version of VCL's Types unit; these two units are totally unrelated.

Warning 

Watch out for your uses statements! If you compile a project that includes a CLX form, but you fail to update the project source code, leaving a reference to the VCL Forms unit there, your program will run but stop immediately. The reason is that no VCL form was created, so the program terminated right away. In other cases, trying to create a CLX form within a VCL application will cause run-time errors. Finally, the Delphi IDE might inappropriately add references to uses statements of the wrong library; in this case you end up with a single uses statement that refers to the same unit for both libraries, but only the second of the two will be effective. This situation rarely prevents the program from compiling, but you won't be able to run it.

As a helper in converting some of my own programs, I've written a simple unit-replacement tool called VclToClx; it's available in the Tools section of the source code that accompanies the book. You can find more information about this program in Appendix A, "Extra Delphi Tools by the Author."


 
Previous Section Next Section


 


 


Copyright © 2004-2016 "Delphi Sources". Delphi Programming Guide
     Twitter     Facebook