Introduction to the Scroll Bar Control
|
|
Microsoft Windows provides a type of scroll bar,
considered a complete control in its own right:
Like all other controls, this one must be explicitly
created and is not added automatically but it provides most of the same
basic functionality as if the operating system’s automatically added scroll
bars.
Practical
Learning: Introducing Scroll Bars
|
|
- To start a new project, on the main menu, click File -> New -> VCL
Forms Application - C++Builder
- In the Object Inspector, change the following properties for the
form:
Caption: HTML Body Tag Name:
frmMain
- To save it, on the Standard toolbar, click the Save All button
- Click the New Folder button
- Set the name of the new folder as BodyTag1 and press Enter
twice
- Set the name of the unit as Formatter and click Save
- Set the name of the project as HTMLBodyTag and click Save
- In the Tool Palette, click Standard
- Click the TRadioGroup icon
and click the form
- In the Object Inspector, double-click (TStrings) from the
Items field
- Type Background and press Enter. Complete the list with
Text, Link, Active Link, and Visited Link
- Click OK
- While the RadioGroup control is still selected, on the Object
Inspector, change its properties as follows:
Caption = Body
Attributes ItemIndex = 0 Name = grpBodyAttributes
To create a scroll bar control, in the Standard section
of the Tool Palette, you can click the TScrollBar button
and click a container. The scroll bar is one of the earliest controls of the
Microsoft Windows operating system. To create it using the Win32 approach
call the CreateWindow() or the CreateWindowEx() functions and
specify the class name as SCROLLBAR. If you decide to
create it in Win32, you would need to configure all of its functionality. In
the VCL, all operations that are needed on a scroll bar control are ready to
be used.
In the VCL, a scroll bar control is implemented by a
class named TScrollBar. The TScrollBar class is derived from the
TWinControl class:
Notice that the TScrollBar class is not derived from the
TScrollingWinControl. This is because the scroll bar is not a control but
the controls that use automatic scroll bars need a mechanism to get scroll
bars when they need them.
To programmatically create a scrollbar, declare a
variable of type TScrollBar. Specify the owner of the control, which
is usually the form on which it is positioned. Also specify the parent of
the control. This is usually the form but can also be any container that is
hosting the scroll bar. This dynamic creation can be inside of an event or a
function. Here is an example:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;
}
//---------------------------------------------------------------------------
After declaring the variable, you can set its properties
as desired.
Practical
Learning: Creating a Scroll Bar
|
|
- In the Standard section of the Tool Palette, click the TScrollBar
control
and, on the form, click on the right side of the panel
- On the Object Inspector, click Name and type scrRed
Characteristics of the Scroll Bar Control
|
|
By default, when you add a scroll bar to a form (or
other container), the control assumes the horizontal position. This position
is controlled by the Kind property whose default value is
sbHorizontal. To change the direction of the control to vertical, set
this property to sbVertical. The Kind property is
controlled by the TScrollBarKind enumerator defined as follows:
enum TScrollBarKind { sbHorizontal, sbVertical };
To set this property programmatically, assign the
desired value. Here is an example:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
}
//---------------------------------------------------------------------------
PPractical
Learning: Setting the Scroll Bar Kind
|
|
- Make sure the scroll bar is still selected on the form.
On the
Object Inspector, click Kind and select sbVertical
The Minimum and Maximum Positions
|
|
When using a scroll bar, the user can navigate from one
end of the control to the other end. These are the control’s minimum and
maximum values. For a horizontal scrollbar, the minimum is the far left
position that the bar can assume. For a vertical scrollbar, the minimum is
the most top position. The maxima are the opposites. These two values are
controlled by the Min and Max properties.
By default, a newly added scroll bar allows scrolling
from 0 to 100. To change these values at design time, type an integer number
for each field in the Object Inspector. The lowest number the Min
property can have is –2147483648 and the highest number for Max would
be 2147483647.
Here is an example of programming setting the maximum
value:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;
Scroller->Left = 24;
Scroller->Width = 228;
Scroller->Top = 35;
Scroller->Kind = sbVertical;
Scroller->Max = 1500;
}
//---------------------------------------------------------------------------
Practical
Learning: Setting the Maximum Value
|
|
- Make sure the scroll bar is still selected on the form.
On the
Object Inspector, click Max and type 255
The Position of a Scroll Bar
|
|
The primary technique the user applies to a scroll bar
is to click (or press, on a touch screen) one of the arrows at the ends of
the control. As the bar slides inside of the control, it assumes an integer
position from Min to Max. At design time,
you can use the Position property to set the position that
the scroll bar would assume when the form opens. If you visually set the
Position to a value less than the Min, the Object
Inspector would restore it to the Min value. If you visually set a
Position greater than the Max, the Object Inspector
would assign it the Max value.
To programmatically set the position of the bar, assign
the desired value, which must be between Min and Max, to the
Position property. At run time, when the user scrolls the
control, you can find the position of the thumb by getting the value of the
Position property. Here is an example:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1->Caption = ScrollBar1->Position;
Label2->Caption = ScrollBar2->Position;
}
//---------------------------------------------------------------------------
|
|
Practical
Learning: Setting and Using the Position
|
|
- Make sure the scroll bar is still selected on the form.
On the
Object Inspector, click Position, type 255, and press Enter
- Complete the design of the form as follows:
|
Control |
Name |
Text/Caption |
Other Properties |
Form |
frmMain |
Body Tag Formatter |
BorderStyle: bsDialog Position:
poScreenCenter |
RadioGroup |
grpBodyAttributes |
Body Attributes |
ItemIndex: 0 |
Edit |
edtBackground |
#000000 |
|
Edit |
edtText |
#0000FF |
|
Edit |
edtLink |
#FF0000 |
|
Edit |
edtALink |
#008000 |
|
Edit |
edtVLink |
#800000 |
|
Label |
|
Preview ___________ |
|
Panel |
pnlPreview |
|
Color: clWhite |
Label |
|
R |
|
ScrollBar |
scrRed |
|
Kind: sbVertical Max: 255
Position: 255 |
Label |
|
G |
|
ScrollBar |
scrGreen |
|
Kind: sbVertical Max: 255 Value:
255 |
Label |
|
B |
|
ScrollBar |
scrBlue |
|
Kind: sbVertical Max: 255 Value:
255 |
BitBtn |
|
&Close |
Kind: bkClose |
Memo |
mmoPreview |
|
Lines: Nothing |
Edit |
edtPreviewText |
Body tag formatter and colorizer |
Font->Color: clBlue ReadOnly: true |
Edit |
edtPreviewLink |
Sample text as link |
Font->Color: clRed ReadOnly: true |
Edit |
edtPreviewALink |
Active link that is being visited |
Font->Color: clGreen ReadOnly: true |
Edit |
edtPreviewVLink |
This link has been already been visited |
Font->Color: clMaroon ReadOnly: true |
GroupBox |
|
Hexadecimal |
|
Label |
|
Red: |
|
Edit |
edtHexaRed |
00 |
|
Label |
|
Green: |
|
Edit |
edtHexaGreen |
00 |
|
Label |
|
Blue: |
|
Edit |
edtHexaBlue |
00 |
|
GroupBox |
|
Numeric |
|
Label |
|
Red: |
|
Edit |
edtRed |
00 |
|
Label |
|
Green: |
|
Edit |
edtGreen |
00 |
|
Label |
|
Blue: |
|
Edit |
edtBlue |
00 |
|
BitBtn |
btnCopy |
Cop&y |
|
Edit |
edtBody |
<body bgcolor="#FFFFFF"
text="#0000FF" link="#FF0000" alink="#008000"
vlink="#800000"> |
|
- Access each edit box in the lower-left memo and set its BorderStyle
property to bsNone
- In the header file of the form, declare the following private
variables:
private: // User declarations
AnsiString HexBG, HexText, HexLink, HexALink, HexVLink;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
- In the ClassExplorer window, right-click TForm1 and click New
Method...
- Set the method options as follows:
Method Name: ApplyColor
Function Result: void Visibility: private Directives: __fastcall
- Click OK
- Implement the method as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmMain::ApplyColor()
{
//TODO: Add your source code here
// Retrieve the current hexadecimal colors from their Edit controls
HexBG = edtBackground->Text;
HexText = edtText->Text;
HexLink = edtLink->Text;
HexALink = edtALink->Text;
HexVLink = edtVLink->Text;
// Get the integral position of each ScrollBar control
int Red = 255 - scrRed->Position;
int Green = 255 - scrGreen->Position;
int Blue = 255 - scrBlue->Position;
// Display the position of each ScrollBar
// in its corresponding Edit control
edtRed->Text = Red;
edtGreen->Text = Green;
edtBlue->Text = Blue;
// Get the hexadecimal equivalent of each ScrollBar control
AnsiString HexRed = IntToHex(Red, 2);
AnsiString HexGreen = IntToHex(Green, 2);
AnsiString HexBlue = IntToHex(Blue, 2);
// Display the hexadecimal value in the appropriate Edit controls
edtHexaRed->Text = HexRed;
edtHexaGreen->Text = HexGreen;
edtHexaBlue->Text = HexBlue;
// Change the color of the Preview panel
// according to the values of the ScrollBar positions
pnlPreview->Color = TColor( RGB(Red, Green, Blue) );
// Get the position of each ScrollBar control
// Create a hexadecimal color starting with #
// And display the color in the appropriate Edit control
switch( grpBodyAttributes->ItemIndex )
{
case 0:
edtBackground->Text = "#" +
IntToHex(Red, 2) +
IntToHex(Green, 2) +
IntToHex(Blue, 2);
mmoPreview->Color = pnlPreview->Color;
edtPreviewText->Color = pnlPreview->Color;
edtPreviewLink->Color = pnlPreview->Color;
edtPreviewALink->Color = pnlPreview->Color;
edtPreviewVLink->Color = pnlPreview->Color;
HexBG = edtBackground->Text;
break;
case 1:
edtText->Text = "#" +
IntToHex(Red, 2) +
IntToHex(Green, 2) +
IntToHex(Blue, 2);
edtPreviewText->Font->Color = TColor( RGB(Red, Green, Blue) );
HexText = edtText->Text;
break;
case 2:
edtLink->Text = "#" +
IntToHex(Red, 2) +
IntToHex(Green, 2) +
IntToHex(Blue, 2);
edtPreviewLink->Font->Color = TColor( RGB(Red, Green, Blue) );
HexLink = edtLink->Text;
break;
case 3:
edtALink->Text = "#" +
IntToHex(Red, 2) +
IntToHex(Green, 2) +
IntToHex(Blue, 2);
edtPreviewALink->Font->Color = TColor( RGB(Red, Green, Blue) );
HexALink = edtALink->Text;
break;
case 4:
edtVLink->Text = "#" +
IntToHex(Red, 2) +
IntToHex(Green, 2) +
IntToHex(Blue, 2);
edtPreviewVLink->Font->Color = TColor( RGB(Red, Green, Blue) );
HexVLink = edtVLink->Text;
break;
}
// Update the contents of the bottom Edit control
edtBody->Text = "<body bgcolor=\"" +
HexBG + L"\" text=\"" +
HexText + L"\" link=\"" +
HexLink + L"\" alink=\"" +
HexALink + L"\" vlink=\"" +
HexVLink + L"\">";
}
//---------------------------------------------------------------------------
- Save all
- Press F12 to return to the form
When the user clicks (or presses) an arrow of a scroll
bar, the bar slides one unit. This unit is called SmallChange and is
set to 1 by default. If you want the bar to slide more than one unit, change
the SmallChange property to an integer value between Min
and Max. The higher the value, the faster the sliding would
occur because the bar would jump by SmallChange units. Here is an
example of programming setting the small change:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;
Scroller->Left = 24;
Scroller->Width = 228;
Scroller->Top = 35;
Scroller->Kind = sbVertical;
Scroller->Max = 1500;
Scroller->Position = 780;
Scroller->SmallChange = 5;
}
//---------------------------------------------------------------------------
There are two main ways the user can scroll faster using
scroll bars: by pressing either page buttons or by clicking (or manually
dragging) the scrolling region. The amount covered using this technique is
controlled by the LargeChange property. Once again, the user can
scroll only between Min and Max. This
means that you can set this value only to an integer from Min
to Max.
To find the scrolling amount, the compiler would divide
the actual scrolling range (the difference between the Max
and Min) by the LargeChange value. When the user
clicks (or touches) in the scrolling region or presses the Page Up or Page
Down keys, the bar would jump by LargeChange up to the scrolling
amount value. You can change the LargeChange property
programmatically as follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
ScrollBar1->Min = -122;
ScrollBar1->Max = 240;
ScrollBar1->Position = 38;
ScrollBar1->SmallChange = 4;
ScrollBar1->LargeChange = 20;
}
//---------------------------------------------------------------------------
The bar inside the scroll region has a size relative to
the Min and Max values. By default, it is
a square of the approximate size of the arrow buttons. This size of the bar
is controlled by the PageSize property. Approximately, this
represents the percentage of the scrolling range (the difference between the
Max and Min). You can change this value at
design time in the Object Inspector, by an integer value between Min
and Max. To change it programmatically, assign the desired integer to
the PageSize property. Here is an example:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;
Scroller->Left = 24;
Scroller->Width = 228;
Scroller->Top = 35;
Scroller->Kind = sbVertical;
Scroller->Max = 1500;
Scroller->Position = 780;
Scroller->SmallChange = 5;
Scroller->LargeChange = 150;
Scroller->PageSize = 250;
Scroller->SetParams(780, 0, 1500);
}
//---------------------------------------------------------------------------
The most fundament event of a scrollbar occurs when the
bar slides. This happens when:
- The user clicks one of the arrows (or manually presses one of the
arrows on a touch screen)
- The user presses one of the arrow keys
- The user presses Page Up or Page Down
Every time the user performs one of these actions, the
position of the bar changes unless it is already at one of the extremes.
When the position of the bar has changed, a message is sent to the operating
system that the bar has changed its position. Using the OnChange event of
the scrollbar, you can tell the compiler what to do. Fundamentally you can
find out the new position and display it on a label. Here is an example:
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
Label1->Caption = ScrollBar1->Position;
}
//---------------------------------------------------------------------------
The OnScroll event occurs when the user scrolls the bar.
This event is appropriate if or when you want to capture the specific action
that caused the scrolling action. These actions relate to the TScrollCode
enumerator:
enum TScrollCode { scLineUp, scLineDown, scPageUp, scPageDown,
scPosition, scTrack, scTop, scBottom, scEndScroll };
The syntax of the OnScroll event is:
void __fastcall (__closure *TScrollEvent)(System::TObject* Sender,
TScrollCode ScrollCode,
int &ScrollPos);
Practical
Learning: Using the Scroll Bar Events
|
|
- Double-click the left scroll bar
- Press F12 to return to the form
- Double-click the middle scroll bar
- Press F12 to return to the form
- Double-click the right scroll bar
- Implement their OnChange events as follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::scrRedChange(TObject *Sender)
{
ApplyColor();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::scrGreenChange(TObject *Sender)
{
ApplyColor();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::scrBlueChange(TObject *Sender)
{
ApplyColor();
}
//---------------------------------------------------------------------------
- Test the application and return to your programming environment
- When the user clicks a radio button from the Body Attributes group
box, we need to display its color on the Preview panel. When a
particular button is clicked, we will retrieve the color of its font
from the Body text box, translate that color into red, green, and blue
values, and then use those values to automatically update the scroll
bars and the edit boxes. While we are at it, we also need to update the
corresponding text box in the Body Attributes group box. Since this
functionality will be used by all radio buttons in the group, we will
use a global function to which we can pass two variables.
When the
user clicks a particular radio button, that button is represented by a
text box in the lower-left Body section. We need to get the color of
that edit box and pass it to our function. Since the clicked radio
button has a corresponding text box in the Body Attributes group box, we
need to change/update that value with the hexadecimal value of the first
argument. Therefore, we will pass a String argument to our function.
In the header file of the form, declare a method as follows:
private: // User declarations
AnsiString HexBG, HexText, HexLink, HexALink, HexVLink;
void __fastcall ApplyColor();
void __fastcall ClickOption(TColor Clr, AnsiString Result);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
- In the source code of the form, implement the function as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmMain::ClickOption(TColor Clr, AnsiString Result)
{
long lngColor;
int Red, Green, Blue;
pnlPreview->Color = Clr;
lngColor = Clr;
Red = 255 - (lngColor % 256);
Green = 255 - ((lngColor / 256) % 256);
Blue = 255 - (lngColor / 65536);
scrRed->Position = Red;
scrGreen->Position = Green;
scrBlue->Position = Blue;
edtRed->Text = Red;
edtGreen->Text = Green;
edtBlue->Text = Blue;
edtHexaRed->Text = IntToHex(Red, 2);
edtHexaGreen->Text = IntToHex(Green, 2);
edtHexaBlue->Text = IntToHex(Blue, 2);
Result = "#" + IntToHex(Red, 2) + IntToHex(Green, 2) + IntToHex(Blue, 2);
}
//---------------------------------------------------------------------------
- Double-click the grpBodyAttributes RadioGroup control and implement
its OnClick as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmMain::grpBodyAttributesClick(TObject *Sender)
{
// If the user clicks a button from the RadioGroup control
// find out what button the user clicked
// set color of the panel to that of the radio button that was clicked
TColor BGColor = mmoPreview->Color;
mmoPreview->Color = BGColor;
edtPreviewText->Color = BGColor;
edtPreviewLink->Color = BGColor;
edtPreviewALink->Color = BGColor;
edtPreviewVLink->Color = BGColor;
switch(grpBodyAttributes->ItemIndex)
{
case 0:
ClickOption(mmoPreview->Color, edtBackground->Text);
HexBG = edtBackground->Text;
break;
case 1:
ClickOption(edtPreviewText->Font->Color, edtText->Text);
HexText = edtText->Text;
break;
case 2:
ClickOption(edtPreviewLink->Font->Color, edtLink->Text);
HexLink = edtLink->Text;
break;
case 3:
ClickOption(edtPreviewALink->Font->Color, edtALink->Text);
HexALink = edtALink->Text;
break;
case 4:
ClickOption(edtPreviewVLink->Font->Color, edtVLink->Text);
HexVLink = edtVLink->Text;
break;
}
}
//---------------------------------------------------------------------------
- Save and test the application then return to your programming
environment
- Double-click the Copy button and implement it as follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCopyClick(TObject *Sender)
{
edtBody->SelectAll();
edtBody->CopyToClipboard();
}
//---------------------------------------------------------------------------
- Save all
- Press F9 to test the application
|
|