sam@neoucom.UUCP (Scott A. Mason) (05/08/89)
I need some help from some of you more experienced Mac programmers. Although I am well versed in C, I am just starting to program in the Macintosh environment. I have a window which I use QuickDraw routines to draw characters. (Not a text edit window, that is) I am have difficulties responding to an update event. I have IM volumes and several different books, but none of them sufficiently covers the use of an offscreen buffer to store window info for updating. How does one set up an offscreen buffer so that CopyBits may be used to refresh the window when responding to an update event? -- -------------------------------------------------------------------------------- "If it ain't broke, don't fix it," and certainly don't blame me. UUCP: {pitt, scooter, hal, cwjcc}!neoucom!sam INTERNET: sam@neoucom.UUCP Scott A. Mason, Coordinator of Systems Operations, NEOUCOM
ksitze@nmsu.edu (Kevin Sitze) (05/10/89)
In article <sam@neoucom.UUCP's message of 8 May 89 04:17:52 GMT> >I have a window which I use QuickDraw routines to draw characters. (Not >a text edit window, that is) I am have difficulties responding to an >update event. I have IM volumes and several different books, but none of >them sufficiently covers the use of an offscreen buffer to store window >info for updating. > >How does one set up an offscreen buffer so that CopyBits may be used to >refresh the window when responding to an update event? This is really a rather simple procedure. The idea is to draw into an offscreen port and then CopyBits the wanted information to the desired window. To setup an offscreen port for drawing, you can do something like this... In Pascal (LSP): Function SetupPort : GrafPtr; var tmpPort, myPort : GrafPtr; begin GetPort(tmpPort); { Need to allocate memory for the port } myPort := GrafPtr(NewPtr(sizeof(GrafPort)); { -- Error checking for nil pointer goes here -- } { Create the internal structures for the port } OpenPort(myPort); { Now we need to set aside enough memory to draw into } with myPort^.portBits do begin baseAddr := NewPtr(rowBytes * (bounds.bottom - bounds.top)); { -- Error checking for nil pointer goes here -- } { Don't need to initialize any of the rest of the fields in } { the port because Quickdraw has done all we need already. } end; { And return the resulting port, voila, an offscreen graph port! } SetPort(tmpPort); SetupPort := myPort; end; or, for them (LS)C buffs... #define myBM myPort->portBits GrafPtr SetupPort() { GrafPtr tmpPort; register GrafPtr myPort; GetPort(&tmpPort); myPort = (GrafPtr) NewPtr(sizeof(GrafPort)); /* -- Error checking for nil pointer goes here -- */ /* Create the internal structures for the port */ OpenPort(myPort); /* Now we need to set aside enough memory to draw into */ myBM.baseAddr = NewPtr(myBM.rowBytes * (myBM.bounds.bottom - myBM.bounds.top)); /* -- Error checking for nil pointer goes here -- */ /* And return the resulting port, voila, an offscreen graph port! */ SetPort(tmpPort); return myPort; } #undef myBM There are several problems with the program as it stands above. 1) it does not have any error conditions. 2) It eats up about 6K of the heap everytime it's called (or more if your doing color, but if that's the case, you'll _need_ to look at Macintosh Technote #120) Notice that I saved the current port on entry, this is because I didn't really want SetupPort to change my current graph port. If you don't care, you can remove these lines (but you may never know when you may need them, I spent several hours tracking down a single missing SetPort once...not a pleasant experience.) You can save memory by passing a window to the procedure and then resizing the port to the window size. If you do this though, you have to resize the port everytime you resize the window, something of a bother. Enough of this, let's describe how to draw, etc. The procedure to draw into the newly created port may look something like this (in Pascal): Procedure DrawInMyPort( port : GrafPtr ); var tmpPort : GrafPtr; begin GetPort(tmpPort); SetPort(port); { various Quickdraw calls here } SetPort(tmpPort); end; And in C... DrawInMyPort(port) GrafPtr port; { GrafPtr tmpPort; GetPort(&tmpPort); SetPort(port); /* various Quickdraw calls here */ SetPort(tmpPort); } Pretty easy huh? The way the port is setup, you have the entire 'screen' to draw into, we'd have to do a few more calls if the window are 'larger' than the screen (e.g. paint programs). Finally, we want to do an update event, drawing from the offscreen port to a window: Procedure UpdateWind( wind : WindowPtr; port : GrafPtr ); var tmpPort; begin GetPort(tmpPort); SetPort(wind); BeginUpdate(wind); CopyBits(port^.portBits, wind^.portBits, port^.portRect, wind^.portRect, srcCopy, nil); EndUpdate(wind); SetPort(tmpPort); end; or #define NIL (0L) UpdateWind(wind, port); WindowPtr wind; GrafPtr port; { GrafPtr tmpPort; GetPort(&tmpPort); SetPort(wind); BeginUpdate(wind); CopyBits(&port->portBits, &wind->portBits, &port->portRect, &wind->portRect, srcCopy, NIL); EndUpdate(wind); SetPort(tmpPort); } These are all pretty much basic routines here but they should work. If you have any more questions, you might refer to the Macintosh technical notes. (You might be able to find the most recently distributed tn's on comp.mac.sources (comp.sources.mac?)) Specifically, TN#120 (which I know was uploaded recently) Hope this helps! -Kelesi -- ------------------------------------+------------------------------- From the Macintosh of: Kevin Sitze | Disclamer: Who the heck needs | a disclamer? After all, Dan EMail: ksitze%NMSU.edu | Quayle doesn't. SMail: 601 S. Melendres +------------------------------- Las Cruces, NM 88005 | "We have the answers, the ------------------------------------+ trouble lies in finding the "The difference between intelligence| questions..." and stupidity is that intelligence | "The information is there, has a limit." - anonymous | finding it is another story." The dolt confuses you -- more -- | - Any consultant ------------------------------------+-------------------------------