From: keith@taligent.com (Keith Rollin)
Subject: Re: Spurious invalidation
Followup-To: comp.sys.mac.programmer
Organization: Taligent
Date: Tue, 10 Nov 1992 22:22:10 GMT

In article <1992Nov10.155449.14655@alw.nih.gov>, fixer@faxcsl.dcrt.nih.gov
(Chris Spiral Catfish Tate) wrote:
> 
> Thanks to everyone who responded, either on the net or via email.
> 
> In summary, what's happening is that indeed, SetCTitle() is *both* redrawing
> the control with its new title *and* causing an update event in the dialog.
> I'm not quite clear on why it has to generate the update event, but that's
> beside the point.

I looked into this when working on "Macintosh Programming Secrets." What
happens when you call SetCTitle is the following:

    _HideControl
    change the title of the control
    _ShowControl

_HideControl calls _EraseControl and then invalidates the area under the
control's bounds. This is correct behaviour for _HideControl. When
_ShowControl is called, the control is redrawn, but the area is still
marked invalid in the window's update region. The second drawing of the
control is the dialog manager responding to the update.

> If you're absolutely sure you don't have to update anything else when the
> control changes its title, you can also call ValidRect() on its rectangle
> immediately following the call to SetCTitle(), and the update will be
> "cancelled."

Right. Here's the section for MPS that deals with this issue. Note that it
assumes that, if a dialog item is not a static or edit text item, that it
is a control. This is not a valid assumption in all cases (as in the
original poster's, who had user items in his dialog).

/*******************************************************************************

	SetDialogItemTitle

	Change the text associated with a particular dialog item. This is a little
	tricky since there are two ways to change the text. If you are dealing
	with an EditText or StatText (static text) item, you must call SetIText.
	If you are dealing with a dialog item that is backed up by a Control
	Manager control (like a simple button, radio button, or checkbox), you
	must call SetCTitle.

	We determine what kind of dialog item we are dealing with by calling
	GetDItem. Returned in the kind parameter is a number that identifies
	what sort of item we are handling. First, we strip off the upper bit,
	which identifies the item as being enabled or disabled. Once that bit is
	removed, we can examine the kind of the item and act accordingly.

	Notice the special handling we give to controls when we call SetCTitle.
	This is to take care of excessive flashing as Online Companion puts it.
	When you call SetCTitle, the control manager first calls HideControl to
	remove the control with its old text from the screen. It then changes the
	controls title in the ControlRecord, and reshows the control by calling
	ShowControl. At this point, the control is properly shown on the screen
	with its correct, new title.

	However, theres a little time bomb lurking in the works. When HideControl
	was called, the Control Manager called InvalRect on the area the control
	occupied. Even though ShowControl was later called on the same area and
	everything is drawn correctly, that rectangle is still marked as invalid
	and is incorporated into the update region for the dialog. The event loop
	at the heart of ModalDialog will then get an update event for that area
	and redraw the button _again_! This can cause the button to flicker and
	flash more than we would like. We already know that that area is
	adequately drawn, so we tell the Event Manager to hoof it by validating it
	with a call to ValidRect.

*******************************************************************************/
void	SetDialogItemTitle(DialogPtr dlg, short item, Str255 *newTitle)
{
	short	iKind;
	Handle	iHandle;
	Rect	iRect;

	GetDItem(dlg, item, &iKind, &iHandle, &iRect);
	iKind &= ~itemDisable;				// Strip off the enable/disable bit
	if ((iKind == statText) || (iKind == editText)) {
		SetIText(iHandle, *newTitle);
	} else {
		SetCTitle((ControlHandle) iHandle, *newTitle);
		SetPort(dlg);
		ValidRect(&iRect);
	}
}


-----
Keith Rollin
Phantom Programmer
Taligent, Inc.
Newsgroups: comp.sys.mac.programmer