From: casgrain@ERE.UMontreal.CA (Casgrain Philippe)
Newsgroups: comp.sys.mac.programmer
Subject: Default buttons in dialogs (R)
Keywords: Default button, FilterProc
Date: 7 Jan 93 05:39:58 GMT
Organization: Universite de Montreal
Rganization: Universite de Montreal

In article <880840m.29.726366713@axe.acadiau.ca> 880840m@axe.acadiau.ca (MICHAEL
 ALEXANDER MCKAY) writes:
>
>Whenever I make a dialog box with ResEdit, my "OK" buttons, which are always
>the number 1 button, fail to show up in my app with the heavy outline around
>them. What am I doing wrong?
>
>
The #1 button is drawn with a heavy outline only in alert boxes.  If you want
to implement that behaviour in a dialog box, you have two options:

1) You can have an additional item in your dialog box, a 'PICT' you drew in
MacDraw or something, which looks like a heavy outline.  Note that its
number must be _lower_ than the button you want to be outlined, since the
Dialog Manager draws overimposed items with the latest on top.  So the 'default'
button won't be #1.
        So that's easy to do, but not a very nice programming practice.

2) You can design your own FilterProc to use when calling ModalDialog (instead
of nil).  I personally favor this approach, as knowledge of how a FilterProc
works is quite valuable indeed.  Here's how it's done:

{ I presume you have a valid DialogPtr in myDlg }
...
{ Somewhere in your program, you call ModalDialog: }
	ModalDialog(myDlg, @MyFilterProc);
...
{ MyFilterProc is a top-level (i.e. not internal to another procedure or
function, but it's fine in a unit) function which has the following structure:}

 function MyFilterProc (dlg: DialogPtr; 
 			var event: EventRecord; 
			var itemHit: Integer): Boolean;
{ We must implement the standard ModalDialog "features": the default
(#1) button gets activated when the user presses Enter or Return, and
the #2 when he/she presses Escape or, as a nice touch, Command-Period}

  const
   kPeriod = 46;
   kEnter = 3;
   kReturn = 13;
   kEscape = 27;
{ Note that I also filter for when the cursor enters item # 3, an EditText
item, it gets changed into an I-Beam cursor }
   kEditTextItem = 3;
  var
   iKind, radius: Integer;
   iHandle: Handle;
   iRect: Rect;
   key: Char;
   dumBool: Boolean;
   mouseLocation: Point;
   theWindow: WindowPtr;
   part: Integer;
 begin
  dumBool := False; { By default, we don't handle the event, thus leaving
			it to ModalDialog.  We could process the event and
			delete it, or leave it for further processing by
			ModalDialog}

  case event.what of
   nullEvent: 
{ This code handles the cursor-changing behaviour.  Extend as needed! }
    begin
     GetDItem(dlg, iValueItem, iKind, iHandle, iRect);
     GetMouse(mouseLocation);
     if (PtinRect(mouseLocation, iRect)) then
      SetCursor(GetCursor(IBeamCursor)^^)
     else
      SetCursor(arrow);
    end;{nullEvent}

   keyDown, autoKey:
{ This filters for key presses in the dialog box } 
    begin
     key := Char(BAnd(event.message, charCodeMask));
     if (BAnd(event.modifiers, cmdKey) <> 0) then
{ a command-key combination was created and sent }
      begin
       if Ord(key) = kPeriod then
       begin
       itemHit := Cancel;
{ FlashDialogItem is a generic procedure that hilites (sets its CtlValue to 1)
a control for exactly 1/6th of a second :-) }
       FlashDialogItem(dlg, itemHit);
       dumBool := True;
       end;{if key}
      end{if BAnd(event.modifiers, cmdKey)}
     else
      begin
       if (Ord(key) = kReturn) or (Ord(key) = kEnter) then
       begin
       itemHit := OK;
       FlashDialogItem(dlg, itemHit);
       dumBool := True;
       end;{if}
       if (Ord(key) = kEscape) then
       begin
       itemHit := Cancel;
       FlashDialogItem(dlg, itemHit);
       dumBool := True;
       end;{if}
      end;{else}
    end;{keyDown, autoKey}

   updateEvt:
{ Here's the part you've been waiting for! }
{ Thanks to Keith Rollin and Scott Knaster for their book, "Macintosh
Programming Secrets" for all the pointers I found there! } 
    begin
     SetPort(dlg);
     GetDItem(dlg, OK, iKind, iHandle, iRect);
     InsetRect(iRect, -4, -4);
     radius := (iRect.bottom - iRect.top) div 2;
     if (radius > 16) then
      radius := 16;
     PenNormal;
     PenSize(3, 3);
     FrameRoundRect(iRect, radius, radius);

     dumBool := False;
    end;{updateEvt}

  end;{case}
  MyFilterProc := dumBool;
 end;{function MyFilterProc}


Share and enjoy!
Philippe		Casgrain@ere.umontreal.ca 
Newsgroups: comp.sys.mac.programmer