About Me

My Photo
Rob
London, United Kingdom
View my complete profile

Thursday, 25 December 2008

Honeymoon - Part 1

Journey to Singapore


We had a fun and fabulous time getting in the holiday spirit the BA lounge - things are so much more fun when they're "free", and we had enough time to experiment making our own champagne cocktails. Everything was as smooth as smooth can be and it makes flying - even from Heathrow - a pleasure. I (Emma) saw Sir Roy Strong at the buffet counter in the BA lounge but no one else seems to know who he is. The 12-hour flight passed by in a trice, mainly because we were so replete with Christmas spirit that we fell into a comfortable coma on our flat beds, waking up in Singapore. Again, the transfers were sheer pleasure as we were collected from Changi airport by a be-flagged Raffles limo complete with damp flannels to freshen up.

Singapore

Several interesting things about Singapore: they drive on the left; they only cross the road when the man is green; there is a counter to let you know how long you have to get across the road; alcohol is extortionate at £15 for a bottle of Blossom Hill in the supermarket; it's the monsoon; no one has nut allergies; their Christmas decorations are very classy, yet they don't really shut for Christmas; a Singapore evening's entertainment appears to be going to the local shopping mall and shopping; the tropical weather's wonderful, hot and steamy.

Raffles


Wow, what an amazing place. First, let's get the criticism out of the way: the famous "Long Bar" is held up to be a colonial, traditional place where a tiger was shot under the billiards table in the nineteenth century. The reality is that it's a mock-Irish bar with an overloud band, crap decor, no tiger, no billiard table and a floor that needs a good sweep. And even the peanuts on the tables are small and mean. That said we did enjoy the cocktails, including the ubiquitous Singapore Sling.

Raffles itself is just beautiful: high ceilings bedecked with multitudes of langorously circulating fans, endless white walls (we saw the paintwork being touched up, even on Christmas Eve), shiny dark teak floors and colonial furniture carefully placed. Our suite was fabulous: we had a parlour with slippers laid out by the front door, strangely; interior, shuttered windows between parlour and bedroom, and a wonderful two-basined dressing room. The bathroom was pretty much the size of our flat; and contained a surfeit of fluffy white towels. Our bed was huuuuuuge - must be seven feet wide and so, so comfy. Outside our suite we had a pair of chairs and a table overlooking a lush tropical garden with little birds tweeting and fountains playing gently. We brought in Christmas sat on the verandah sipping champage and listening to the gentle sound of rain against the foliage next to us.

This-morning we've used the roof-top pool (somewhat colder water than we were expecting, but very refreshing), and we are now sat by the pool drinking beers while writing this. It's hard to imagine that we're right in the middle of a throbbing city - the only thing that gives it away are the high-rise buildings nearby - with the pool surrounded by greenery and the birds singing in the trees.


Food


We've managed to sample a variety of the city's offerings already: Japanese BBQ (including yummy Wagu beef), American-style muffins at breakfast; Starbucks(!); German sausage and sauerkraut; and best yet seafood from Jumbo's (East Coast Parkway): Black peppered Crab, Sambal Crayfish and Yam wrapped scallops. All so very good ...

Around and about

