Scrollbars - Part 4 - The Scroll Event
You might want to see parts 1, 2, and 3 before reading this article.
So far we have a window that shows a part of an image, and have added scrollbars to the window, but the scrollbars don't yet work. In this article we'll look at the event we need to handle to make the scrollbars do something useful.
5 use Win32::GUI 1.05 qw( 6 CW_USEDEFAULT WS_CLIPCHILDREN 7 WM_HSCROLL WM_VSCROLL 8 SB_CTL SB_HORZ SB_VERT 9 SB_TOP SB_BOTTOM SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN 10 SB_LEFT SB_RIGHT SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT 11 SB_THUMBTRACK SB_THUMBPOSITION SB_ENDSCROLL 12 );
13
14 my @vert_cmds = qw(SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN 15 SB_THUMBPOSITION SB_THUMBTRACK 16 SB_TOP SB_BOTTOM 17 SB_ENDSCROLL);
18 my @horz_cmds = qw(SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT 19 SB_THUMBPOSITION SB_THUMBTRACK 20 SB_LEFT SB_RIGHT 21 SB_ENDSCROLL);
Don't worry too much about all these constants. We'll eventually see that we don't need many of them; I'll explain the important ones below, and the 2 arrays are to simplify the conversion of numeric numbers to strings for display of the messages.
23 my $mw = Win32::GUI::Window->new(
24 -title => "Scrollbar 04: View Scroll Messages",
25 -left => CW_USEDEFAULT,
26 -size => [ 400, 300 ],
27 -addstyle => WS_CLIPCHILDREN,
28 -vscroll => 1,
29 -hscroll => 1,
30 -onScroll => \&process_scroll,
31 );
The event we need to handle is the 'Scroll' event - it is triggered whenever a user does something with one of our scrollbars. I'm using a NEM-style handler here (-onScroll
), but you can (almost as) easily use an OEM-style handler (sub NAME_Scroll(...)
).
42 sub process_scroll {
43 my ( $self, $bar, $op, $pos ) = @_;
The handler is called with 4 arguments:
$self
is the window object that contains the scrollbar.$bar
indicates which scrollbar is being used - possible values areSB_VERT
for the vertical scrollbar orSB_HORZ
for the horizontal scrollbar.$op
is information about what operation is being performed - more on this in a minute.$pos
is the (new) position of the scrollbar - note that it is zero unless$op
isSB_THUMBTRACK
orSB_THUMBPOSITION
.
The possible values for $op
for vertical scrollbars are:
SB_LINEUP
when the arrow at the top is pressed. Indicates that we should move one 'line' towards the top of the contents of the window.SB_LINEDOWN
when the arrow at the bottom is pressed. Indicates that we should move one 'line' towards the bottom of the contents of the window.SB_PAGEUP
when the sunken area between the thumb and the top arrow is pressed. Indicates that we should move one 'page' towards the top of the contents of the window.SB_PAGEDOWN
when the sunken area between the thumb and the bottom arrow is pressed. Indicates that we should move one 'page' towards the bottom of the contents of the window.
For horizontal scrollbars there are a similar set of messages:
SB_LINELEFT
when the arrow at the left is pressed. Indicates that we should move one 'line' towards the left of the contents of the window.SB_LINERIGHT
when the arrow at the right is pressed. Indicates that we should move one 'line' towards the right of the contents of the window.SB_PAGELEFT
when the sunken area between the thumb and the left arrow is pressed. Indicates that we should move one 'page' towards the left of the contents of the window.SB_PAGERIGHT
when the sunken area between the thumb and the right arrow is pressed. Indicates that we should move one 'page' towards the right of the contents of the window.
Both horizontal and vertical scrollbars can generate events for the following operations:
SB_THUMBTRACK
when the thumb is being dragged.$pos
indicates the current position of the dragged thumb.SB_THUMBPOSITION
when the thumb is released after being dragged.$pos
indicates the position of the dragged thumb when the mouse is released.SB_ENDSCROLL
whenever a scroll operation finishes.
Note that we'll see that we are under control of the definition of the size of a 'line' and a 'page' in future articles in this series.
45 my ( $bar_text, $op_text );
46
47 if ( $bar == SB_VERT ) {
48 $bar_text = "VERTICAL";
49 $op_text = $vert_cmds[$op];
50 }
51 elsif ( $bar == SB_HORZ ) {
52 $bar_text = "HORIZONTAL";
53 $op_text = $horz_cmds[$op];
54 }
55 else {
56 $bar_text = "UNKNOWN";
57 $op_text = "UNKNOWN";
58 }
59
60 printf "%-10s : %-16s : %d\n", $bar_text, $op_text, $pos;
61
62 return 1;
63 }
The rest of the code decodes the $bar
and $op
fields, before displaying the information. Here's the full code for this article - run it and play with the scrollbars to see the generated messages. Next time we'll see how to set the range of positions the scrollbar can report, rather than the default 0 through 100 that you'll see if you drag the thumb from one end of the scrollbar to the other.
#!perl -w
use strict;
use warnings;
use Win32::GUI 1.05 qw(CW_USEDEFAULT WS_CLIPCHILDRENWM_HSCROLL WM_VSCROLLSB_CTL SB_HORZ SB_VERTSB_TOP SB_BOTTOM SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWNSB_LEFT SB_RIGHT SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHTSB_THUMBTRACK SB_THUMBPOSITION SB_ENDSCROLL);
my @vert_cmds = qw(SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWNSB_THUMBPOSITION SB_THUMBTRACKSB_TOP SB_BOTTOMSB_ENDSCROLL);
my @horz_cmds = qw(SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHTSB_THUMBPOSITION SB_THUMBTRACKSB_LEFT SB_RIGHTSB_ENDSCROLL);
my $mw = Win32::GUI::Window->new(
-title => "Scrollbar 04: View Scroll Messages",
-left => CW_USEDEFAULT,
-size => [ 400, 300 ],
-addstyle => WS_CLIPCHILDREN,
-vscroll => 1,
-hscroll => 1,
-onScroll => \&process_scroll,
);
my $bm = Win32::GUI::Bitmap->new("kids.bmp");
$mw->AddLabel( -bitmap => $bm );
$mw->Show();
Win32::GUI::Dialog();
$mw->Hide();
exit(0);
sub process_scroll {
my ( $self, $bar, $op, $pos ) = @_;
my ( $bar_text, $op_text );
if ( $bar == SB_VERT ) {
$bar_text = "VERTICAL";
$op_text = $vert_cmds[$op];
}
elsif ( $bar == SB_HORZ ) {
$bar_text = "HORIZONTAL";
$op_text = $horz_cmds[$op];
}
else {
$bar_text = "UNKNOWN";
$op_text = "UNKNOWN";
}
printf "%-10s : %-16s : %d\n", $bar_text, $op_text, $pos;
return 1;
}
Source code can be downloaded from the series index page. Back to Part 3. Move on to Part 5.