[comp.sys.mac.misc] Centering Dialog Boxes on the Macintosh

talcott@nunki.usc.edu (Adam Talcott) (09/04/90)

Over the summer I began to learn to use the Macintosh Toolbox.  I have begun
writing my first piece of Macintosh software and have stumbled into one
problem.  I understand that Apple's Interface Guidelines requires dialog boxes
to be centered horizontally and have one-third of the screen above the dialog
and two thirds of the screen below.  My problem is I can center the border of
the dialog to conform to these standards, but the contents of the dialog box
do not move!!  What do I do to move this?  The following are the lines of code
I use (in THINK C):

CenterDialog( whichDialog )
DialogPtr	whichDialog;
{
   Rect   dialogRect;
   int    dialogWidth, dialogHeight, screenWidth, screenHeight;
	
   if ( whichDialog != NIL_POINTER )
   {
     screenWidth = ( screenBits.bounds ).right - ( screenBits.bounds ).left;
     screenHeight = ( screenBits.bounds ).bottom - ( screenBits.bounds ).top;
     dialogWidth = ( whichDialog->portRect ).right - ( whichDialog->portRect ).left;
     dialogHeight = ( whichDialog->portRect ).bottom - ( whichDialog->portRect ).top;
		
     /* Center horizontally */
     ( whichDialog->portRect ).left = ( screenWidth - dialogWidth ) / 2;
     ( whichDialog->portRect ).right = ( whichDialog->portRect ).left + dialogWidth;
		
     /* Place one-third of screen above, two-thirds of screen below dialog */
     ( whichDialog->portRect ).top = ( screenHeight - dialogHeight ) / 3;
     ( whichDialog->portRect ).bottom = ( whichDialog->portRect ).top + dialogHeight;
   }
}

Any help is greatly appreciated (if you didn't understand, e-mail and I'll
attempt to explain it better).



-- 
| Adam Talcott                               | Not a bad bit of rescuing,    |
| talcott@nunki.usc.edu                      | huh?  You know, sometimes I   |
| Electrical Engineering (Computers) Senior  | even amaze myself.            |
| University of Southern California          |                    --Han Solo |

dolf@fwi.uva.nl (Dolf Starreveld) (09/06/90)

talcott@nunki.usc.edu (Adam Talcott) writes:
> ... Deleted ...
> and two thirds of the screen below.  My problem is I can center the border of
> the dialog to conform to these standards, but the contents of the dialog box
> do not move!!  What do I do to move this?  The following are the lines of code
> I use (in THINK C):
I cleaned this up a bit and inserted modifications in the right place(s).

> CenterDialogwhichDialog
> DialogPtr	whichDialog;
> {
>    Rect   dialogRect;
>    int    dialogWidth, dialogHeight, screenWidth, screenHeight;
-->  int    spaceWidth, spaceHeight;
> 	
>    if whichDialog != NIL_POINTER
>    {
>      screenWidth = screenBits.bounds.right - screenBits.bounds.left;
>      screenHeight = screenBits.bounds.bottom - screenBits.bounds.top;
>      dialogWidth = whichDialog->portRect.right - whichDialog->portRect.left;
>      dialogHeight = whichDialog->portRect.bottom - whichDialog->portRect.top;
> 		
-->    /* Compute amount of space on both sides */
-->    spaceWidth = screenWidth - dialogWidth;
-->    spaceHeight = screenHeight - dialogHeight;
-->
-->    /* Now move the dialog window to centered position according to rules */
-->    MoveWindow(whichDialog,
-->	  screenBits.bounds.left + spaceWidth / 2, /* Halfway horiz. */
-->	  screenBits.bounds.top + spaceHeight / 3);/* 1/3 from top */
>    }
> }