We spent our one full day here (we're back again at the end of the week) exploring town. The subway is clean and fast - making getting around a breeze. We wandered the plethora of shopping malls along Oarchard Road, taking in the somewhat rainy atmosphere, before heading to China Town. There we explored the many tat-selling stalls and took in the atmosphere. We're told it was very quiet compared to normal, but really that made it all the more appealing.

That's all for now - we're heading to Langkawi this-evening - hopefully more from us in a couple of days.

Saturday, 23 February 2008

Blissful Kerala


Emma and I have just got back to Bangalore following a couple of days relaxing by the sea in Kerala. We didn't know the area at all and by chance found the most amazing, remote, quiet location to relax in. The village is called Edakkad, and is about 10km south of Kannur (also known as Cannanore).

We left Bangalore on the Yesvantpur Express sleeper train on Monday night, after a long and exciting (for Emma at least) auto ride from one side of the city to the station on the other. The train was surprisingly comfortable, although our sleep was disturbed by the jolting of the train on occasions .... we arrived in Kannur to almost silence as there was a Hartal (a sort of General Strike) in progress. We were met at the station by our hosts (Suresh, Vivin and Gafur), who had arranged a hotel room for us to relax in until the Hartal finished at 6PM, when we would be allowed to take the car on the road and move to Edakkad.

Our hosts maintain 2 houses for guests in Edakkad. One called the Beach House, and the other called the River House. They are almost next to each other, and both in immaculate condition with some of the nicest bathrooms I have seen in India, outside of the 5-star hotels.

We spent our 2-days relaxing and being looked after by the staff - we pretty much didn't lift a finger for the duration of our stay. The staff went shopping for us, cooked our meals (yum!) and acted as local guides on the few occasions that we braved the sun and left our cool verandah, to explore the village and our 'private' beach. On our second afternoon we paddled across the river (only possible at low-tide) and then took the jeep and drove it the length of the 4KM 'drive-in' beach.

We got up early most mornings so that we could walk through the village in the relative cool, before the sun really got going. It was interesting to see the local village life with the kids on their way to school (and testing out their English on us) and listening to the gentle 'thwack' of clothes being beaten onto the washing stones.

We mainly ate local curries - sometimes just vegetable curry and ghee rice, once having fresh fish caught by our neighbour (see the fishing boats here) and drinking the milk from coconuts plucked from the trees right on our doorstep. The coconut trees as well as providing their fruit to eat and drink, also act as firewood and the most amazing deep shade to keep us out of the blazing sun.

After just 2 short days it was time for us to head back to Bangalore. We really didn't want to leave, and would love to find a way to go back and stay for a bit longer, as this would be a great base from which to explore the wildlife, hill-stations and backwaters of Northern Kerala, and I know that our hosts would have been very happy to arrange that for us.

This is not a location for those expecting swimming-pools and restaurants on the doorstep. Although we didn't explore the local facilities outside our immediate village we are led to believe that there are some hotels with restaurants and pools within a short drive. You can read a bit more about our hosts and the facilities at their website. (also here).

We (I?) forgot to take a camera with us (doh!), but we did take a few snaps on our phones, and Suresh found us a camera and a film to take some photos, which you can see here. My, how I have forgotten how limiting a film camera is with only 24 snaps to take, and no way to preview them to see what they look like.

Monday, 3 September 2007

Scrollbars - Part 7 - Processing the scroll messages

In the previous articles in this series (parts 1, 2, 3, 4, 5 and 6) we investigated the scrollbar messages and set-up the scrollbars for our application. In this article we finally make the scrollbars do something for us.

In the Scroll handler we react to each scrollbar operation, and re-position the image:


51 sub process_scroll {
52 my ( $self, $bar, $op, $pos ) = @_;
53
54 my $prev_pos = $self->ScrollPos($bar);
55 my $new_pos = $prev_pos;
56
57 if ( $op == SB_LINEUP ) { # or SB_LINELEFT
58 $new_pos -= 1;
59 }
60 elsif ( $op == SB_LINEDOWN ) { # or SB_LINERIGHT
61 $new_pos += 1;
62 }
63 elsif ( $op == SB_PAGEUP ) { # or SB_PAGELEFT
64 $new_pos -= $self->ScrollPage($bar);
65 }
66 elsif ( $op == SB_PAGEDOWN ) { # or SB_PAGERIGHT
67 $new_pos += $self->ScrollPage($bar);
68 }
69 elsif ( $op == SB_THUMBTRACK ) {
70 $new_pos = $pos;
71 }
72 elsif ( $op == SB_THUMBPOSITION ) {
73 $new_pos = $pos;
74 }
75
76 $self->ScrollPos( $bar, $new_pos );
77
78 if ( $bar == SB_VERT ) {
79 $self->BM->Top( -$new_pos );
80 }
81 else { # SB_HORZ
82 $self->BM->Left( -$new_pos );
83 }
84
85 return 1;
86 }
There are two subtleties:

The first is that because we have chosen a positive range for our reported positions, we have to negate them before using them to position the label control.

The second is that we also need to re-position the control in the
Resize handler. Because we change the page size in this handler we may make the current position invalid (remember from the last article in the series the page-size affects the maximum reportable position of the scrollbar). Fortunately the scrollbar implementation takes care of adjusting the current position for us, so we can just retrieve the new current position after we set the page size and use that to position the control.

40 sub process_resize {
41 my ($self) = @_;
42
43 $self->ScrollPage( SB_HORZ, $self->ScaleWidth() );
44 $self->ScrollPage( SB_VERT, $self->ScaleHeight() );
45
46 $self->BM->Move( -$self->ScrollPos(SB_HORZ), -$self->ScrollPos(SB_VERT) );
47
48 return 1;
49 }
Finally we end up with what we want - scrollbars that allow us to scroll around the image and see the parts that don't fit into the window.

Note that handling both the SB_THUMBTRACK and SB_THUMBPOSITION operations is not strictly necessary. Typically it is better to handle the SB_THUMBTRACK, as that allows us to move the contents while the user is dragging the thumb; however, if we had a window that took a long time to redraw, then we might chose to only process the SB_THUMBPOSITION operation so that we only need to redraw when the user releases the thumb. Try removing the branches in the above code to see the 2 behaviours.

As always, here is the full code:

#!perl -w
use strict;
use warnings;

use Win32::GUI 1.05 qw(
CW_USEDEFAULT WS_CLIPCHILDREN
WM_HSCROLL WM_VSCROLL
SB_CTL SB_HORZ SB_VERT
SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_THUMBTRACK SB_THUMBPOSITION
);

my $mw = Win32::GUI::Window->new(
-title => "Scrollbar 07: Process Scroll Messages",
-left => CW_USEDEFAULT,
-size => [ 400, 300 ],
-addstyle => WS_CLIPCHILDREN,
-vscroll => 1,
-hscroll => 1,
-onScroll => \&process_scroll,
-onResize => \&process_resize,
);

my $bm = Win32::GUI::Bitmap->new("kids.bmp");
$mw->AddLabel( -bitmap => $bm, -name => 'BM' );

my ( $bmw, $bmh ) = $bm->Info();

$mw->ScrollRange( SB_HORZ, 0, $bmw );
$mw->ScrollRange( SB_VERT, 0, $bmh );

$mw->ScrollPage( SB_HORZ, $mw->ScaleWidth() );
$mw->ScrollPage( SB_VERT, $mw->ScaleHeight() );

$mw->Show();
Win32::GUI::Dialog();
$mw->Hide();
exit(0);

sub process_resize {
my ($self) = @_;

$self->ScrollPage( SB_HORZ, $self->ScaleWidth() );
$self->ScrollPage( SB_VERT, $self->ScaleHeight() );

$self->BM->Move( -$self->ScrollPos(SB_HORZ), -$self->ScrollPos(SB_VERT) );

return 1;
}

sub process_scroll {
my ( $self, $bar, $op, $pos ) = @_;

my $prev_pos = $self->ScrollPos($bar);
my $new_pos = $prev_pos;

if ( $op == SB_LINEUP ) { # or SB_LINELEFT
$new_pos -= 1;
}
elsif ( $op == SB_LINEDOWN ) { # or SB_LINERIGHT
$new_pos += 1;
}
elsif ( $op == SB_PAGEUP ) { # or SB_PAGELEFT
$new_pos -= $self->ScrollPage($bar);
}
elsif ( $op == SB_PAGEDOWN ) { # or SB_PAGERIGHT
$new_pos += $self->ScrollPage($bar);
}
elsif ( $op == SB_THUMBTRACK ) {
$new_pos = $pos;
}
elsif ( $op == SB_THUMBPOSITION ) {
$new_pos = $pos;
}

$self->ScrollPos( $bar, $new_pos );

if ( $bar == SB_VERT ) {
$self->BM->Top( -$new_pos );
}
else { # SB_HORZ
$self->BM->Left( -$new_pos );
}

return 1;
}

Scrollbars - Part 6 - Setting the page size

Previous parts: 1, 2, 3, 4 and 5.

In this article we set the scrollbar's page-size. Setting the page size has two effects on the scrollbars:

Firstly it sets the size of the scrollbar thumb to indicate the amount of the document that is visible. Resize the window and see how the size of the thumb changes to indicate what proportion of the document is visible. Note too how the scrollbars disappear if the whole of the image is visible.

Secondly it effects the range of positions available so that the position reported by the scrollbar so that when at the bottom (or right) of its range the position reported is the value needed to position the top (or left) edge of the content such that it just fits the visible window. In other words the maximum position reported is the maximum position set using the ScrollRange() method minus the page size.


42 $mw->ScrollPage( SB_HORZ, $mw->ScaleWidth() );
43 $mw->ScrollPage( SB_VERT, $mw->ScaleHeight() );
Initially we set the page size to reflect the client area. Note that as we set the range in pixels we set the page size in pixels too. If we were displaying a document, then we might set the range to reflect the number of lines in the document, and we would then set the page size in terms of the number of lines that can be displayed in the window.

23 my $mw = Win32::GUI::Window->new(
24 -title => "Scrollbar 06: Set Scroll Page Size",
25 -left => CW_USEDEFAULT,
26 -size => [ 400, 300 ],
27 -addstyle => WS_CLIPCHILDREN,
28 -vscroll => 1,
29 -hscroll => 1,
30 -onScroll => \&process_scroll,
31 -onResize => \&process_resize,
32 );

50 sub process_resize {
51 my ($self) = @_;
52
53 $self->ScrollPage( SB_HORZ, $self->ScaleWidth() );
54 $self->ScrollPage( SB_VERT, $self->ScaleHeight() );
55
56 return 1;
57 }
We also add a Resize event handler for our window, as the page size changes whenever we resize the window, and so we need to reset the page size that the scrollbars
know about.

Here is the full code for this example. Note how the thumbs change size as the window is resized, and note the reduction in range of positions reported when dragging the thumbs compared to the previous example.

#!perl -w
use strict;
use warnings;

use Win32::GUI 1.05 qw(
CW_USEDEFAULT WS_CLIPCHILDREN
WM_HSCROLL WM_VSCROLL
SB_CTL SB_HORZ SB_VERT
SB_TOP SB_BOTTOM SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_LEFT SB_RIGHT SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT
SB_THUMBTRACK SB_THUMBPOSITION SB_ENDSCROLL
);

my @vert_cmds = qw(SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_THUMBPOSITION SB_THUMBTRACK
SB_TOP SB_BOTTOM
SB_ENDSCROLL);
my @horz_cmds = qw(SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT
SB_THUMBPOSITION SB_THUMBTRACK
SB_LEFT SB_RIGHT
SB_ENDSCROLL);

my $mw = Win32::GUI::Window->new(
-title => "Scrollbar 06: Set Scroll Page Size",
-left => CW_USEDEFAULT,
-size => [ 400, 300 ],
-addstyle => WS_CLIPCHILDREN,
-vscroll => 1,
-hscroll => 1,
-onScroll => \&process_scroll,
-onResize => \&process_resize,
);

my $bm = Win32::GUI::Bitmap->new("kids.bmp");
$mw->AddLabel( -bitmap => $bm );

my ( $bmw, $bmh ) = $bm->Info();

$mw->ScrollRange( SB_HORZ, 0, $bmw );
$mw->ScrollRange( SB_VERT, 0, $bmh );

$mw->ScrollPage( SB_HORZ, $mw->ScaleWidth() );
$mw->ScrollPage( SB_VERT, $mw->ScaleHeight() );

$mw->Show();
Win32::GUI::Dialog();
$mw->Hide();
exit(0);

sub process_resize {
my ($self) = @_;

$self->ScrollPage( SB_HORZ, $self->ScaleWidth() );
$self->ScrollPage( SB_VERT, $self->ScaleHeight() );

return 1;
}

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;
}

