Hi,

The code below shows an example of using a child window containing a bitmap 
which is scrolled using the scroll bars of the child window. The example uses a 
hooked paint message to pain directly to the child window via a memory DC. 

Assuming there is no problem with this example and people think it's useful 
I'll commit it to the samples folder today.

Cheers,

jez.

==================
#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
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();

sub Paint {
  #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;
}


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

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

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


Reply via email to