stdFilterHacking.c

/*
    File:       stdFilterHacking.c
 
    Contains:   For those of you who have been using the new Standard Dialog Filter
                in 7.0 and later (documented in tech note #304, which has been renamed 
                to MM.{something}.PendingUpdates) you may have encountered some odd behaviour
                when you bring up another dialog or alert in front of
                a dialog using the standard filter.
 
                If you have dimmed (de-hilited, disabled) the OK or Cancel button and
                bring up a dialog on top, when you dismiss the top dialog the dialog
                where the OK button was dimmed will suddenly have the OK button enabled!
 
                This is a behaviour of the standard filter.  When the standard filter
                gets an Activate event, it will automatically enable the default and
                cancel buttons (set with SetDialogDefaultItem and SetDialogCancelItem), it
                is assuming that the only reason those buttons were disabled was because they
                were in a deactivated window.
 
                The filter has no state-saving routines or caches to remember what the old state
                of the buttons was, so it just slams them active again.
 
                This may not be what you want.  If you disable an OK or Cancal button, use the
                standard filter, and bring another dialog or alert up on top of that dialog, 
                you need to add a little extra code in your own filter to handle that
                situation.
 
                The code is included here, look in the filterIt function included in 
                stdFilterHacking.c.
 
                Better Living Through Code.
                
    Written by:     
 
    Copyright:  Copyright © 1984-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/10/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#include <Dialogs.h>
#include <Controls.h>
#include <QuickDraw.h>
#include <Windows.h>
#include <ToolUtils.h>
#include <OSUtils.h>
#include <Menus.h>
#include <Fonts.h>
#include <resources.h>
#include <Sound.h>
#include <Traps.h>
#include <Gestaltequ.h>
#include <Memory.h>
#include <Scrap.h>
#include <TextEdit.h>
 
/* prototypes */
ControlHandle   SnatchHandle(DialogPtr thebox, short theGetItem);
void            ToggleCheckBox(DialogPtr myDialog,short theItem);
pascal   Boolean  filterIt(DialogPtr inputDialog, EventRecord *myDialogEvent, short *theDialogItem);
 
 
enum  {
    /* ok and cancel are already defined in Dialogs.h */
    kMessUpItem = 3,
    kHiliteOK
};
enum  {
 
    kSampleDialog = 128, 
    kMessUpAlert
};
 
ModalFilterUPP gModalFilterUPP;
 
void main(void)
{
    DialogPtr myDialog = nil;                               /* the dialog wee're using */
    short hitItem = 0;                                      /* hitItem for ModalDialog */
 
    /* start up managers */
    InitGraf(&qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(nil);
    InitCursor();
    
    /* set up the UPP for the Modal Dialog filter */
    gModalFilterUPP = NewModalFilterProc(filterIt);     
 
    /* get our dialog */
    myDialog = GetNewDialog(kSampleDialog, nil, (WindowPtr)-1);
 
    SetDialogDefaultItem(myDialog, ok);
    SetDialogCancelItem(myDialog, cancel);
    /* dim the OK button initially */
    HiliteControl(SnatchHandle(myDialog,ok),255);
 
    do {
        ModalDialog(gModalFilterUPP, &hitItem);
        if(hitItem == kMessUpItem){
        /* bring up an alert to obscure the OK button */
        Alert(kMessUpAlert,nil);
        }
        else{
        if(hitItem == kHiliteOK)
        ToggleCheckBox(myDialog,kHiliteOK);     
        HiliteControl(SnatchHandle(myDialog,ok),GetControlValue(SnatchHandle(myDialog,hitItem)) ? 0 : 255);
        
        }
    
    }
    while (hitItem != ok && hitItem != cancel);
   
    DisposeDialog(myDialog);
    InitCursor();                                           /* Init to prevent I-beam from hanging around in some circumstances */
 
 
}
 
 
pascal Boolean filterIt(DialogPtr inputDialog, EventRecord *myDialogEvent, short *theDialogItem)
{
   ModalFilterUPP  theModalProc;  /* address of standard filter */
 
 
   if (/* myDialogEvent->what == activateEvt || */myDialogEvent->what == updateEvt) {
   /* reset the state of the button based on my */
   /* check box.  Use whatever conditions you need to determine the  */
   /* correct highlighting */
    HiliteControl(SnatchHandle(inputDialog,ok),GetControlValue(SnatchHandle(inputDialog,kHiliteOK)) ? 0 : 255);
 
    } 
/* You must still call through the standard filter for things to work, of course */
  GetStdFilterProc(&theModalProc);
  return CallModalFilterProc(theModalProc, inputDialog, myDialogEvent, theDialogItem);
 
}
 
ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
{
    short itemtype;
    Rect itemrect;
    Handle thandle;
    
    GetDialogItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
    return((ControlHandle)thandle);
} /* end SnatchHandle */
 
 
void ToggleCheckBox(DialogPtr myDialog,short theItem)
{
 
SetControlValue(SnatchHandle(myDialog,theItem),GetControlValue(SnatchHandle(myDialog,theItem)) ? false:true);
}