Scrollbars - Part 5 - Setting the scroll range

Previous parts: 1, 2, 3 and 4.

The default set of positions that a scroll-bar can take is 0 .. 100. We are, however, free to set this range any way we wish to make our lives easy. In this case we'll choose to make the range of possible horizontal and vertical values equal to the width and hight of the bitmap that we're displaying.


33 my $bm = Win32::GUI::Bitmap->new("kids.bmp");
34 $mw->AddLabel( -bitmap => $bm );
35
36 my ( $bmw, $bmh ) = $bm->Info();
37
38 $mw->ScrollRange( SB_HORZ, 0, $bmw );
39 $mw->ScrollRange( SB_VERT, 0, $bmh );
Now if you run the sample and drag the scrollbar thumbs from one end to the other you'll
see the range as set.

#!perl -w
use strict;
use warnings;

use Win32::GUI 1.05 qw(
CW_USEDEFAULT WS_CLIPCHILDREN
WM_HSCROLL WM_VSCROLL
SB_CTL SB_HORZ SB_VERT
SB_TOP SB_BOTTOM SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_LEFT SB_RIGHT SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT
SB_THUMBTRACK SB_THUMBPOSITION SB_ENDSCROLL
);

my @vert_cmds = qw(SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_THUMBPOSITION SB_THUMBTRACK
SB_TOP SB_BOTTOM
SB_ENDSCROLL);
my @horz_cmds = qw(SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT
SB_THUMBPOSITION SB_THUMBTRACK
SB_LEFT SB_RIGHT
SB_ENDSCROLL);

