Overview of the VCL for .NET

By: John Kaster

Abstract: This article provides an overview of the architecture, design, and intent of the Visual Component Library for .NET included with the Delphi for .NET preview

By John Kaster, Eddie Churchill, and Danny Thorpe

Borland has included experimental versions of the VCL (Visual Component Library) for .NET in an update to the Delphi for .NET preview, which is available for download by registered users. Even with access to this source code, many Delphi users are still confused about exactly what the VCL for .NET is and how they can use it. Hopefully we can clear up some of this confusion.

If you haven't already read the BDN article on the Delphi for .NET compiler, I recommend doing that before reading this article.

In this article, I will be providing graphics and information extracted from a presentation originally given by Eddie Churchill at BorCon 2002 in Anaheim, California, USA. These slides say "BorCon Tokyo" because I presented them there after Eddie presented them in California. BorCon 2003 is in the planning stages now, so be sure to mark your calendar so you don't miss it.

Review of frameworks

What is probably the chief source of confusion regarding the VCL for .NET is based on imprecise usage of the term "VCL" by both Borland and the users of the framework that comes with the native code development products Delphi, C++Builder, and Kylix. "Visual Component Library" was a misnomer for the entire component framework, since the majority of the framework was non-visual. When Borland introduced Kylix, we also finally came up with an official name for the Delphi component framework: "CLX." CLX stands for "Component Library for Cross-Platform" development, and is pronounced the same as "clicks."

CLX is now the official term describing the entire component framework that is used in Delphi, C++Builder, and Kylix. The VCL is the set of components that provide a visual interface for applications running on top of the Win32 API. You can see the VCL listed in the upper right tier of the architectural diagram below.

CLX, the Delphi framework
Defining "CLX," the Component Library for cross-platform development

VisualCLX vs. VCL

With Kylix, Borland introduced VisualCLX. VisualCLX is the set of components used in cross-platform GUI applications. Qt, a class library from TrollTech, is used as the graphical API for VisualCLX. VisualCLX is available in all versions of Kylix, and in Delphi and C++Builder 6 and onwards, in Professional or higher SKUs. The interface to the VisualCLX controls is nearly identical to the interface to the VCL controls. They perform the same functions, and are mutually exclusive in an application. CLX supports writing identical source code that can talk to the properties, methods, and events of either the VCL or VisualCLX. You specify which set of controls to use by referring to the appropriate source code unit names, as the following code snippet illustrates.


{$ifdef VisualCLX}
uses
  Classes, QControls, QComCtrls;
{$endif}
{$ifdef VCL}
uses
  Classes, Controls, ComCtrls;
{$endif}

... 

{ the same source code for talking to either 
set of controls goes here, such as }

Form1.Caption := 'Hello World!';
Button1.Enabled := True;

....

This source code sample is similar to what is required in your source code when default namespace searching is not available. More on this later.


VisualCLX and VCL side by side

The difference between VCL and VisualCLX lies in their display API.

VisualCLX on Linux
VisualCLX on Linux

VisualCLX calls the Qt class library on Linux, which in turn calls XWindow for graphical display.

VisualCLX on Win32
VisualCLX on Win32

VisualCLX calls the Qt class library on Win32, which in turn calls Win32 for graphical display.

VCL on Win32
VCL on Win32

The VCL calls Win32 APIs for its graphical display.

Current framework choices

The following guidelines may be helpful when making a decision between VCL and VisualCLX for your GUI application.

  • If you want your visual application to look best on Windows, use VCL.
  • If you want your visual application to work on both Windows and Linux, use Visual CLX. For Windows, you will need to deploy the Qt run-time library and packages. Qt is already included with every major Linux distribution.

Whether you use VCL or VisualCLX, your application will use CLX, the Delphi framework.

The packages that contain the visual components for VCL and VisualCLX are only nine (9) of the over forty (40) packages that comprise CLX. The vast majority of the classes and components in CLX are non-visual in nature, and have identical programming interfaces for any platform.

Comparing VCL for .NET and WinForms

.NET includes controls for building visual applications on the platform. These controls are included in an assembly called System.Windows.Forms. Many of these controls are very similar to existing visual controls from CLX. This similarity is primarily caused by the environment in which both sets of controls run, and the fact that they are a component-based implementation.

The similarities

There are many similarities between the current Delphi application environment and the .NET application environment:

  • Framework and applications
    • Both are written on top of Win32.
    • When running, applications created in both frameworks run "Native."
    • Execution speed and code size are similar.
    • Both present the OS as a series of objects and components.
  • VCL and System.Windows.Forms
    • Both use User32, ComCtrls and RichEd.
    • Both talk to the OS via abstraction layers.
    • Both present the underlying OS user interface APIs as a series of controls.
      • Forms
      • Panels
      • Buttons
      • Etc.

The following slide illustrates the similarity in the architecture of Winforms and VCL. You can compare this to the VCL slide.

WinForms on Win32
.NET WinForms on Win32

