By: David Intersimone
Abstract: The first draft document for the Visual Component Library (VCL) description, dated May 13, 1993. This document describes components, properties, events, forms, and more.
VCL is a set of components that are used and combined to construct an application. The components are objects that have properties, methods and events. A property represents the component's state, a method is an action that can be performed on the component, and an event is some action the user can hook code to that is generated by the component. The components are designed to be created and manipulated inside a application building tool. Those familiar with Visual Basic will be familiar with the model.
VCL is easy to use and does not require prior knowledge of Windows programming, the use of pointers, allocating and deallocating dynamic memory, or object-oriented programming. Modifying a property of a visual component should have an immediate visual effect. Events are "contract-less"--doing nothing in response to an event is always valid, and there are little or no restrictions on what a user can do inside an event. Finally, the user does not need to sub-class in order to customize a component and therefore does not have to be familiar with object-oriented programming concepts such as inheritance and polymorphism.
To avoid pointers, VCL relies on a reference object model (as opposed to a static object model like BP7). All components are dynamically allocated and the reference model allows a simplified syntax for referring to dynamically allocated objects in the same way that a var parameter allows a pointer-free reference to a formal parameter. To make it unnecessary for the component user to allocate and deallocate objects, an application's initial state is created and edited by the application builder and written to a file ("streaming" in BP7, "filing" in Delphi). When the program is run, the initial state is filed in and all objects are allocated by the application object. Deallocation is done automatically by the application object when the program terminates. All this is done without the user ever dereferencing a pointer or calling New or Dispose.
To avoid requiring a user to subclass in order to extend an object's functionality, the language now supports method pointers. Method pointers are used to delegate program control to user-written code. While C++'s method pointers contain only a reference to a C++ method ("unbound"), Delphi's method pointers are bound to both an object instance and a particular method of that object. These bound method pointers can point to any method of any object that matches the method pointer's declaration signature (parameters, types, function result type, etc.). This allows the delegation of events to object instances regardless of the class of the delegate.
Every component has a set of properties that the user can modify. Some of these properties are events like OnMouseDown or OnChange to which a user can attach new behavior. A VCL event is always declared as a method pointer property. Using the application builder, a user can quickly specify which component to modify, which event to handle within that component, and then write a few simple lines of code. For example, dropping a new push button onto a form and then double-clicking on the button causes the Ul builder to generate a method stub called Command] Click, connect the OnClick event property to Command] Click, and then position the cursor within the empty begin/end statements in the editor. At this point, the program can be run. When the button is clicked, the default OnClick handler gets control first and then Commandl Click is called and executed.
The component should be modeless, meaning it should not have modes where setting certain properties or calling certain methods is not valid or indeterminate. If a component has a writeable property, it should be able to be changed at any time, and any method should be callable at anytime and produce the expected result. This is difficult to guarantee when encapsulating windows controls. VCL gets around these difficulties by being able to recreate any window's handle it may have. If a change is made to the windows state that cannot be changed via a standard windows call (i.e. from a thick frame to a thin frame window), a new window handle is created and the old window handle is thrown away. To avoid creating and destroying windows unnecessarily, VCL will also delay the creation of windows until it is necessary (i.e. until the window becomes visible).
The best way to get a feel for VCL is to look at a prototypical component in VCL. The Button component is probably the easiest to understand:
TButton = class(TComponent)
Property Bounds: TRect read FBounds write SetBounds;
Property Left: LongInt read FBounds.Left write SetLeft;
Property Top: LongInt read FBounds.Top write SetTop;
Property Width: LongInt read FBounds.Width write SetWidth;
Property Height: LongInt read FBounds.Height write SetHeight;
Property Color: TColor read FColor write SetColor;
Property Cursor: HCURSOR read FCursor write SetCursor;
Property Enabled: Boolean read FEnabled write SetEnabled;
Property Font: TFont read FFont write SetFont;
Property hWnd: HWND read Gethwnd;
Property Cancel: Boolean read FCancel write FCancel;
Property Caption: string read GetCaption write SetCaption;
Property Default: Boolean read FDefault write SetDefault;
Property Parent: TControlGroup read FParent write SetParent;
Property TabIndex: Integer read FTabIndex write SetTabIndex;
Property TabStop: Boolean read FTabstop write SetTabstop;
Property Visible: Boolean read FVisible write Setvisible;
Property OnClick: ENotify read FOnClick write FOnClick;
Property OnGotFocus: ENotify read FOnGotFocus write FOnGotFocus;
Property OnKeyDown: EKey read FOnKeyDown write FOnKeyDown;
Property OnKeyPress: EKeyPress read FOnKeyPress write FOnKeyPress;
Property OnKeyUp: EKey read FOnKeyUp write FOnKeyUp;
Property OnLostFocus: ENotify read FOnLostFocus write OnLostFocus;
constructor Create(AOwner: TGroup);
procedure SetFocus; virtual; procedure Refresh; virtual;
The above is how the declaration of a button object might look (it is a flattening of the actual properties and methods of a button, most of the which are actually inherited from TWinControl and TControl). Let's assume that we have a window than contains a button called "OkButton". Here's how to change its text to "Close":
OkButton.Caption := '&Close';
Here's how to change the button font to Arial - 18 points:
OkButton.Font.Name :_ 'Arial';
OkButton.Font.Size := 18;
Hiding the button is equally as simple:
OkButton.Visible := False;
The On... properties (e.g. OnClick) are the event properties. As you can see, a user can have code executed on keyboard events, on getting or losing the focus, or when the button is "clicked".
A form is a window that contains visual and non-visual components and is the primary focus of application construction in the new IDE. Components are dragged and dropped from a palette onto a form. The form is then filed to a resource file and appended to the EXE when the user requests a MAKE.. The resource file contains the initial state of the application and property information for each component.
"Non-visual components" are those which do not have a visual representation at runtime (database tables, timers, etc.). As with their visual counterparts, their icons are added to a form by drag and drop and corresponding instance variables are generated in the class declaration.
VCL consists of four units. CLASSES contains TComponent, filing support and a variety of miscellaneous types (many of which have counterparts in BP7's OBJECTS unit). CONTROLS contains TForm and the encapsulations of Windows controls (TButton, TEdit, TListbox, etc.). GRAPHICS contains the encapsulation of GDI (TCanvas, TPen, TBrush, TFont, etc.). MENUS contains the TMenu and some helper functions.
Download Delphi 10 now!
Webinars on demand!
More social media choices:
Delphi on Google+
@RADTools on Twitter
Server Response from: ETNASC03