my $mw = Win32::GUI::Window->new(
-title => "Scrollbar 05: Set Scroll Range",
-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 );

my ( $bmw, $bmh ) = $bm->Info();

$mw->ScrollRange( SB_HORZ, 0, $bmw );
$mw->ScrollRange( SB_VERT, 0, $bmh );

$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;
}

Thursday, 30 August 2007

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:
  1. $self is the window object that contains the scrollbar.
  2. $bar indicates which scrollbar is being used - possible values are SB_VERT for the vertical scrollbar or SB_HORZ for the horizontal scrollbar.
  3. $op is information about what operation is being performed - more on this in a minute.
  4. $pos is the (new) position of the scrollbar - note that it is zero unless $op is SB_THUMBTRACK or SB_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 pre ssed. 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_CLIPCHILDREN
WM_HSCROLL WM_VSCROLL
SB_CTL SB_HORZ SB_VERT
SB_TOP SB_BOTTOM SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_LEFT SB_RIGHT SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT
SB_THUMBTRACK SB_THUMBPOSITION SB_ENDSCROLL
);

my @vert_cmds = qw(SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN
SB_THUMBPOSITION SB_THUMBTRACK
SB_TOP SB_BOTTOM
SB_ENDSCROLL);
my @horz_cmds = qw(SB_LINELEFT SB_LINERIGHT SB_PAGELEFT SB_PAGERIGHT
SB_THUMBPOSITION SB_THUMBTRACK
SB_LEFT SB_RIGHT
SB_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;
}

