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__