The script below shows the problems I'm having with InvalidateRect(). The script makes a RichEdit move in tandem with a splitter.
When no InvalidateRect() is called in the Splitter_OnRelease(), and the splitter is moved into the RichEdit area, echoes of it are created in the RichEdit. When $Main->InvalidateRect(1) is called at the end of Splitter_OnRelease() the echo problem is corrected, but clearly only the RichEdit has been updated, not the whole $Main window. And finally, when Win32::GUI::InvalidateRect(0,0) is used, the whole window is repainted correctly, but so is the whole desktop, with unacceptable flicker. I've tried every imaginable variation on InvalidateRect(), Redraw() and Update(), and only invalidating the whole desktop works (sort of). Brief notes on the support functions Sum(), Dif(), XY(), X(), and Y(), --follow the script. -------------------------------------------- use strict; use Win32::GUI; my $RichEditText = <<'__'; Testing InvalidateRect(). (note: resizing the window redraws everything correctly, and can be used to clean up after the first two tests.) Check the checkbox ... ..None: means there's no InvalidateRect() called in Splitter_OnRelease(). In this case moving the splitter to the right creates echoes of it in the RichEdit. ..Main: calls $Main->InvalidateRect(1) in Splitter_OnRelease(). This corrects the splitter-echo problem, but apparently only the RichEdit is invalidated, not the whole $Main window. ..Desk: calls Win32::GUI::InvalidateRect(0,0) in Splitter_OnRelease(). This corrects both problems, but it invalidates the whole desktop, with much flicker. __ my $MainHeight = 600; my $MainWidth = 600; my $Desk = Win32::GUI::GetDesktopWindow(); my $Main = new Win32::GUI::Window ( -height => $MainHeight, -width => $MainWidth, -text => 'testing InvalidateRect()', -onResize => \&Main_OnResize, -onTerminate => \&Main_OnTerminate, -background => 0x0000FF, ); my $Edit = $Main->AddRichEdit ( -text => $RichEditText, -left=>10,-top=>10, -width=>$MainWidth-110, -height=>$MainHeight-20, ); my $Splitter = $Main->AddSplitter ( -left => 10, -top => 10, -width => 10, -height => $MainHeight-20, -onRelease => \&Splitter_OnRelease, ); my $Test1 = $Main->AddRadioButton ( -left => $MainWidth-90 , -top => 20, -text => 'None', -checked => 1, ); my $Test2 = $Main->AddRadioButton ( -left => $MainWidth-90 , -top => 40, -text => 'Main', ); my $Test3 = $Main->AddRadioButton ( -left=>0,-top=>0,# -width=>0,-height=>0, -left => $MainWidth-90 , -top => 60, -text => 'Desk', ); sub Splitter_OnRelease { XY($Edit, 0,0, XY($Splitter,1,0), 1,1, Dif(XY($Main,1,1),100,10) ); if($Test1->Checked()) { # no InvalidateRect() } elsif($Test2->Checked()) { $Main->InvalidateRect(0); } elsif($Test3->Checked()) { Win32::GUI::InvalidateRect(0,0); } } sub Main_OnResize { Y($Splitter,0,10, 1,Y($Main,1)-10); XY($Edit, 0,0, XY($Splitter,1,0), 1,1, Dif(XY($Main,1,1),100,10) ); X($Test1,0, X($Main,1)-90); X($Test2,0, X($Main,1)-90); X($Test3,0, X($Main,1)-90); } XY($Main, .5,.5, XY($Desk, .5,.5)); Main_OnResize(); $Main->Show(); Win32::GUI::Dialog(); sub Main_OnTerminate { -1 } # ------------------------------------------------------------------------ sub Sum { my @sum; for(my($i,$j)=(0,@_/2);$j<=$#_;$i++,$j++) { push @sum,$_[$i]+$_[$j] } @sum; } sub Dif { my @dif; for(my($i,$j)=(0,@_/2);$j<=$#_;$i++,$j++) { push @dif,$_[$i]-$_[$j] } @dif; } sub X { if(@_ == 2) { my ($O,$x)[EMAIL PROTECTED]; my $parent = eval{$O->GetParent()}; return $x * Win32::GUI::ScaleWidth($O) if ! defined($parent); return $x * $O->Width() + $O->Left(); } elsif(@_ == 3) { my ($A,$ax,$Px) = @_; $A->Left($Px-$ax*$A->Width()); } else # @_ == 5 { my ($A, $ax1,$Px1, $ax2,$Px2) = @_; my $ok1 = defined($ax1) && defined($Px1); my $ok2 = defined($ax2) && defined($Px2); if($ok1 && $ok2) { my $Aw = eval { int(($Px2-$Px1)/($ax2-$ax1))}; $A->Width($Aw) if defined($Aw); my $Ax = eval { int(($ax2*$Px1-$ax1*$Px2)/($ax2-$ax1)) }; $A->Left($Ax) if defined ($Ax); } elsif($ok1){$A->Left($Px1-$ax1*$A->Width())} elsif($ok2){$A->Left($Px2-$ax2*$A->Width())} } } sub Y { if(@_ == 2) { my ($O,$y)[EMAIL PROTECTED]; my $parent = eval{$O->GetParent()}; return $y * Win32::GUI::ScaleHeight($O) if ! defined($parent); return $y * $O->Height() + $O->Top(); } elsif(@_ == 3) { my ($A,$ay,$Py) = @_; $A->Top( $Py - $ay*$A->Height()); } else # @_ == 5 { my ($A, $ay1,$Py1, $ay2,$Py2) = @_; my $ok1 = defined($ay1) && defined($Py1); my $ok2 = defined($ay2) && defined($Py2); if($ok1 && $ok2) { my $Ah = eval { int(($Py2-$Py1)/($ay2-$ay1))}; $A->Height($Ah) if defined($Ah); my $Ay = eval { int(($ay2*$Py1-$ay1*$Py2)/($ay2-$ay1))}; $A->Top($Ay) if defined $Ay; } elsif($ok1){$A->Top($Py1-$ay1*$A->Height())} elsif($ok2){$A->Top($Py2-$ay2*$A->Height())} } } sub XY { if(@_ == 3) { my ($O,$x,$y) = @_; return ( X($O,$x), Y($O,$y) ) } elsif(@_ == 5) { my ($A,$ax,$ay,$Px,$Py) = @_; X($A,$ax,$Px); Y($A,$ay,$Py); } else # @_ == 9 { my ($A, $ax1,$ay1, $Px1,$Py1, $ax2,$ay2, $Px2,$Py2) = @_; X($A,$ax1,$Px1,$ax2,$Px2); Y($A,$ay1,$Py1,$ay2,$Py2); } } __END__ Sum() and Dif() take an even number of arguments, and divide them in two halves and then add or subtract the halves like vectors. XY() is my way of hiding all the arithmetic of the layout design. In brief, XY($obj,$x,$y) returns the absolute coordinates of the $obj-relative point ($x,$y) (-- object-relative meaning eg that (0,0),(0,1),(1,0),(1,1), and (.5,.5) are the upper left, upper right, lower left, lower right, and center of the object. - etc) XY($obj,$x,$y,$P,$Q) moves the object so that the object-relative point ($x,$y) will be at absolute point ($P,$Q). XY($obj, $x1,$y1,$P1,$Q1, $x2,$y2,$P2,$Q2) both moves and resizes the object so that the object-relative point ($x1,$y1) will be at absolute point ($P1,$Q1), and object-relative point ($x2,$y2) will be at absolute point ($P2,$Q2). (And likewise for the single-coordinate versions X() and Y().) In the script, in Splitter_OnRelease() XY($Edit, 0,0, XY($Splitter,1,0), 1,1, Dif(XY($Main,1,1),100,10) ); causes the RichEdit's upper left corner to be located at the Splitter's upper right corner, thus moving them in tandem, and RichEdit's lower right corner to be located at an (-100,-10)-offset from the Main window's lower right corner. And in Main_OnResize() Y($Splitter,0,10, 1,Y($Main,1)-10); keeps the Splitter's upper edge at 10, and its lower edge at an offset of -10 from the Main window's lower edge. X($Test1,0, X($Main,1)-90); etc keep the checkboxes pined to the right side. Finally, XY($Main, .5,.5, XY($Desk, .5,.5)); centers the window in the desktop.