Let's look more closely at the implementation of WinForms for the .NET framework that runs on the Windows operating system. A managed layer (System.Windows.Forms) makes calls to what is termed "Native Methods" in .NET. This is actually how everything in the .NET framework (and the Java framework, for that matter) is implemented. At some point, calls to native methods/machine code are required.

Native Methods
.NET native method calls

This is an important point to note, because it is a very important similarity between the VCL and .NET framework, as I'll explain later.

The differences

The language neutrality as defined in the CIL (Common Intermediate Language), the CLS (Common Language Specification), and the CLR (Common Language Runtime) of the .NET platform also drives some differences between the frameworks.

  • Delphi and its framework
    • Runs on Windows and Linux right now.
    • Only components written with Delphi can participate in the Delphi framework.
    • VCL has TGraphicControl which does not have a Win32 handle. .NET does not currently have anything similar.
  • .NET framework
    • Runs on Windows and PocketPC but a number of other OSs are in the works
    • Any component or control written using a .NET compatible language can participate in the .NET framework. This includes Delphi for .NET, C#, VB.NET, and so on.

VCL for .NET implementation

As mentioned previously, an important implementation detail the VCL for .NET has in common with System.Windows.Forms is a managed layer that makes calls to the native APIs for Win32. Furthermore, VCL for .NET can be used in conjunction with System.Windows.Forms controls, unlike the VCL for Win32 and VisualCLX, which are mutually exclusive. This provides tremendous flexibility for migrating your existing Delphi applications to .NET. You can quickly move the entire application by using VCL for .NET for cross-platform language compatibility, then gradually replace the VCL code with standard CLR code should you choose to do so.

The following slide illustrates what will probably be a typical usage pattern for Delphi applications on .NET.

Delphi for .NET application
Borland.VCL and .NET WinForms coexisting in a Delphi application

There is another slide with the arrow going the other way, but I think you get the idea.

These slides make the level of similarity between .NET WinForms and the VCL misleading. We originally investigated using class helpers and wrappers to produce the VCL for .NET as simple name aliases to the visual components provided by .NET WinForms. We eventually decided that while WinForms shares many design patterns with VCL, the implementation semantics are too different to simply map VCL class names onto Winform classes. In particular, the initialization and finalization semantics of WinForms controls are radically different from VCL.

If you are willing to accept changes in fundamental semantics, you could do a simple name mapping between VCL and WinForms. However, that is not an acceptable solution to achieve a high degree of compatibility with existing VCL source code that relies heavily on the rich semantics of the VCL framework.

All Borland-produced redistributable assemblies will be strong named and codesigned by Borland. That should allow the assemblies to be handled by the default security policies set up by the .NET framework and the OS.

The whole point of VCL for .NET is to replicate the VCL architecture in .NET, all the way down to the message methods and other Win32 API bits. VCL for .NET is the fastest way to move existing desktop application code from VCL (or CLX) to desktop .NET. VCL for .NET is not intended to be used on non-Win32 platforms.

Namespaces

Namespace support is a good topic to bring up when considering the migration of existing application code. With the addition of namespace support to the compiler and IDE, compatibility among the various platforms Delphi supports will be increased.

The unit names (which are what make the namespace value) are being expanded in Delphi for .NET, and in future releases of Delphi for Win32 and Delphi for Linux to take advantage of the compiler and IDE's planned namespace support.

Run-time namespace
Examples of values in the run-time namespace

Borland.VCL namespace
Examples of values in the VCL namespace

Of particular interest to people who want to use Delphi for cross-platform code are the VCL namespace entries. In Kylix 3 and Delphi 7, the VisualCLX source files that correspond to the VCL source files have a "Q" prepended to them. For example, the VCL source file Controls.pas becomes the CLX source file QControls.pas. With the support for default namespaces, the file name will be quite different when fully qualified, but the same when left to the default lookup rules.

The following diagram illustrates how the namespace resolution will probably work:

VCL for Win32 or .NETCLX for Win32 or Linux
Looks for local SysUtils,Looks for a local SysUtils,
then Borland.VCL.SysUtils,then Borland.CLX.SysUtils,
then Borland.Delphi.SysUtilsthen Borland.Delphi.SysUtils

This namespace resolution logic will allow you to write Delphi code that simply says:

uses SysUtils;

and the SysUtils unit will end up referencing the appropriate code for the type of project you are developing.

A package deal!

