
XVisuals.pas
unit
This unit contains definition of the base class for all XCL controls
and windows - XVisual. It is a descender of XClass and adds
to it a set of properties and methods peculiar to windows-similar visual elements (forms
and controls) such as position, size, visibility, enabling, painting and so on.
Yes, certainly it would be possible to create a single root class,
uniting ability to have parent-childs relations and window-similar visibility in one, but
I found that ability to have childs and become a parent is important itself. And this
allow to improve any poor pascal object just by changing its ancestor from TObject to XClass and to obtain as a result object that is destroying
automatically when its parent is destroying. This last ability is similar to TComponent
autodestroying capability.
Be remember, that in contrast to VCL, where base class for all objects
is TPersistent, XCL objects do not provide capability of reading its original state from
form definition. This allow not to link stream support modules, input/output routines
needed to read data from executable and recognize it and do not create form definition
blocks in executable. As a result, application made with XCL (called as APPLETS)
leaves its size dramatically small.
Disadvantages of this are evident: inconvenience for programmers
because it is necessary to place controls on forms only at run time. Programming in XCL,
at design time developer can now work only with pascal code. No ObjectInspector, no double
click on event to create event handler, no components palette and so on. But all this is
generously repaid by extremely small size of end applet, and You do not ever need to
distribute bpl- or dpl-files to do it!
XVisual <= XClass <= TObject
XVisual properties:
Enabled : Boolean;
- Default is True. Set it to False to disable focusing (and keyboard input) and
all mouse events for this object. |
Visible : Boolean;
- Default is True. Set it to False to void painting of object (form, control) and
taking its rectangle into account while autoplacing, autosizing and aligning controls,
handling mouse and keyboard events and so on. |
BoundsRect : TRect;
- Use it to change position and size of visual object by the single operation to
avoid flicks (instead of consequence assignments of values to follow Left, Top, Width and
Height properties). |
- Left : Integer;
- Top : Integer;
- Width : Integer;
- Height : Integer;
Position : TPoint;
- Use it to change position of visual object with a single operation instead
assigning values to Left and Top properties to reduce resize and realign operations and to
avoid flicks. |
Color : XColor;
- This property is introduced here because the most of descenders of XVisual need
in it. But it is made protected to show it in further classes, derived from XVisual. |
ReadScrollOffset : TSize;
- Returns FScrollOffset : TSize field, which contains offset for scrollable
controls (XScrollBox and its descenders only, for other (0,0) is always returned). |
MemberCount : Integer;
Members[ Idx : Integer ] : XClass;
- Starting from XVisual, all its descenders can contain internal children visual
elements hidden. This means, that these are not enumerated with property
Children[0..ChildCount-1]. Therefore, such member controls can be accessed using property
Members[0..MemberCount-1]. Moreover, usual children and members can be accesed in single
property Members[0..MemberCount+ChildCount-1].
Therefore, it is recommended to avoid using this property and take into
consideration only usual child controls, added by developers of the project. |
Properties inherited from XClass:
- Parent : XClass;
ChildCount : Integer;
Children[ Idx : Integer ] : XClass;
XVisual methods:
function ClientRect
: TRect; virtual; abstract;
- This method is declared as abstract to prevent creating of instances of XVisual
class. Descenders of XVisual (XWindow and XControl)
are implementing this method by the way inherent in each of these two.
ClientRect usually is less or equal to BoundsRect
in size (and it is not always is originating from topleft corner of the bounding rectangle
area of visual object itself, so Left and Top can be not 0 and Right-Left and Bottom-Top
are equal to ClientWidth and ClientHeight accordingly).
If You want to get ClientWidth and ClientHeight, first call ClientRect
once to obtain client rectangle and then use Right-Left and Bottom-Top
of that rectangle as ClientWidth and ClientHeight. This is more efficient then calling
ClientRect twice (or more) and using ClientRect.Right-ClientRect.Left and
ClientRect.Bottom-ClientRect.Top . |
- function ControlRect
: TRect; virtual;
- This method is intended to return bounding rectangle from topleft corner of
client area of parent window (usually XForm). It is convenient to use it in painting,
because in XCL drawing is taking place on the canvas belonging to parent form.
- Additionally, function ControlRect uses protected field FScrollOffset : TSize to shift
control rectangle accordinately to current scroll position. This is used only in
XScrollBox (and its descenders), but allows to perform correctly painting and mouse events
for scrolled controls. |
function ElementAtPos(
X, Y : Integer; IgnoreDisabled : Boolean ) : XVisual; virtual;
- Searches visual child element taking place at the given position. Only Visible
childs are taking into consideration, and if IgnoreDisabled parameter is
set to True, then only Enabled childs can be found. If
two or more childs are overlapped, then first found is last created.
- This function is used in XForm.ControlAtPos and XControl.ControlAtPos. |
procedure MembersCreating;
- Usually called in constructor before start of creating internal controls, which
becomes 'member' and are hidden in list of normal Children[]. It is impotant to do so,
because after calling it and until MembersCreated called, all the children controls are
considered as members. This allows to avoid its from enumerating and considering in some
add-ons and to prevent some unwanted processing of those. |
procedure MembersCreated;
- Call it usually in constructor of control, which has internal ones as 'hidden'
members. Actually, this procedure resets internal boolean flag FCreating and sets
FMembersCount to ChildCount, making all created children controls as members.
- If it is necessary to create/destroy members later, it is possible to change field
FMembersCount manually, because it is made as protected. |
procedure AdjustMembers; virtual;
- Implement this procedure in descending controls to change sizes and positions of
member ones, when BoundsRect is changed or in other cases, when this method is called to
change appearance of member controls. |
procedure Invalidate;
virtual;
- Invalidates rectangle occupying by visual element in parent window (or its own
window if it is Windowed). |
function Windowed:Boolean;
virtual; abstract;
- Return True in descendent class if it has its own window. If True, function
GetWindowHandle must return window handle if it exists. |
- function ElementAtPos(
X, Y : Integer; IgnoreDisabled : Boolean ) : XVisual;
- Searches visual child element taking place at the given position. Only Visible
childs are taking into consideration, and if IgnoreDisabled parameter is
set to True, then only Enabled childs can be found. If
two or more childs are overlapped, then first found is last created.
Has no sense for XApplet. |
- function WndProc(
var Msg : TMsg ) : Integer; virtual;
- method for overriding in windowed descenders of XVisual. By default, calls
DefWndProc method (ignoring the most of messages). |
|
Following several functions and procedures made virtual to give possibility to
override it in descenders (and it was useful at least to override
GetBoundsRect/SetBoundsRect in XWindow, and SetColor can be useful for creating combined
controls which use other controls as internal elements). |
function GetEnabled:Boolean; virtual;
procedure SetEnabled(Value:Boolean); virtual;
function GetVisible:Boolean; virtual;
procedure SetVisible(Value:Boolean); virtual;
function GetBoundsRect:TRect; virtual;
procedure SetBoundsRect(Value:TRect); virtual;
procedure SetColor(Value:XColor); virtual;

