FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

WINDOWS

Better understand refreshing


Some time ago a question was posed to this list concerning limiting the updating of a window to the region that needed it and no more.

I responded with something like

rgn& = [WINDOW(_wndPointer)+_visRgn]

would yield the region that required updating. Someone else responded with something like...

that's not right - that gives you the window's visible region - what you want is

rgn& = [WINDOW(_wndPointer)+_updateRgn]

but its been clobbered by the time you get a window update event in a DIALOG function so you have to go through a low level EVENT routine doing

your own BEGINUPDATE and ENDUPDATE calls.

Wellllll... I know I didn't imagine what I had read nor do I make it up as I go along ;-) so I found some passages from the FBII documentation that might be relevant...

On page 300 of the FBII Handbook it says "In the routine that updates this window, check if drawing is going to the _visRgn. The handle to the _visRgn is returned as follows:

tgnHndl& = [WINDOW(_wndPointer)+_visRgn]

Drawing objects that aren't in this region wastes time." Further, on page 20 of the FBII Program Generator manual there is a rationale for this statement...

"FutureBASIC starts with a command that swaps the window's visible region (the part that you can see on the screen) with the clobbered region. If the Update clobbered region only box is checked in the Program Generator, it calls upon the Program Generator and your application to do any necessary drawing in the window. At that point, it is not possible to draw in any other section of the window because it was not previously part of the clobbered region. This is good, because existing sections are not erased and redrawn when only a tiny portion of the window needs updating.

If this box is not checked, FutureBASIC handles drawing that lies in its own personal realm of responsibility (edit fields, buttons, and so on) and reinstates the original visible region. Then it calls upon your application to draw after it has made the entire window available for your use. While this is sometimes desirable, it often causes flicker from unnecessary erasure and drawing."

I'm presuming that checking the "update clobbered region only" box in PG is (at least) similar to using _updateVisRgn as an attribute when a window is created in FB. If that's so then it seems to me that the appropriate region to update in your DIALOG routine when you get a window update event is, indeed, [WINDOW(_wndPointer)+_visRgn]. If that's not so, then my answer was wrong and I apologize for the misdirection.

Now, if you want to, you can process the update events in a low level EVENT function doing your own BEGINUPDATEs and ENDUPDATEs but I still contend that you can update just the _visRgn in your DIALOG routine if you specify _updateVisRgn when you define your window. By the way, I have been programming it this way for some time and it seems to work.

Charlie Dickman


That may well be the case. Frankly, I have never used the _updateVisRgn attribute before, because I could never find a good explanation for what it's for: but what you've said makes sense, and I'll bet that's what _updateVisRgn does. I'm not a PG person, but I'll bet that checking the "update clobbered region only" box just causes a window to be built with the _updateVisRgn attribute.

Your quote about swapping the visible region with the "clobbered region" (a.k.a. the update region) is exactly what BEGINUPDATE does. ENDUPDATE swaps them back again, and then sets the update region to an empty region. So, I'll bet that FB works internally as follows, when HANDLEVENTS detects that a window needs refreshing:

If _updateVisRgn is set:
BEGINUPDATE
Redraw button's, etc.
Call User's "DoDialog" FN for other updating
ENDUPDATE

If _updateVisRgn is _not_ set:
BEGINUPDATE
Redraw button's, etc.
ENDUPDATE
Call User's "DoDialog" FN for other updating

Rick


Hi all. I'm writing two programs; one in PG, and one in plain vanilla FB.

In one instance(the PG project), I'm hiding the menubar until the mouse is in the menubar region; and hiding it again when it's not.

Having the Control Strip on at the same time, I get two _wUpdate events when I hide the menu bar(it seems to hide the control strip automatically, which is nice.); but for speed purposes, I can't see redrawing the whole screen(copybitting the entire screen) when I can just copybit the coordinates that need refreshing; saving valuable time...

pretty much the FB project has an open-file-dialog window in front of the main window, and I just want to update those coordinates, again.

Terence Jordan


The address of the region of the window that requires updating is given by [WINDOW(_wndPointer)+_visRgn] so, if rgn& = [WINDOW(_wndPointer)+_visRgn] then rgn&+_rgnBBox is the address of the rect containing the region and you can use this rect to COPYBITS just what needs updating.

Charlie Dickman


Actually, the visRgn represents the region of the window that's visible, not the region that needs updating. The region that needs updating is given by:

rgnHandle& = [WINDOW(_wndPointer)+_updateRgn]

But there's still a problem--FB does a certain amount of updating for you (when you call HANDLEEVENTS), and by the time your dialog-handling FN gets the _wndRefresh event, FB has already set the update region to an empty region.

If you want to find out the region that actually needs updating, I can think of a couple of possibilities:

1. Make a copy of the window's update region just _before_ you call
HANDLEEVENTS. Like so:

(assumes gUpdtRgn& was created via gUpdtRgn& = FN NEWRGN):

CALL COPYRGN(wptr&.updateRgn&, gUpdtRgn&)
HANDLEEVENTS

Then you can just refresh the region defined by gUpdtRgn&.

Or:

2. Instead of trapping _wndRefresh events with your ON DIALOG function, trap _updatEvt events with your ON EVENT function. This lets your program detect the event before FB has a chance to mess with the update region. You would do it something like this:

LOCAL FN DoEvent
  eventPtr& = EVENT
  type = eventPtr&.evtNum%
  SELECT CASE type
    CASE _updatEvt
      wptr& = eventPtr&.evtMessage&
      id = FN GetWindowID(wptr&)
      CALL BEGINUPDATE(wptr&)
      FN RefreshWindow(id)
      CALL ENDUPDATE(wptr&)
      eventPtr&.evtNum% = _nil 'so FN DoDialog won't act on it
  END SELECT
END FN

The BEGINUPDATE and ENDUPDATE calls manipulate regions so that anything you draw in FN RefreshWindow will be clipped to the actual region that was clobbered, and they make sure that the Update Region gets cleared to an empty region (indicating that "this window has been refreshed"). FN GetWindowID returns the FB window id when you give it the window's pointer (I leave the implementation as an exercise for the reader).

Rick