Wednesday, 29 August 2007

Scrollbars - Part 3 - Adding the scrollbars

In part 1 and part 2 of this series we set up the framework, and now we can get down to the real business of adding scrollbars, so that we can see the parts of our image that don't fit into the window frame.

In this article we add the scrollbars to the main window:


7 my $mw = Win32::GUI::Window->new(
8 -title => "Scrollbar 03: Adding Scrollbars",
9 -left => CW_USEDEFAULT,
10 -size => [ 400, 300 ],
11 -addstyle => WS_CLIPCHILDREN,
12 -vscroll => 1,
13 -hscroll => 1,
14 );
Using the '-vscroll' and '-hscroll' options we request that the window has both vertical and horizontal scroll bars. But that's all these options do - they ask for the scrollbars to be drawn. The scrollbars are drawn, but they don't do anything - we will need to add code for that.

Next time we'll look at the 'Scroll' event handler, and investigate the messages that we get passed that we will need to process.

Full code for this article:

#!perl -w
use strict;
use warnings;

use Win32::GUI 1.05 qw( CW_USEDEFAULT WS_CLIPCHILDREN );

my $mw = Win32::GUI::Window->new(
-title => "Scrollbar 03: Adding Scrollbars",
-left => CW_USEDEFAULT,
-size => [ 400, 300 ],
-addstyle => WS_CLIPCHILDREN,
-vscroll => 1,
-hscroll => 1,
);

my $bm = Win32::GUI::Bitmap->new("kids.bmp");

$mw->AddLabel( -bitmap => $bm );

$mw->Show();
Win32::GUI::Dialog();
$mw->Hide();
exit(0);