From: friedman@netcom.com (Greg Friedman)
Subject: Mark Manning: Scrolling Dlogs
Organization: Netcom - Online Communication Services  (408 241-9760 guest) 
Date: Thu, 17 Dec 1992 23:40:08 GMT

Mark - I tried to e-mail this response to you directly, but
mail kept bouncing.  Anyhow, here is additional info on
creating scrolling dlogs.  Hope this helps:

First off - the code I sent you was from one of my first attempts
at Mac programming. If I were writing the same app today, I would
not using scrolling dialogs.  I would use windows and text boxes.
That's one possible solution, though I doubt it would be trivial
for you to convert at this point.

There was a reason that MoveControl didn't work for me. Unfortunately,
I didn't comment on it in the code, and I can't remember why now.

Calling GetDItem/SetDItem is not the solution.  SetDItem expects
a handle to an item in the ditl list, not a control handle. I
would expect it to crash in this case.

Oh yeah, now I remember why I didn't call MoveControl.  MoveControl
erases and redraws controls as they are being moved. It may even
disable them.  It looked very ugly in a scrolling dialog, and not
at all smooth. (Be aware that scrolling dialogs are a WEIRD idea!).
The shift control function I sent you basically does it's own move
control by walking the controlList of a window and shifting each
control by walking the controlList of a window and shifting each
control up a specified number of pixels. It only shifts vertically, so
if you're scrolling horizontally, you'll have to make what should be
obvious changes.

If you are working in a development environment that supports interactive
debuggin, break in shift controls and take a look at the control
handles you are attempting to use when alter the rects.  If they
are bogus, you may have the wrong windowPtr.

Here, in summary, is the sequence that works for me:

Assume a hit on the down button:

SetCtlValue() //increment the ctlValue by your index
ShiftControls() //move all of the controls in the window
                // they won't be redrawn at this point, but their rects
                // will be updated.
SetRect() //set up a local var rect that you want to scroll.
          //make sure to remove the scroll bars from your rect
          //rect.right  = windowRect.right - 15, etc.
ScrollRect() // scroll the rect the correct number of pixels.
SetOrigin() // now set the origin of the rect as I did in the sample
            // code I sent you.  Otherwise dialog item offsets will
            // be screwed and the dlog mgr will draw everything in
           // the wrong place.
SetRect() // set up a new rect that includes everything but the
          // scrollbars.  Relative offsets have changed, so you
          // have to do this again.
ClipRect() // send in the rect you just made. Do this so when you
           // call drawDialog, scroll bars aren't drawn.
DrawDialog() //send in the dlogPtr
ValidRect() // send the windows Rect (get the portRect from the structure
           // pointed to by the GrafPtr

That works for me.  I don't know why you are crashing.  It probably
means you are using a bogus address somewhere along the line.  You'll
have to debug it.  Make sure that you have set the port to the dlog
you want to scroll.  If you aren't calling SetPort() with the dlog
pointer, that could be the source of your problem.  I suggest stepping
through the code and looking at the window pointers and control handles
you are passing around.  Make sure they point to the structures you
think they do.  If you can't tell which control is which, put some
identifying information into the refCon field of each control.  During
the shift process, check it out in your source level debugger or
MacsBug.  Happy bug hunting!

Let me know if I can answer any other ?'s.  I'm happy to try.  

Best,

Greg 
Newsgroups: comp.sys.mac.programmer