gt4586c@prism.gatech.EDU (WILLETT,THOMAS CARTER) (05/30/91)
i'm trying to draw the nifty rubber band we all know and love, the one that is a rectangle defined by the mouse location at the time of button down as the anchor point and the current mouse location (still with button down) as the other corner. i've got the mouse location and drawing the rectangle alright, but it blanks out my drawing as it goes because i'm calling EraseRect do blank out the rectangles outline as the mouse moves. what's the right way to do it? thanks for any help -- thomas willett Georgia Institute of Technology, Atlanta gt4586c@prism.gatech.edu "Violence is the last refuge of the incompetent." - Salvor Hardin (Foundation)
stevec@Apple.COM (Steve Christensen) (05/31/91)
gt4586c@prism.gatech.EDU (WILLETT,THOMAS CARTER) writes: >i'm trying to draw the nifty rubber band we all know and love, the one that >is a rectangle defined by the mouse location at the time of button down as >the anchor point and the current mouse location (still with button down) as >the other corner. i've got the mouse location and drawing the rectangle >alright, but it blanks out my drawing as it goes because i'm calling >EraseRect do blank out the rectangles outline as the mouse moves. what's >the right way to do it? thanks for any help If you just want to track an empty rectangle around, how about doing something like this: void RubberBand(Point startPt, Rect *theRect) { Point lastPt,newPt; lastPt.v = startPt.v; // initialize the last mouse location lastPt.h = startPt.h; // to be the starting mouse location SetRect(theRect,0,0,0,0); // empty rectangle to start PenMode(patXor); // use XOR transfer mode while (StillDown()) { GetMouse(&newPt); // get the mouse's current location if ((newPt.v != lastPt.v) && (newPt.h != lastPt.h)) { lastPt.v = newPt.v; // it's moved since last time, so lastPt.h = newPt.h; // update the last location FrameRect(&theRect); // erase the previous rectangle if (lastPt.v > startPt.v) { // make sure the bottom of the theRect->top = startPt.v; // rectangle is below the top theRect->bottom = lastPt.v; } else { theRect->top = lastPt.v; theRect->bottom = startPt.v; } if (lastPt.h > startPt.h ) { // ditto with the left and right theRect->left = startPt.h; theRect->right = lastPt.h; } else { theRect->left = lastPt.h; theRect->right = startPt.h; } FrameRect(theRect); // draw the new rectangle } } PenNormal(); // restore the pen mode } Note that startPt should be in local coordinates. This means you've done a SetPort() to the appropriate port followed by GlobalToLocal(&startPt). If you'd like a gray rubber band instead of a black one, you could also do a PenPat(&qd.gray) (MPW) or PenPat(gray) (Think) right after the PenMode call. steve -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Steve Christensen Never hit a man with glasses. stevec@apple.com Hit him with a baseball bat.
jcav@quads.uchicago.edu (john cavallino) (05/31/91)
In article <53513@apple.Apple.COM> stevec@Apple.COM (Steve Christensen) writes: >If you just want to track an empty rectangle around, how about doing something >like this: All of the futzing around to create the rectangle from the points can be eliminated if you use the Quickdraw procedure _Pt2Rect (IM I-175). See below: >void RubberBand(Point startPt, Rect *theRect) { > Point lastPt,newPt; > > lastPt.v = startPt.v; // initialize the last mouse location > lastPt.h = startPt.h; // to be the starting mouse location > SetRect(theRect,0,0,0,0); // empty rectangle to start > > PenMode(patXor); // use XOR transfer mode > > while (StillDown()) { > GetMouse(&newPt); // get the mouse's current location > if ((newPt.v != lastPt.v) && (newPt.h != lastPt.h)) { > lastPt.v = newPt.v; // it's moved since last time, so > lastPt.h = newPt.h; // update the last location > > FrameRect(&theRect); // erase the previous rectangle Pt2Rect(&startPt,&newPt,&theRect); // MUCH MUCH simpler > FrameRect(theRect); // draw the new rectangle > } > } > > PenNormal(); // restore the pen mode >} -- John Cavallino | EMail: jcav@midway.uchicago.edu University of Chicago Hospitals | USMail: 5841 S. Maryland Ave, Box 145 Office of Facilities Management | Chicago, IL 60637 B0 f++ w c+ g+ k s(+) e+ h- pv (qv) | Telephone: 312-702-6900
dickie@schaefer.math.wisc.edu (Garth Dickie) (06/01/91)
In article <53513@apple.Apple.COM> stevec@Apple.COM (Steve Christensen) writes: >gt4586c@prism.gatech.EDU (WILLETT,THOMAS CARTER) writes: >>i'm trying to draw the nifty rubber band we all know and love, the one that >>is a rectangle defined by the mouse location at the time of button down as >>the anchor point and the current mouse location (still with button down) as >>the other corner. i've got the mouse location and drawing the rectangle >>alright, but it blanks out my drawing as it goes because i'm calling >>EraseRect do blank out the rectangles outline as the mouse moves. what's >>the right way to do it? thanks for any help > >If you just want to track an empty rectangle around, how about doing something >like this: > > [ code for tracking a rectangle ] It also pays to play with regions, so that the old rectangle is erased at the same time the new one is drawn. It takes a little more time per step, but it *looks* faster, since there is no flicker. The Finder now does this, when you drag an icon, although DragGrayRgn still does it the old way. So, PenPat( gray ); PenMode( notPatXor ); // so we look black, not white, on desktop oldframe = NewRgn(); newframe = NewRgn(); insidebox = NewRgn(); [ whenever the cursor changes ] { Pt2Rect( oldwhere, newwhere, &bounds ); oldwhere = newhere; RectRgn( newframe, &bounds ); // compute a region for a one InsetRect( &bounds, 1, 1 ); // pixel wide frame inside the RectRgn( insidebox, &newrect ); // rectangle. XorRgn( insidebox, newframe, newframe ); XorRgn( newframe, oldframe, oldframe ); // compute the difference PaintRgn( oldframe ); // xor the difference temp = oldframe; // save the current rectangle oldframe = newframe; // as oldframe. newframe = temp; } PaintRgn( oldframe ); // erase the rectangle Somebody was asking about doing color hilighting under the inverted rectangle, like the Finder appears to do. The trick is that the Finder does the hiliting just before it draws over the hilited icon. So, (as far as I can tell), at each step, you: figure out the new rectangle. hilite anything which is now included, but wasn't before. draw the difference between the frames. dehilite anything now not included, which was before. -- Garth Dickie -- Math Graduate Student? -- dickie@math.wisc.edu
stevec@Apple.COM (Steve Christensen) (06/06/91)
jcav@quads.uchicago.edu (john cavallino) writes: >In article <53513@apple.Apple.COM> stevec@Apple.COM (Steve Christensen) writes: >>[...about doing rubber-banding, to which John writes...] > >All of the futzing around to create the rectangle from the points can be >eliminated if you use the Quickdraw procedure _Pt2Rect (IM I-175). I knew that it existed, but I must've been suffering a temporary case of blindness when perusing those pages in Inside Mac, so I did it the hard way. Also, in a separate message, it was pointed out the check to see if the mouse moved should be "if ((newPt.v != lastPt.v) || (newPt.h != lastPt.h))" instead of "&&". Brain-deadness on my part, I guess... steve -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Steve Christensen Never hit a man with glasses. stevec@apple.com Hit him with a baseball bat.