We plan to support packages in Delphi for .NET (it's not done yet) so that you will have the same build and deploy options you have today in Delphi 7: link all code into a single large executable, or link to code that resides in packages to produce a much smaller executable.

These packages will be similar in size to the existing packages. If you choose to use the run-time package option for your applications, the packages will have to be deployed/installed on the machine running the application.

When to use VCL for .NET or Windows.Forms

There are always trade-offs when choosing a technical direction to go. The following list is not intended to be all-inclusive or even definitive, but should give you some broad implementation issues to consider when determining which way you will implement solutions for .NET.

Downside of Borland.VCL

  • The deployment size of applications using Borland.VCL will often be larger than applications that only use Windows.Forms equivalents, because the Windows.Forms packages are already deployed with the .NET run-time, but the Borland.VCL packages are not.
  • Borland.VCL is only available on the Win32 platform, so source code changes will usually be required to make the application run on the .NET Compact Framework. If you want to use the Compact Framework, you would be better off using Windows.Forms with Delphi for .NET.

Upside of Borland.VCL

  • By using Borland.VCL with Delphi for .NET, changes to existing code will be minimized.
  • The coding experience and application behavior for Borland.VCL will be very similar to today's VCL and VisualCLX implementations, so you minimize retraining time for both developers and end-users.
  • You keep a high level of "identifier" compatibility with VisualCLX, which will still leave the option of compiling natively to the Linux platform.
  • VCL for .NET perserves the handle sharing mechanisms of VCL, while WinForms does not perform any consolidation or sharing of resource handles like fonts, brushes, canvases, etc. VCL for .NET could have a memory and/or performance edge over WinForms when we get it all tuned and tied down.
  • VCL for .NET does bring with it more code than WinForms, largely because VCL for .NET represents nearly a decade of component architecture development, experience, and features above and beyond the Win32 API. WinForms is a nice start for a component architecture, but it is still only a 1.0.
  • You get the source code!

Downside of Windows.Forms

  • Systems.Windows.Forms is different from the VCL's behavior. It will take some getting used to if you are familiar with VCL.
  • The third party control market for .NET is still in its early stages, but is ramping up quickly. Furthermore, remember you will also be able to use those controls in applications that use Borland.VCL as well.
  • You don't get the source code

Upside of Windows.Forms

  • If you choose Windows.Forms instead of Borland.VCL (remember, they are not mutually exclusive so you can still use both if you are so inclined), your application's code size may be smaller.
  • You finally get a chance to rework your visual logic and fix all those bugs that have been plaguing you :-).
  • Developing applications that use Systems.Windows.Forms will have a better chance at portability to other .NET platforms.
    • Applications that are limited to the feature set of the .NET compact framework will run fine on the full platform as well.
    • Applications that use Borland.VCL won't easily shift to other .NET platforms because Borland.VCL will still be built on top of the Win32 API.

Even better news on the horizon

The component set solutions discussed here are heavily reliant on .NET's support for native methods to call the underlying Win32 API. Microsoft is committed to creating managed APIs for all their existing technology. All new technology Microsoft produces will ship with managed APIs. Because Delphi for .NET has complete access to the .NET run-time by being a first-class language for .NET, you have complete access to any new Microsoft technology immediately.

For example, DirectX 9 SDK includes .NET support and .NET language examples. Looks like fun! No more header translations required for Delphi, and you have complete access to the SDK instantly!

This commitment also works in your favor. Your managed classes and components will be first-class citizens to the rest of .NET.

When is .NET not .NET?

Like all "portable" frameworks, different implementations of .NET may not include all of .NET. For example, ROTOR, includes a vast majority of what the Desktop version of .NET delivers, but does not include (among other things) the System.Windows.Forms assembly. This means that if you create an application that uses System.Windows.Forms it wont run on ROTOR.

Likewise, the .NET compact framework includes only a subset of what is found in the Desktop version of .NET. While it delivers System.Windows.Forms, it does not include all of it. There are a number of methods, properties and classes missing. Due to the late JITing and linking you might not know that something your code calls is unavailable until it is too late.

Not ready for .NET?

Even if you dont want to use .NET, it still will make your life easier. More of the SDKs will be available to you faster, without resorting to "C"-like code. From a native Delphi application, the whole of .NET is available via COM interop.

Déjà vu all over again?

While it may look like we are changing everything again, it is not quite a bad as it might seem at first glance. Delphi is alive and vibrant, and of course will evolve as technology changes. The Delphi language is getting lots of exciting new features and still remaining compatible with existing code. Many of the extensions to it will also be available in future releases of the native compilers, perpetuating a high degree of compatibility among the platforms.

The run-time library (RTL) is still there and still very familiar. It is simply renamed to Borland.Delphi to take advantage of the new namespace support in the compiler.

The VCL is still there, just renamed Borland.VCL. We have no plans to get rid of VCL or deprecate it. Your current Delphi skill set will still apply, but you are also free to dig into .NET's Systems.Windows.Forms as well.

We plan to make the vast majority of the existing Delphi framework available on .NET, including dbExpress, DataSnap, WebSnap, and so on.

With Delphi's support for the .NET platform, Delphi developers have a strategic advantage for writing feature rich, high performance applications that run natively not only on .NET, but also Win32 and Linux. If you haven't already started working with Delphi for .NET, you can start by purchasing any version of Delphi 7. When you come to .NET, you'll see many familiar faces there, and find that Delphi still gives you the power you need to get the job done.

Enjoy!

Server Response from: SC3