From: Mark D. <mar...@zn...> - 2007-03-21 19:41:42
|
Hi, wxWidgets DC is drawing not my area, but you are going to have to become familiar with the way device contexts and, I think, drag and drop work in wxWidgets. You'll have a fair bit of reading to do! (You need the wxWidgets help file(s) ) I did once have occasion to have to do some drawing in MSWin, so I think the basic concepts are as follows: Perhaps someone else more experienced can post any errors or even point out complete misunderstanding :-) For an example, you have your DC and you want to draw two elements on it - a rectangle and a text string. You need to retain the details of the elements and draw them all each time the GUI events request that you do so. So, every time you get an 'OnPaint' event from your Wx::PaintDC object, call the drawing code for all your elements. At this stage, the location on the DC that your elements get drawn to is always the same so you would always be using $dc->SetLogicalFunction(wxCOPY); To select and move the elements you will need to become familiar with responding to mouse events and probably 'drag and drop.' Essentially all you really want to do is reset the position of your element on the DC in response to some mouse actions. To give user the feeling of 'dragging' the element, when the user presses the mouse down in your window, you need to get the xy position of the mouse from the event. The outside bounds of each of your drawing elements can be described by a Wx::Rect object. You can construct this for your 'rectangle' element, simply by recording the x,y,w,h coordinates you used to create it. The bounding rectangle of your text can be found by calling $dc->GetTextExtent(). You would probably keep some objects of your own devising that define each separate drawing element in an array, with each object containing the necessary primitive information along with the bounding Wx::Rect. So, when you get an xy position for the mouse, you can iterate through the array checking each objects Wx::Rect member to see if the xy is within that rect. ($rect->Contains()). The ordering of the array is important so that if the elements on screen overlap, you get the topmost one returned for the xy position. Once you know which object has been selected by the mouse, you can respond to a 'drag' operation by simply drawing its bounding rect outline. For this you would use $dc->SetLogicalFunction(wxINVERT); Once that is set, repeating a drawing operation simply reverts the affected elements to the original colour (so it would work on a background containing many colours). So, you would have a 'draw_dragged_object' sub that accepted a bounding rect as a param and some flag or method of knowing if this is the start of a dragging operation or the end of the operation. So sub draw_dragged_object { my ($self, $obj, $startend, $dc) = @_; if($startend !~ /START/) { $self->_draw_invert_rect(elf->{_prior_rect},$dc ) } if($startend !~ /END/) { $self->_draw_invert_rect( $obj->Rect, $dc ); } $self->{_prior_rect} = $obj->Rect; } sub _draw_invert_rect { my($self, $rect, $dc) = @_; my $savelogic = $dc->SetLogicalFunction(wxINVERT); .... Do drawing $dc->SetLogicalFunction( $savelogic ); } When the mouse is released, you can save the position of your moved object and then you can go for the full redraw. (I think Update or Refresh will do this)? Then the standard OnPaint response of simply redrawing the objects will work The bounding area of any irregular object can be represented by a Wx::Region (so you can do the selection test.) The Demo module you need to look at is wxPrinting.pm Hope this helps get you started at least. Regards Mark |