Parent Controls
|
The Window’s Desktop
|
When you start the computer, the first object the
operating system creates is the desktop window. This is a wide rectangular
area that covers the entire monitor screen. Based on the settings of the
Control Panel, the operating system uses either a color or a picture (a
bitmap) to fill the window. Once the desktop is ready, other objects or
controls can be placed on it.
|
To provide some information about the desktop, the VCL
is equipped with the TScreen class. This allows you to get such
details as the screen dimensions (its width and height), the form that is
displaying on the screen, the type of keyboard being used, etc. To make
the screen information available to you any time, every application
declares a TScreen global variable so you do not have to declare
your own.
Alternatively, to get access to the desktop, you can
call the GetDesktopWindow() function. Its syntax is:
HWND GetDesktopWindow(VOID);
This function simply returns a handle to the desktop
window. This handle can give some information about the desktop such as its
size, etc.
|
Because GetDesktopWindow() is just a function, it
only produces a handle to the desktop. If you want to perform other
processing on the desktop, you should use the TScreen class members
or you can use some of the Win32 library functions such as
SystemParametersInfo().
A control is referred to as container if it can host
other controls. While the desktop is the biggest container of the computer,
to develop your applications, you will use your own controls that can act as
parent to other controls. The VCL provides various objects that can play
this role. The list includes the form, the frame, the group box, the panel,
the scroll box, the control bar, the tab control, the page control, the
status bar, the toolbar, the cool bar, the page scroller, the tabbed
notebook, etc. The list is impressive and these parent controls are usually
used for different purposes. In fact, the only real characteristic they
share is their ability to host other controls.
Except for the form (and consequently the dialog box),
most, if not all, of the other containers must be hosted by a form.
Therefore, after starting a project or once you get a form, you can place a
control container on it (the form). Once placed on a form, these parent
windows can host their own controls. Therefore, to use a container, you can
either position your control on the form, in which case the form would act
as the parent, or you can first select one of the containers, place it on a
form, and then add other controls to it.
As seen with child controls, except for the desktop
window, every visual object either on the screen or in your application must
be located. The location of an object depends on its parent and some other
considerations.
The main object or frame of an application, which is
usually the first form of a project, when it appears on the screen, is
located with regards to the screen. Such a form is located on a Cartesian
coordinate system whose origin is on the top-left corner of the screen. The
horizontal axis moves from the left border to the right. The vertical axis
moves from the top border down.
The distance from the left border of the screen to the
form is the Left measurement. The distance from the top border of the screen
to the top border of the form is its Top measurement.
This can be illustrated as follows:
The above illustration shows a form positioned on a
monitor. The desktop acts as the parent window of the form. In the same way,
if you place a control on a container, the control is located with regards
to its parent, not based on the screen. As seen previously, in such a case,
the origin of the coordinate system is located on the top-left corner of the
parent window. The distance from the left border of the parent window to the
left border of the control is the control’s Left property.
The distance from the top border of the parent window to the top border of
the control is the control’s Top property. Here is an
example in which a child control positioned inside a another control that
acts as its parent (that container itself is a child to the form):
In the same way, an object positioned on a parent can be
seen only if its dimensions are confined to the body of the parent.
To manage the display of visible windows, each parent
provides a section called the client area. For the desktop screen, the
client area is the whole screen. For a form, the client area is the body of
the form without the title bar. Most other containers provide their whole
body as the client area:
The desktop window provides a rectangular area that it
can use to display the computer’s applications. This area is also used to
host other objects. Although an object’s borders can span beyond the borders
of the desktop, only the area of an object covered by the desktop can be
seen. Here is an example of a window whose right side cannot be seen:
The client area is a rectangle primarily used for its
location and dimensions. To get the values of the shape that compose the
client area, you have various options and considerations. For example, to
get the area that represents the desktop, which would let you know how much
real estate is available for your application, you can call the
TScreen::DesktopRect member variable. Here is an example:
The TScreen class also provides such aspects as
the location and width of the desktop in the forms of DesktopLeft,
DesktopTop, DesktopWidth, and DesktopHeight.
The DesktopRect and the DesktopHeight
provide the height of the desktop including the task bar. If you want to
know the actual area that is made available on the desktop, which does not
include the taskbar, use the TScreen::WorkAreaRect or the
TScreen::WorkAreaHeight respectively.
Otherwise, you can also get the
left, the top, and width measures using the WorkAreaLeft, the
WorkAreaTop, and the WorkAreaWidth respectively. In reality, the
WorkArea_ measures can be more useful if your application takes
advantage of more than one monitor. In this case the WorkArea_
measures provide information about the desktop of the primary monitor.
Besides the TScreen class, you can use the
GetDesktopWindow() function to get a handle to the desktop and find the
dimensions of that window. Here is an example that displays the screen
resolution:
//--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { TRect recto; HWND hWndDesktop = GetDesktopWindow(); GetWindowRect(hWndDesktop, &recto); Caption = "Width: " + IntToStr(recto.Width()) + " Height: " + IntToStr(recto.Height()); } //---------------------------------------------------------------------------
It is important to know where the origin of a control is
located. During control design, we saw that, when a container is selected
and you double-click a visual control on the Tool Palette, the new control
would be added to the container. On the other hand, if you have a container
that is positioned on the form but the container, or any specific container,
is not selected, if you double-click a control on the Tool Palette, the
control would be added to the form even though the new control may be
positioned on a container. In this case, the form would become the parent of
the new control. Therefore, in order to do anything related to the location
and/or dimensions of a control, you must know the coordinate of the origin
used as the basis for its location and dimensions.
Because only a parent can host some controls, it holds
an origin and makes it available to its children. To get the origin of a
container, call the TControl::ClientOrigin property.
To get the location and dimensions of any window that
serves as parent, you can call the TControl::ClientRect property. A
control hosted by a container can be displayed only inside its parent. If
the control’s left or top measures are negative, its left or top borders
respectively would be hidden under the left or top sides of the parent. If
the dimensions of the child control span beyond the dimensions of the parent
window, the control’s right or bottom border will be hidden. We will see
that some controls cannot allow their child or children to expand the client
area and some other controls can display scroll bars so the hidden parts can
be navigated to.
The ClientRect property mainly provides only the
width and the height of a client area since the left and the top measures
are set to 0 each as the origin (0, 0) is the base. Alternatively, you can
get the width of a control using the TControl::ClientWidth and you
can get the height of the control using the TControl::ClientHeight
properties.
|
Besides the Top, the Left,
and the Position properties, you can also control the
position of a control in the client area of its container using the
Align property. This property and its values have the following
effects:
In case of a (regular) form, the Align property
controls how the form is positioned with respect to the monitor's screen.
When it comes to a form, the Align property should be used only if you have
a good reason. For example, to maximize a form at startup, you can set its
Align property to alClient, which you can also accomplish using the
WindowSate property. The default value of the Align property is
alNone, which means the appearance of the form is left to other
properties. We will explore the Align property when we get to the controls
but remember that it is also available to the form.
The user of your application will have the ability to
resize the form when using your application. If the form is not a classic
dialog box, by default, the user can resize it to any dimensions allowed by
the screen resolution; the minimum is to have the system buttons and just a
tiny part of the caption.
You can set the minimum height, the maximum height, the
minimum width, and the maximum width allowed on the control if the control
gets resized. This property is controlled by the Constraints
property. The Constraints property is a TSizeConstraints
class, which is inherited from the TPersistent class. Although it is
a class, you should never declare it. The control that uses a Constraints
property will create and initialize an instance of the class. The
MinWidth, MinHeight, MaxWidth, and MaxHeight values
are integers you can set using the keyboard. To set the constraints of a
control that has this property, click the + button of the Constraints field
in the Object Inspector, click the field desired and type an integer value.
To programmatically control the constraints of a control, call the
TSizeConstraints::Property and type the desired value. In the following
example, when the user tries to resize the Form1 form, the minimum and
maximum dimensions of the form are already set and would not change:
//--------------------------------------------------------------------------- void __fastcall TForm1::FormResize(TObject *Sender) { Form1->Constraints->MinHeight = 300; Form1->Constraints->MinWidth = 500; Form1->Constraints->MaxHeight = 400; Form1->Constraints->MaxWidth = 565; } //---------------------------------------------------------------------------
If you position a (visual) control on a form, if the
control is positioned on the top left section of the form, when the user
resizes the form, the control’s position would appear static, it would not
move. This could be a concern if the control is positioned on the right, the
bottom or the lower right section of the form. When the user resizes the
form, the control’s position would not be updated. Sometimes you will want
the control to have the same location and/or distance with regard to the
bottom, the right, and/or the lower right corner of the form. This ability
is controlled by the Anchors property.
The anchoring of a control to its parent or host
container is controlled using a set property derived from the TAnchors
enumerator. By default, when you add a control to a form, it is "glued" to
the top left corner of its container. Since this property is a Set, you can
set the control’s position with regards to its container’s right and bottom
borders. The possible values of the Anchors property are:
One of the most useful actions performed on a control
consists of involving it in drag and drop operations. Some controls can
serve as the source or the destination on such an operation. Drag and drop
operations are performed using specific properties of child controls
associated with their parents.
The DockSite property uses a Boolean value to
indicate that the control can serve as the host for a drag’n’drop operation.
The DragKind property specifies how the control participates in the
drag’n’drop operation. If the control serves as a docking host, you should
set its DragKind property to dkDock. By contrast, if the
control will itself be used when dragging, set its DragKind property
to dkDrag.
If a control is “draggable”, you can use the DragMode
property to specify how the dragging operation on the control would be
initiated. If you want the dragging operation to be possible when the user
clicks the control, set its DragMode property to dmAutomatic.
Otherwise, some controls, depending on the result you are trying to achieve,
should be available for dragging only depending on an intermediary action.
In such a case, you can write your program so that the dragging operation on
a control would be available only after the application or another event or
control has called the TControl::BeginDrag() method. In this case,
you can set the DragMode property to dmManual.
|
No comments:
Post a Comment