On approximately 5/17/2004 2:02 AM, came the following characters from
the keyboard of Jez White:
Assuming there is no problem with this example and people think it's
useful I'll commit it to the samples folder today.
Well, as long as it isn't committed yet....? Or even if it is, perhaps
another go-round would be acceptable. I have read through the code now,
and apologies if I say something stupid, because I'm tired and it is
bed-time, but perhaps a few extra comments would make the sample even
more useful than it already is. I'll throw some in, but they may not be
accurate, so please double check me.
Most of my comments are related to my thought that the NEM allows the
writing of "generic" functions for particular functionality. I haven't
tried any of the stuff I'm suggesting here.... yet....
==================
#This example creates a scrolling bitmap within another window. This
example uses
#a hooked event to paint to the window directly, rather than using a Graphic
#Control.
use Win32::GUI;
use strict;
#create a new class which stops the WM_ERASEBKGND message from erasing
the background
# Because of this, it is necessary to redraw background explicitly
if/when the bitmap changes size, especially if it becomes smaller.
my $WC = new Win32::GUI::Class(
-name => "NoFlicker",
-style => 0,
);
#Create the window and child controls.
my $mainwin = new Win32::GUI::Window (
-pos => [100, 100],
-size => [330, 235],
-name => "Window",
-text => "Bitmap Scroll demo",
-pushstyle => WS_CLIPCHILDREN,
-class => $WC,
#NEM Events for this window
-onResize => \&Resize,
-onTerminate => sub {return -1;}
);
$mainwin->AddButton (
-name => 'Open',
-pos => [205, 20],
-size => [110, 20],
-text => 'Open Bitmap',
-onClick => \&OpenBitmap,
);
#Create a child window with a scroll bars.
my $ChildWin = new Win32::GUI::Window (
-parent => $mainwin,
-name => "ChildWin",
-pos => [0, 0],
-size => [200, 200],
-popstyle => WS_CAPTION | WS_SIZEBOX,
-pushstyle => WS_CHILD | WS_CLIPCHILDREN,
-pushexstyle => WS_EX_CLIENTEDGE,
-class => $WC,
-hscroll => 1,
-vscroll => 1,
-onScroll => \&Scroll,
);
#hook into the paint event of the child window
$ChildWin->Hook(15, \&Paint);
#Create a memory DC compatible with the child window DC
my $memdc=$ChildWin->GetDC->CreateCompatibleDC();
#Define global variables
my $bitmap; #will hold the bitmap
#show both windows and enter the Dialog phase.
$mainwin->Show();
$ChildWin->Show();
Win32::GUI::Dialog();
# This Paint Hook uses an outer scope reference to the $ChildWin
variable, tying it to this specific window. It also used a global
$memdc, tying it to that particular bitmap. Factoring out these two
items would make the function more generic. Something like
sub Paint {
# Can $ChildWin be derived from the parameters to the hook function?
return & PaintHelp( $ChildWin, $memdc );
}
sub PaintHelp {
#Paint event handler, called when ever the window needs to be
redrawn/painted
return unless $bitmap;
#tell windows that we are starting to paint
$ChildWin->BeginPaint;
#get the DC of the child window
my $dc=$ChildWin->GetDC;
#Performa a bit block transfer of the memory DC into the child window DC
#The cordinates are based upon the possition of the scroll bars
$dc->BitBlt(0, 0,
$ChildWin->Width,$ChildWin->Height,$memdc,$ChildWin->ScrollPos(0),$ChildWin->ScrollPos(1));
#tell windows that we have finished painting.
$ChildWin->EndPaint;
}
# Again, if the $ChildWin could be derived from the parameters to the
Resize event, this function could be generic to any Scrollable window,
it would appear.
sub Resize {
#Resize handler
my ($width, $height) = ($mainwin->GetClientRect)[2..3];
$mainwin->Open->Left($width-120);
#Resize the child window and set the scroll bar page of each scroll bar.
#This has the effect of increasing/decreasing the size of the bar
within the scroll bar
#as the window is resized.
$ChildWin->Resize($width-150,$height);
$ChildWin->ScrollPage(0,$ChildWin->Width);
$ChildWin->ScrollPage(1,$ChildWin->Height);
}
# Three parameters ( $ChildWin, $bitmap, $memdc ) would make this
function generic.
sub OpenBitmap {
#Function to load in the bitmap
my $file = Win32::GUI::GetOpenFileName(
-owner => $mainwin,
-hidereadonly => 0,
-title => "Open an bitmap file",
-filter => ['Bitmaps' => '*.bmp',
'All files' => '*.*',
],
);
$bitmap=new Win32::GUI::Bitmap($file);
if ($bitmap) {
#if we have a valid bitmap, get the dimentions
my ($width,$height)=$bitmap->Info();
#select the bitmap into the memory DC so it can be maniplated later.
$memdc->SelectObject($bitmap);
#set the scroll bar range and position based upon the height and
width of the bitmap.
$ChildWin->ScrollRange(1,0,$height+20); #add 20 for the scroll bar
$ChildWin->ScrollRange(0,0,$width+20);
$ChildWin->ScrollPage(0,$ChildWin->Width);
$ChildWin->ScrollPage(1,$ChildWin->Height);
#set the scroll bars to 0.
$ChildWin->ScrollPos(0,0);
$ChildWin->ScrollPos(1,0);
$ChildWin->InvalidateRect(0); #invalidate the child window so
windows triggers the paint event
}
}
# This function appears to be generic to any scrollable window. Can the
technique shown here to obtain $win be applied to obtain $ChildWin in
some of the above functions? (Resize? Paint?)
sub Scroll {
#Scroll event handler. We have to explicitly "move" the scroll bars.
#Once they have been moved, we repaint the window.
my($win,$scrollbar, $operation, $position) = @_;
if($operation == SB_THUMBTRACK) {
$win->ScrollPos($scrollbar,$position);
}
elsif($operation == SB_LINEDOWN) {
$win->ScrollPos($scrollbar,$win->ScrollPos($scrollbar)+1);
}
elsif($operation == SB_LINEUP) {
$win->ScrollPos($scrollbar,$win->ScrollPos($scrollbar)-1);
}
elsif($operation == SB_PAGEDOWN) {
$win->ScrollPos($scrollbar,$win->ScrollPos($scrollbar) +
$win->ScrollPage($scrollbar));
}
elsif($operation == SB_PAGEUP) {
$win->ScrollPos($scrollbar,$win->ScrollPos($scrollbar) -
$win->ScrollPage($scrollbar));
}
#invalidate the child window so windows triggers the paint event
$win->InvalidateRect(0);
}
--
Glenn -- http://nevcal.com/
===========================
The best part about procrastination is that you are never bored,
because you have all kinds of things that you should be doing.