From: Robert M. <rob...@us...> - 2007-06-04 20:17:34
|
On 30/05/07, George <sir...@ya...> 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__ |