#!perl -w #This example uses regions to create clipping areas in an DC. use strict; use warnings; use Win32::GUI 1.03_03, qw( SB_THUMBTRACK SB_LINEDOWN SB_LINEUP WS_CAPTION WS_SIZEBOX WS_CHILD WS_CLIPCHILDREN WS_EX_CLIENTEDGE RGN_DIFF); my $regiontype=0; #Create the window and child controls. my $Win = new Win32::GUI::Window ( -pos => [100, 100], -size => [330, 235], -name => "Window", -text => "Win32::GUI Region demo", #NEM Events for this window -onTimer => \&Timer, -onTerminate => sub {return -1;} ); $Win->AddTimer("Timer", 1); $Win->AddButton ( -name => 'rectange', -pos => [205, 20], -size => [110, 20], -text => 'Rectangle', -onClick => sub {$regiontype=0}, ); $Win->AddButton ( -name => 'Elliptic', -pos => [205, 40], -size => [110, 20], -text => 'Elliptic', -onClick => sub {$regiontype=1}, ); $Win->AddButton ( -name => 'Rounded Rectangle', -pos => [205, 60], -size => [110, 20], -text => 'Rounded Rectangle', -onClick => sub {$regiontype=2}, ); #Create a child window with a scroll bar. my $ChildWin = new Win32::GUI::Window ( -parent => $Win, -name => "ChildWin", -pos => [0, 0], -size => [200, 200], -popstyle => WS_CAPTION | WS_SIZEBOX, -pushstyle => WS_CHILD | WS_CLIPCHILDREN, -pushexstyle => WS_EX_CLIENTEDGE, -hscroll => 1, -onScroll => \&Scroll, ); my $H = $ChildWin->ScaleHeight; #set the scroll bar range and position based upon #the height of the child window. $ChildWin->ScrollRange(0,0,$H); $ChildWin->ScrollPos(0,$H/2); #show both windows and enter the Dialog phase. $Win->Show(); $ChildWin->Show(); Win32::GUI::Dialog(); sub Scroll { #scoll handler. my($win,$scrollbar, $operation, $position) = @_; if($operation == SB_THUMBTRACK) { $win->ScrollPos(0,$position); } elsif($operation == SB_LINEDOWN) { $win->ScrollPos(0,$win->ScrollPos(0)+1); } elsif($operation == SB_LINEUP) { $win->ScrollPos(0,$win->ScrollPos(0)-1); } } sub Timer { #get the dimentions and DC from the child window my $W = $ChildWin->ScaleWidth; my $H = $ChildWin->ScaleHeight; my $DC = $ChildWin->GetDC; #We could draw directly to the window, but to remove #drawing flicker we create a memory DC and draw to that. #Once drawing has been finished, we BitBlt the memory DC #direct into the window DC. # #For a large amount of GDI drawing, the use of a memory DC #can also be quicker. # #We create a Compatible DC, and a Compatible Bitmap. To #improve performance you would #only recreate these objects if the dimentions of the source #DC have change. my $DC2=$DC->CreateCompatibleDC(); my $bit=$DC->CreateCompatibleBitmap($W,$H); #Select the bitmap into the new DC my $oldbit = $DC2->SelectObject($bit); #The size of the region is based upon the scroll bar position #Don't allow it to be zero my $size=$ChildWin->ScrollPos(0) || 1; #Create a region my $region; if ($regiontype==0) { #create a rectangle region $region=CreateRectRgn Win32::GUI::Region(0,0,$size,$size); } elsif ($regiontype==1) { #create a Elliptic region (in this case a circle) $region=CreateEllipticRgn Win32::GUI::Region(0,0,$size,$size); } else { #create a rectangle region with rounded corners $region=CreateRoundRectRgn Win32::GUI::Region(0,0,$size,$size,20,20); } #Clear the area outside the region we are painting into: my $region2 = CreateRectRgn Win32::GUI::Region(0,0,$W,$H); my $region3 = CreateRectRgn Win32::GUI::Region(0,0,$W,$H); $region3->CombineRgn($region2,$region,RGN_DIFF); $DC2->PaintRgn($region3); #Use the region for clipping for the rest of the GDI operations. $DC2->SelectClipRgn($region); for(1..40) { #create a randon pen and brush, and select them into the DC my $P1 = new Win32::GUI::Pen( -color => [ rand()*255, rand()*255, rand()*255 ], -width => rand()*5, ); my $B = new Win32::GUI::Brush([ rand()*255, rand()*255, rand()*255]); my $oldP = $DC2->SelectObject($P1); my $oldB = $DC2->SelectObject($B); my $left = rand()*$W; my $top = rand()*$H; my $right = $left + rand()*($W-$left); my $bottom = $top + rand()*($H-$top); #create a random rectangle $DC2->Rectangle($left, $top, $right, $bottom); my $P2 = new Win32::GUI::Pen( -color => [ rand()*255, rand()*255, rand()*255 ], -width => rand()*5, ); $DC2->SelectObject($P2); #create a random line $DC2->Line(rand()*$W,rand()*$H,rand()*$W, rand()*$H ); #restore the original Pen and Brush so that the new ones #are not selected into the DC, and they get destroyed #when they go out of scope, otherwise we have a huge #resource leak, and quickly stop drawing correctly $DC2->SelectObject($oldP); $DC2->SelectObject($oldB); } #We now update the screen in one action $DC->BitBlt(0, 0, $W,$H,$DC2, 0, 0); #As for the Pen and Brush above, restore the original bitmap $DC2->SelectObject($oldbit); #We now delete the memory DC $DC2->DeleteDC(); }