englhq@jetson.uh.edu (04/20/91)
I'm working through the window techniques in Huxham, Burnard and Takatsuka's USING THE MACINTOSH TOOLBOX WITH C, and I'm stuck at the GrowWindow function. The code goes like this: case inGrow: newSize=GrowWindow(whichWindow,theEvent.where,&limitRect); SizeWindow(whichWindow, LoWord(newSize),HiWord(newSize),0xff); contRgnHnd=theWindowRec.contRgn; tempRect=(*contRgnHnd)->rgnBBox; EraseRect(&tempRect); DrawGrowIcon(theWindow); break; What happens is, the outline of the scroll bars and size box remain in the middle of the window. i.e. It seems that the EraseRect isn't doing what I think it's supposed to. The maddening part of this is that when I step through with the debugger everything performs as advertised; tempRect has the correct coordinates and the content region is erased just fine. WHAT IS GOING ON HERE?? As soon as I remove the breakpoint, the window goes back to its old tricks. Any advice is greatly appreciated. Duane Franklet englhq@jetson.uh.edu
Henry_Van_Tunen@mindlink.bc.ca (Henry Van Tunen) (04/22/91)
The content region of the window is in global coordinates. It is simpler to use the window's portRect. In Pascal use: EraseRect (whichWindow^.portRect); Hank van Tunen
dedreb@arco.com (Richard Beecher) (04/22/91)
In article <9190.2810258e@jetson.uh.edu> englhq@jetson.uh.edu writes: >I'm working through the window techniques in Huxham, Burnard and Takatsuka's >USING THE MACINTOSH TOOLBOX WITH C, and I'm stuck at the GrowWindow function. >The code goes like this: > >case inGrow: > newSize=GrowWindow(whichWindow,theEvent.where,&limitRect); > SizeWindow(whichWindow, LoWord(newSize),HiWord(newSize),0xff); > contRgnHnd=theWindowRec.contRgn; > tempRect=(*contRgnHnd)->rgnBBox; > EraseRect(&tempRect); > DrawGrowIcon(theWindow); > break; > >What happens is, the outline of the scroll bars and size box remain in the >middle of the window. i.e. It seems that the EraseRect isn't doing what I >think it's supposed to. > Can't say that I know exactly what is happening here, but I wonder if a simpler approach would fix the problem. In the above code, you are referencing whichWindow, theWindowRec, and theWindow. How about trying the following code? case inGrow: newSize=GrowWindow(whichWindow,theEvent.where,&limitRect); EraseRect(&whichWindow->portRect); SizeWindow(whichWindow, LoWord(newSize),HiWord(newSize),0xff); DrawGrowIcon(whichWindow); break; Here, I only reference whichWindow. Also, for aesthetic reasons, I EraseRect before resizing the window. I think Apple also recommends this in the user interface guidelines (IM-1 section on Window Manager?). Erasing the window's portRect should accomplish the same thing as erasing its content region. Ah hah! I might be on to something hereQthe window's content region is expressed in global coordinates...its portRect is expressed in local coordinates. This might be the source of your problem. Essentially, you are erasing a rectangle that is outside your window's clipRgn. So if you want to stick with your original code, converting tempRect to local coordinates might fix your problem. Good luck! --------------- Richard Beecher dedreb@arco.com ---------------
wdh@well.sf.ca.us (Bill Hofmann) (04/24/91)
In article <9190.2810258e@jetson.uh.edu> englhq@jetson.uh.edu writes: >case inGrow: > newSize=GrowWindow(whichWindow,theEvent.where,&limitRect); > SizeWindow(whichWindow, LoWord(newSize),HiWord(newSize),0xff); > contRgnHnd=theWindowRec.contRgn; > tempRect=(*contRgnHnd)->rgnBBox; > EraseRect(&tempRect); > DrawGrowIcon(theWindow); > break; > >What happens is, the outline of the scroll bars and size box remain in the >middle of the window. i.e. It seems that the EraseRect isn't doing what I >think it's supposed to. Yes. Rather, you aren't quite clear on what the responsibilities of your application are. There are several problems with this code. 1. GrowWindow returns 0 if the user doesn't actually move the mouse before releasing the mouse button. So your code will do funny things in this case. Only call the rest of the code if GrowWindow returns non-zero 2. SizeWindow's last argument is a Boolean, it's safer to use TRUE or FALSE. This isn't what's causing a problem. 3. **YOU** are responsible for moving scrollbars. I don't see code to do this. 4. If SizeWindow's last argument is TRUE, the area that is **newly exposed** by the resize is accumulated into the window's update region. Your problem comes because the scrollbars and the grow icon aren't **newly exposed** when the window is made bigger. When the window is made smaller, **nothing** is newly exposed. The entire Toolbox makes NO assumptions about what you put in your content. If you want portions of your content redrawn, you must invalidate them yourself. 5. BTW, there shouldn't ever really be a reason to use the contentRgn, you can use the portRect. As the previous respondent points out, contentRgn is in global coordinates, and all drawing is done in local coordinates, which are the coordinates portRect is in. 6. Here's a sample inGrow: case inGrow: { /* I've put variables here just for clarity */ /* I'm assuming wp is the window's WindowPtr, event.where * is the event record's mouse loc, in global coords */ long result; Rect bounds; Rect inval; SetRect(&bounds, 50,50, 500,500); if (result = GrowWindow(wp, event.where, &bounds)) { /* First, invalidate the area that the grow icon takes before */ SetPort(wp); inval = wp->portRect; inval.left = inval.right-15; inval.top = inval.bottom-15; InvalRect(&inval); /* Then, size the window */ SizeWindow(wp, LoWord(result), HiWord(result), true); /* Then, invalidate where the grow icon now is, and move scrollbars */ inval = wp->portRect; inval.left = inval.right-15; inval.top = inval.bottom-15; InvalRect(&inval); /* I'm assuming the vscroll and hscroll are the 2 scroll bars. */ /* You figure out how to get them. You might put them in a * data structure you store in the window's refCon with * SetWRefCon */ HideControl(vscroll); MoveControl(vscroll, wp->portRect.right-15, wp->portRect.top-1); SizeControl(vscroll, 16, (wp->portRect.bottom-14) - (wp->portRect.top - 1)); ShowControl(vscroll); inval = (*vscroll)->contrlRect; ValidRect(&inval); /* ShowControl draws, don't need to redraw */ HideControl(hscroll); MoveControl(hscroll, wp->portRect.left-1, wp->portRect.bottom-15); SizeControl(hscroll, (wp->portRect.right-14) - (wp->portRect.left - 1), 16); ShowControl(hscroll); inval = (*hscroll)->contrlRect; ValidRect(&inval); /* ShowControl draws, don't need to redraw */ } break; If you don't have scrollbars, you'll need to invalidate the entire area where they'd be, both before and after the SizeWindow. HideControl invals where the control is after it erases the rect, so it's taken care of in this case. This code is the minimum to avoid unnecessary redraws. You don't need to EraseRect, because your update routine should do that immediately after the BeginUpdate call. Similarly, DrawGrowIcon belongs only 2 places: in activate and update. In activate, it shows the changed state of the window, and in update, it redraws what needs to be drawn. Hope this helps. -Bill Hofmann