This unit contains definition of XForm, representing form window,
and XControl, which is a base class for all visual controls,
placing onto XForm. As You seen in XApplets unit, where
detailed explanation of creating new XCL
project is made, XForm allow to start programming from about 30 Kbytes of executable
(whereas in VCL we started from about 276 Kbytes in D4 and from about 176 Kbytes in D3). I
remind You of why it is so. XForm is not derived from TPersistent and it has no abilities
to read its initial state from executable. Moreovere, it does not include any capability
what is not necessary and can be not used in final applet. Such additional capabilities
are implementing as additional modules (XFormAutoSize, XAligner and so on) or sometimes by
deriving new class from XForm and overriding its methods (XMDIForm, XMDIChild).
XForm itself is a descender of XWindow
and mainly adds to it capability of handling some additional messages (WM_PAINT, WM_ERASE,
WM_SIZE - overriden) and generates some events (or just stores its to make possible to
generate its in add-on modules).
Here You can read all about XForm class, defined in XForms.pas unit.
And using this reference, You can look at XControl definition
(I decided to separate these two documents because every of each is very important).
XForm <= XWindow <= XVisual <= XClass <= TObject
XForm properties:
- represents current focused control. Even if control is not windowed, it
therefore can be "focused" in XCL if its CanFocus function returns True. In that
case it receives key input and can change its appearance if this is provided in its
PaintTo method. To move focus to another control of form, either assign True to control's property Focused, or assign it to CurrentControl property of its parent form. If form looses focus, property CurrentControl is not changing. It is possible also assign nil to CurrentControl (saying that there is no focused control in form now). |
- control, which captured mouse (can be non-windowed). Used in XMouseEvents.pas add-on to redirect all mouse events to control, which was the initiator of capturing control by its parent form. |
- space between client edge and controls, and for controls with children also
space between client edge and children controls. Default is 4. This value is used by
add-on modules (XAligner, XFormAutoSizer, XControlAutoPlacer classes) while executing to
perform its tasks. I would like mark here that XForm can not be scaled or scrolled as TForm in VCL. Therefore, with such add-on modules XForm can look even better than TForm, independantly of screen resolution, set of installed fonts and other factors, which usually confuse Delphi. |
- Default is True. If False, XFormAutoSizer object is not called. You may set
AutoSize to False after placing all controls on form and showing it to prevent further
autosizing when appearance of some elements (labels, buttons and so on) is changing. Anyway, autosizing is performing only in case when You use XFormAutoSizer object (by calling UseFormAutosize). |
- Default is True. If False, XAligner object is not called for form. |
Properties, inherited from XWindow:
Properties, inherited from XVisual:
Properties, inherited from XClass:
XForm methods:
- redirects searching of control at the given position to inherited function
ElementAtPos( X, Y, IgnoreDisabled ) : XVisual. But ControlAtPos is returning nil, if
position is overlapped by visual element which is not an XControl descendant. This function is using mainly in add-on unit XMouseEvents.pas to redirect mouse events to controls of XForm. And You may also use this function for your own purposes. |
- redirects operation to event handler OnGotoControl of GlobalFormsManager object. This event is assigned only if add-on unit XKeyboard.pas is used, to calculate control which has to receive focus after pressing some keys (Tab, Shift-Tab, Right, Left, Up, Down, PgUp, PgDn, Home, End). |
- redirects operation to event handler On_GetAvailableClientRect of GlobalFormsManager object if this event is assigned. If not, it returns the total ClientRect. This function is used usually to align control 'alClient' while realigning, so this event is handled by add-on unit XAligns.pas if it is used in your applet. |
Methods, inherited from XWindow:
Methods, inherited from XVisual:
Methods inherited from XClass:
Events of XForm object:
- these events above are only stored here. Mouse events are handled only
in case when unit XMouseEvents.pas is used (by calling UseStdMouse). And then global
object FormsStdMouseEvents is attaching to On_FormMessage event of GlobalFormsManager and
handling mouse events, redirects it to controls of form or calls form's itself mouse
events OnMouseMove, OnMouseDown, OnMouseUp. Similarly that, keyboard events are handled only when unit XKeyboardEvents.pas is used (by call UseKeyboard). And in that case global object FormsStdKeyEvents is attaching to On_MouseMessage event of GlobalFormsManager and handling keyboard events. It supports passing key messages to "focused" control (if focusing is emulated) or if there are no focused controls or key was not accepted, tabulating between controls with keys Tab,Shift+Tab, arrow keys etc. To make possible attaching more than one handler to the same event On_FormMessage, the technique of joining by chains is applied (saving old handler when joining and calling it if event was not handled by given handler). |
Event, iherited from XWindow object:
XEventAccept = procedure( Sender : TObject; var Accept : Boolean
); - use this event to decide if window can be closed in response to Windows message WM_CLOSE. If not, set Accept to False before return. |
Other definitions of XForms.pas unit:
This class is very important itself and a separate article is devoted to it. It is placed in the same unit with XForm declaration only to make possible its more close interaction (as You know, classes of the same unit have full access to all, even private, fields of each other). |
Also interface class XFormsManager is declared here and single variable GlobalFormsManager of this type. This is derived from TObject and has no methods and properties, but has events:
- stores event handler to make possible drawing of focus rect for focusable self-painting controls using XFocusDrawing.pas add-on unit. Called by control, which needs in focus rectangle, received by handler, installed by FocusPainter global object if this last is used (by calling UseFocusPainter). |
- stores event handler to make possible interception of all messages recived by XForm before its achive the recipient. This event MUST be assigned by chains (i.e. previous handler must be saved in a variable and recalled through if message was not handled). Called by XForm, and used in many other modules (e.g. in add-ons XMouseEvents.pas and XKeyboardEvents.pas). |
- stores event handler to make possible tabulating between controls using
keyboard. If add-on XKeyboardEvents.pas is used (by callig UseStdKeyboard procedure),
following keys are available: (Home, End, Right=Down=PageDown=Tab,
Lef=Up=PageUp=Shift+Tab). This event is called by XForm.GotoControl(VirtKey) procedure, which does nothing itself. |
- stores event handler to make possible autosizing forms and controls. Called by XForm, can receive and handle by global object FormAutosizer (if it is used by call UseFormAutosizer ). |
- stores event handler to make possible calculating of rest of client rect after all left-right and top-bottom aligns (to align alClient-aligned control). Called in function XForm.GetAvailableClientRect, received and handled by global object Aligner (if it is used by calling UseAligner). |
- as above, stores event handler to make possible realigning of controls (which
Align property is not alNone), when form is resizing. Called by XForm in WndProc on
message WM_SIZE, and received and handled by global object Aligner. Even if You use Align for some objects, but do not use alClient alignment, and do not use FormAutoSizer, You may try not to use Aligner. |
It is possible to use XForm object directly, without deriving new
class for form. But I think that it is a good tradition to do so like in Delphi VCL.
Declare controls which You need on form as internal fields of your class derived from
XForm, and override constructor, placing there constructing operators of all child
controls (take in attention, that creation order of controls is also the tab order, so
create focusable controls in the same order as tab order).
Overriding of WndProc procedure is the best way to handle additional
messages, not handled by XForm (and its ancestor XWindow), or to override some of its. (In
XCL You must not use procedures with 'message;'
directive to handle messages).
There are no properties such as FormStyle similar those in VCL TForm.
Instead, to change appearance of form's frame and caption, use Style, ExStyle and ClsStyle
properties. For example, to remove minimize and maximize boxes from caption of form,
write:
with MyForm do Style := Style and not(WS_MINIMIZEBOX or WS_MAXIMIZEBOX); |
Or, to disable close box in caption, write:
with MyForm do ClsStyle := ClsStyle or CS_NOCLOSE; |
To prevent resizing of window by mouse, reset flag WS_THICKFRAME of Style property:
with MyForm do Style := Style and not WS_THICKFRAME; |
Also remember, that first created form becomes "main" window of applet. Minimizing of main window is equal to minimizing the applet, and when main window is closed, applet is fininshing.
When You are designing a form, You create and place controls on it. In
Delphi VCL this process is visual, i.e. You drop controls from components palette onto
form, adjust its place, size and properties. This is very convenient, but Delphi uses
technique of storing all data needed by controls in executable in special format, and your
application is necessarily providing with code which will read and interprete such data at
run-time. And this code is not small but very-very big.
In XCL vs VCL we can not design forms visually. We have to write manually
code for creating and adjusting controls at run-time. I suppose that the best place for
this is the constructor of your form, derived from XForm. It is better to declare form's
controls as private fields of XForm descendent like in VCL.
Yes, this way is not too convenient. But remember, that in charge of it You
obtain very small executable. At least, if You sufficiently creative, it is possible to
design certain external tool application, which could be play role of design-time forms
creation environment and help to design forms visually. Such tool could give controls
definition from special text file in certain format or even from specially formatted
comments in source. (If anybody is interested in performing this task, e-mail me to discuss it).
And in table below You can see list of some of available add-ons, which can be used to include (or not used to exclude) some additional capabilities, not included into XForm itself. Remember, that to use add-on, it is not sufficient to refer onto it in uses clouse. It is necessary also make call of special initialization procedure (right column of table). The best place to do it is dpr-file. Make all such calls before creating of first form (or even before creating the Applet) - in any order You wish.
Global variable |
unit |
initialization call |
---|---|---|
Aligner | in XAligner.pas | UseAligner |
- add-on to apply aligning of controls, which Align property is not
equal to alNone. If not added, Align property is ignored during resize of forms and
controls (but can be applicable at first time when Align is just assigned).
|
||
FormAutoSizer | in XFormAutoSize.pas | UseAutoSizer |
- add-on to autosize form and its child controls having children to
fit all embedded children controls when its size is changing. Very convenient and not too
cost add-on, which allow forms to look better independently of screen resolution, fonts
installed and so on. Even more useful in cumulate with ControlAutoPlacer
add-on (see below).
|
||
FormsStdKeyEvents | in XKeyboardEvents.pas | UseKeyboard |
- add-on to handle keyboard events by self-painted (non-windowed)
controls. If not added, keyboard is ignored (excluding system keys, handling by default).
If included, also allow tabulate between focusable controls on form (using Tab, Ctrl-Tab
and arrow keys). If You are using only windowed controls, You (I hope) do not need to use this add-on to handle keyboard when such controls are intended to work with keyboard (some kinds of edit controls).
|
||
FormsStdMouseEvents | in XMouseEvents.pas | UseStdMouse |
- add-on to handle mouse events. If not added, mouse events are
ignored by XForm and not passed to self-painting controls derived from XCustomControl. If You are using only windowed controls, You (I hope) do not need to use this add-on, and such controls receives mouse messages directly.
|
||
ControlAutoPlacer | in XControlAutoPlace.pas | UseControlAutoPlacer |
- add-on to autoplace controls to avoid overlapping of them. If added,
uses Margin property to make space between controls and spacepads from
client rectangle edge (of form or control); ControlAutoPlacer usually places every new control below from bottom available one. To start placing certain control from the top of next column, assign some value to its Left property, or call Place method of control (see XControl definition). Or make it a child of certaing control, which is placed so (XPanel, XBevel, XGroup). Property VerticalOnly can be set to True, if You prefer to use other ways to place controls in several columns (method Place, or XSplitPanel as columns separator).
|
||
ResizeAntiFlicker | in XResize.pas | UseResizeAntiFlicker |
- add-on to eliminate flickering of opposite-aligned controls during
resize of x-form with mouse. Thus is, when this add-on is used, it prevents the most of
such flicks, so XCL form become really stable and looking good. There is additional property FixResize added to XControl definition. By default it is False. Make it True (when ResizeAntiFlicker is used) to skip control area from auto-scrolling. Usually it is not need to proper working of the add-on but sometimes this one can be useful. E.g., this property was used to fix scrollbars of XScrollBox and to fix drop button (which is centering its drop arrow, but this is contradictory to standard scroll strategy and could lead to additional flicks). I also recommend to set this property to True for controls, which are centering its content (text, image). |