procedure
DoPaint(DC:HDC; Rect:TRect); virtual;
- This is very important procedure. It must paint visual element (form, control)
onto given device context into given rectangle. XVisual implement just calls PaintChilds
and then PaintErase. If some painting need to be done between these two calls, override
DoPaint and do not call inherited one.
Take in attention, that XCustomControl overrides DoPaint, first calling PaintChildren
and then PaintTo virtual methods, so descending self-painting (not
windowed) controls have to use PaintTo to perform painting of itself. |

procedure
PaintChildren(DC:HDC; Rect:TRect); virtual;
- Paints children of visual element. It has to be called before other painting of
visual control itself, because painting of each child is finishing with excluding its area
from clipping area (so it becomes unavailable for further drawing).
Such method of painting allows to prevent flickering in most cases (if
message WM_ERASEBKGND is ignoring - and it is made so in XCL). The main requirement for
self-painting controls is: avoid setting of the pixel more then ones during single paint
operation. And all area, what was not filled during painting must be filled with
background color AFTER painting.
Override this method in descenders only if You want to change order of
painting of children (usually last created child control is painted first). |
procedure PaintChild(
DC : HDC; Rect : TRect; Idx : Integer ); virtual;
- Paints one child with given index regadless of that it can be member (i.e. Idx
is the index of Members[0..MembersCount+ChildCount-1]).
- Usually You do not need to override this method. In XCL it is overriden once only in
XScrollBox to provide perfect painting of scrolled children. |

procedure
PaintErase(DC:HDC; Rect:TRect);
- Erases the rest of (non-clipped) Rect area after painting the control (using
Color property) and excludes Rect from clipping region calling ExcludeUpdRect. |

function
GetWndUpdRgn:HRgn; virtual;
- Returns handle of updating region for device context, which was obtained (by
XForm) when WM_PAINT message was come in. Virtual method of XVisual returns 0, and it is
overriding in XForm and XControl. |

procedure
ExcludeUpdRect(DC:HDC; Rect:TRect); virtual;
- Excludes rectangle from clip area of given device context. Use this procedure
instead of calling API function ExcludeClipRect, because overridden method of XControl and
XForm additionally excludes Rect from FUpdRgn:HRgn member, allowing to avoid repainting of
other controls not overlapping clipping area. |

procedure
ExcludeUpdRgn(DC:HDC; Rgn:HRgn); virtual;
- Similar ExcludeUpdRect above. Use it instead of ExtSelectClipRgn because it does
not only call this API, but also excludes Rgn from FUpdRgn to reduce further painting. |
function GetWindowHandle:HWnd;
virtual;
- Must return window handle for Windowed visual objects (if window is not
allocated, returns 0). |
function CreateWindow
: Boolean; virtual;
- This function do nothing here excluding call of CreateChildWindows and returns
False. When new windowed XVisual descender is designing, it must override this function to
create its window. It is supposing, that before creating window it forces parent windows
to be created (if it is not so) and after creating its own window calls
CreateChildWindows. Look XWindow for more
details. |
procedure CreateChildWindows;
- calls CreateWindow for all childs of the XVisual object. |
Methods inherited from XClass:
- constructor Create(
AParent : XClass );
- destructor Destroy;
- procedure AddChild(
Child : XClass ); virtual;
- procedure DeleteChild(
Child : XClass ); virtual;
Other methods of XVisuals.pas unit:
- function GetWindowHandle(V:XVisual):HWnd;
- it just calls V.GetWindowHandle protected method and returns window handle for
windowed visual elements (forms, windowed controls). |
Tasks.
Usually You have not to descend objects directly from XVisual. To
create new control, use XControl (or XCustomControl, or XMfcControl) as a base. And to create new type of form use XForm as an ancestor. Types XVisual and XClass are taking place at the root of XCL hierarchy and You
only have to know its properties and methods which are inherited in its descenders.
Any XVisual descender can have any XClass
descender as a child. But only descenders of XVisual are taking in consideration when
children are enumerated (e.g. to find control at the given position or to decide which
object have to respond for mouse events and so on). But those childsren, which are not
XVisual-based but are XClass-based, therefore are destroyed
automatically when its parent is destroying. This is similar to relationship between TForm
and TComponent in Delphi VCL (excluding that XClass objects
can not be visual at design time).
goto XCL page
goto home
page