There is a clear, but sometimes vague relationship between a window's
portRect, the boundsRect of its portBits and the position of a window.
Assume that screenBits.bounds are (0,0) - (large, large).
If a window's top left corner is at 100, 100 in global (screen) coordinates,
its bitmap (portBits) is still the screen itself. On the other hand, the
bounds rectangle of the bitmap relative to the window's top left corner is
now (-100, -100) (large - 100, large - 100). This way, when QuickDraw draws
anything in the window's bitmap it appears at the right place. Drawing at 0,0
in this bitmap, will actually by a place offset 100 pixels in both way from
the top left of the screen bitmap and will hence appear in the top left corner
of the window.
However, all drawing in a grafport occurs within the rectangle defined by
portRect, expressed in the coordinates of the portBits.bounds rectangle.

If you directly change the portRect coordinates you are effectively changing
the coordinate system for all subsequent drawing in that grafPort.
The window itself is drawn with another grafport, the so called window
manager grafport, which ytou didn't change. Besides, you can not move
a window on the screen, just by changing some coordinates.
As a side effect of your change, subsequent drawing inside the window
will occur in unexpected locations. You can force this drawing by overlaying
with something else, but since you are in a dialog, you'l;l probably need
an FKEY that pops up a window to do that.

The reason I add screenBts.left, resp .top in the above MoveWindow call is
that thos are not necessarily 0. In multiy screen environments the may
be different.
If you really want things to be all right you should also take the menu bar
and its heigth into account. Note however, that in multiscreen environments
not all screens have one (but since you center against screenBits.bounds you
will always center on the main screen) and the a menubar is not always 20
pixels high, but that's another subject.

--dolf

--
Dolf Starreveld  Phone: +31 20 592 5056/5022 (FAX: 5155), TELEX: 10262 HEF NL
EMAIL:           dolf@fwi.uva.nl (dolf%fwi.uva.nl@hp4nl.nluug.nl)
SNAIL:           Dept. of Math. and Computing Science, University of Amsterdam,
                 Kruislaan 409, NL-1098 SJ  Amsterdam, The Netherlands

lorin@litsun.epfl.ch (Ronan-Yann Lorin) (09/13/90)

The problem is that you must use MoveWindow to move the dialog
instead of using things like (whichDialog->portRect).left = ...

	Ronan.

dwal@ellis.uchicago.edu (David Walton) (09/14/90)

In article <378@disuns2.epfl.ch> lorin@litsun.epfl.ch (Ronan-Yann Lorin) writes:
>The problem is that you must use MoveWindow to move the dialog
>instead of using things like (whichDialog->portRect).left = ...
>
>	Ronan.

I'm not sure what post this is in reference to, but it's quite easy
to center a dialog (modal or otherwise) just by using the boundsRect
field in the DialogTemplate data structure.  For example:
	
    var mydialog:DialogTHndl;


	mydialogtemplate:=DialogTHndl(GetResource('DLOG', kdialogID));
	HNoPurge(mydialogtemplate);
	HLock(mydialogtemplate);{  if you do any memory stuff  }
	CenterRect(mydialogtemplate^^.boundsRect, screenRect);
	.
	.
	.
	mydialog:=GetNewDialog(kdialogID, nil, pointer(-1));
	

When you call GetNewDialog (assuming you've done the math correctly in
CenterRect), your dialog should be centered.
--
David Walton            Internet: dwal@midway.uchicago.edu
University of Chicago   {  Any opinions found herein are mine, not  }
Computing Organizations {  those of my employers (or anybody else). }

CXT105@psuvm.psu.edu (Christopher Tate) (09/15/90)

Apple's Human Interface Notes discuss the appropriate positioning of
alerts and dialogs.  In summary, you place the dialog such that it is
centered left-to-right, and placed top-to-bottom such that 1/3 of the
remaining Y-axis space on the screen (excluding what's taken up by the
dialog itself) is above the dialog.

This is pretty easy to accomplish; somebody already posted a method
for twiddling with the dialog's definition before you display it, using
DialogTHndl's, etc.

(Followups directed to comp.sys.mac.programmer)

-------
Christopher Tate                        |   "Oh wow:  not only is 57
                                        |    prime, but it's also
Bitnet: cxt105@psuvm                    |    divisible by three!"
Uucp: ...!psuvax1!psuvm.bitnet!cxt105   |
Internet: cxt105@psuvm.psu.edu          |    - a very sincere math major