On 30/05/07, George <[EMAIL PROTECTED]> wrote:
thanks for the response,  but where should we  insert the invalidate
function,
 i am lost completely. and many discussions in the forum are complicated and
for experts only, i have tried many variations with no success. the
available examples in the forum are calling a sub paint which includes the
drawing functions inside it ,and it happend the drawing functions are
speedy, but suppose a function are drawing a fractal and this is a time
consuming, then we will see that this approach is unpractical,  we just want
to refresh the points of color ,and not to recalculate the code everytime we
move or hide the window.

Unfortunately drawing using the Win32 API, and understanding all the
gotchas is not trivial.  This is not helped by the way that Win32::GUI
exposes the 'Paint' event.  I've had it on my list of things to
investigate further for some time, and you've spurred me into looking
at it in a bit more detail.  As a result, I'm not sure how to improve
things in a backewards-compatible way.  While I think about it some
more, here's the first of 2 examples.  This example takes the
traditional approach of doing all the painting in the 'Paint' handler,
determining what to draw, and drawing it, each time the handler is
called.

I'll follow-up with a second example showing how to create a memory DC
as a backing store that you only need to draw into when things change.

Hope it is useful.
Regards,
Rob.

#!perl -w
use strict;
use warnings;

use Win32::GUI qw( CW_USEDEFAULT RDW_VALIDATE RDW_NOCHILDREN );

my $do_drawing = 0;

my $mw = Win32::GUI::Window->new(
        -title => 'Draw on click example',
   -left => CW_USEDEFAULT,
        -size  => [ 400, 300 ],
   -onPaint => \&paint,
);

$mw->AddButton(
   -text => _get_button_text(),
   -pos  => [150,150],
   -onClick => \&click,
);

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

sub paint {
        my ($self, $dc) = @_;

   # This Save() and the final Restore() are one way
   # to ensure the DC is returned to Win32 in the same
   # state as when we got it.
   my $saved = $dc->Save();

   # Win32::GUI doesnt use BeginPaint()/EndPaint() for the
   # DC it passes to its Paint handler.  Here we approximate
   # what BeginPaint does:
   # (1) Calling GetUpdateRect with FLAG=1 causes the background
   #     of the invalidated area t be cleared (WM_ERASEBKGND sent),
   #     and invalid non-client area to be repainted (WM_NCPAINT sent).
   # (2) Convert the update rect to a region and select it into the
   #     DC - set up the correct clipping area for us (this is not strictly
   #     necessary, but will help reduce re-draw flicker
   # (3) We validate the DC.  We do this using Window->Redraw() rather than
   #     DC->Validate(), as validating the entire DC validates child windows,
   #     stopping them being repainted (unless we give the main window
   #     the WS_CLIPCHILDREN style).
   {
       # Erase background, repaint non-client area and get update rect
       my($l, $t, $r, $b) = $dc->GetUpdateRect(1);

       # GetUpdateRect can return undef if there is no update region -
       # generally a Paint event only happens if there is a non-empty
       # update region, but it can happen if there are 'internal' paint
       # events being generated.
       if(defined $l) {
           my $clip_rgn = Win32::GUI::Region->CreateRectRgn($l, $t, $r, $b);
           $dc->SelectClipRgn($clip_rgn);
       }

       # Validate the whole window
       $self->Redraw(RDW_VALIDATE | RDW_NOCHILDREN);
   }

   # Eventually .... do our drawing
   if($do_drawing) {
       $dc->Rectangle(10,10,100,100);
   }

   # Restore the DC to the state it was in before we got it
   $dc->Restore();

        return 1;
}

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

   $do_drawing = !$do_drawing;

   $self->Text(_get_button_text());

   $self->GetParent->InvalidateRect(1);

   return 1;
}

sub _get_button_text {
   return $do_drawing ? 'Hide ...' : 'Draw ...';
}
__END__

Reply via email to