Adding Items to the Print Dialogs
The Print Manager dialog was originally designed to be as generic as
possible so that applications could print without being device- specific.
There are times, however, when an application may need additional
information that is not part of the Print Manager interface before it can
print. The following example describes how to add items to the existing style
and job dialogs.
Apple has guidelines to keep in mind before attempting to modify the print
dialogs.
• Do not change the position of items in the current dialogs. This
means don't delete items from the existing item list or add items in
the middle. Only add items to the end of the list.
• Don't depend on items retaining their positions in the list.
• Don't use more than half the screen height for your items. Apple
reserves the right to expand the items in the standard print dialogs
to fill the top half of the screen.
• If you are adding a lot of items to the dialogs, you should consider
having a separate dialog in addition to the standard print dialogs.
second parameter) to set up the dialog, dialog hook and dialog event filter.
(since the window is initially in visible), then it calls ModalDialog, using the dialog event filter pointed to by the pFltrProc field. When an item is
hit, the pFltrProc's procedure is called and the items are handled
appropriately. When the OK button is hit, the print record is validated. The
print record is not validated if the Cancel button is hit.
To modify the print dialogs, you need to change the PTrDlg record before
the dialog is drawn. You can add items to the list and/or replace the standard
dialog hook and event filters.
The following example is long, yet complete. The Rez source is included,
but if you only have ResEdit, note that the ".rsrc" file consists of a single
resource of type 'DITL' with an ID of 256. The size of the two check boxes
can be found in the Rez source code.
Example
/* Example of how to add items to a Print Dialog Box */
/* Rez source for required resource is included */
/* MacHeaders is used for this example */
/* Rez source */
#if 0
/* use pre processor to avoid nested comments - not allowed by C */
{ /* array DITLarray: 2 elements */
/* [1] */
{8, 0, 24, 112},
CheckBox {
enabled,
"First Box
};
/* [2] */
{8,175, 24, 287},
CheckBox {
enabled,
"Second Box
}
}
};
#endif
#include <PrintTraps.h>
#define nil 0L
#define MyDITL 256 /* resource ID of our DITL to be spliced on to job dialog */
TPPrDlg PrtJobDialog;
pascal void MyJobItems(); [TOKEN:12074] our modal item handler */
THPrint hPrintRec; [TOKEN:12074] handle to print record */ short FirstBoxValue = 0; [TOKEN:12074] value of first additional box */
short SecondBoxValue = 0; [TOKEN:12074] value of our second box */
long prFirstItem; /* save first item here */
long prPItemProc; [TOKEN:12074] store the old itemProc here */
/* prototypes */
pascal TPPrDlg MyJobDlgInit(THPrint);
pascal Boolean PrDlgMain(); [TOKEN:12074] print managers dialog handler */
pascal TPPrDlg PrJobInit(); [TOKEN:12074] get standard print job dialog */
pascal TPPrDlg MyJobDlgInit(); /* our extension to PrJobInit */
short AppendDITL(DialogPtr, short);
pascal void MyJobItems(TPPrDlg, short);
main()
{
SetRect(&myWRect, 50, 260, 350, 340); /* call the routine that does printing */
err = Print();
}
{
/* call PrJobInit to get pointer to the invisible job dialog */ if(!PrDlgMain(hPrintRec, &MyJobDlgInit)) /* this line does all */ return Cancel;
}
pascal TPPrDlg MyJobDlgInit(THPrint hPrint) {
/* this routine appends items to the standard job dialog and
sets up user fields of the printing dialog record TPRDlg
*/
short firstItem;
short itemType;
prFirstItem = firstItem; [TOKEN:12074] save so MyJobItems can find it */
/* set up DITL items - the "First Box" */
GetDItem(PrtJobDialog, firstItem, & itemType, &itemH, &itemBox); /* set up second of the DITL items - the "Second Box" */
GetDItem(PrtJobDialog, firstItem, & itemType, &itemH, &itemBox); /* now patch in the item handler. Save the old item handler
address, so it can be called if one of the standard items
is hit, and put our item handler's address in pItemProc field
*/
prPItemProc = (long)PrtJobDialog->pItemProc;
/* now tell the modal dialog handler where our routine is */
PrtJobDialog->pItemProc = (ProcPtr)MyJobItems; /* PrDlgMain expects a pointer to the modifier dialog to be returned */
return PrtJobDialog;
}
pascal void MyJobItems(TPPrDlg theDialog, short itemNo)
{
short myItem;
short firstItem;
short itemType; [TOKEN:12074] for GetDItem/SetDItem calls */
firstItem = prFirstItem; [TOKEN:12074] saved in myJobDlgInit */
myItem = itemNo - firstItem + 1; /* "localize" item number */
if(myItem > 0) /* if localized item > 0, it is our item */
{
GetDItem( theDialog, itemNo, & itemType, &itemH, &itemBox); switch(myItem)
{
case 1:
/* invert value of FirstBoxValue and redraw it */
FirstBoxValue ^= 1;
break;
case 2:
/* invert value of SecondBoxValue and redraw it */
SecondBoxValue ^= 1;
break;
default:
Debugger(); [TOKEN:12074] error state */ }
}
else
/* chain to standard item handler, whose addr is in prPItemProc */
CallPascal( theDialog, itemNo, prPItemProc);
}
short AppendDITL(DialogPtr theDialog, short theDITLID)
{
typedef struct {
char itmType;
char itmData[];
} DITLItem, *pDITLItem, **hDITLItem;
typedef struct {
short dlgMaxIndex;
DITLItem DITLItems[];
} ItemList, *pItemList, **hItemList;
short *IntPtr;
hItemList hDITL;
pDITLItem pItem;
hItemList hItems;
short firstItem;
short newItems, dataSize, i;
long sizeHandle;
maxRect = ((DialogPeek) theDialog)-> window.port.portRect; offset.v = maxRect.bottom; offset.h = 0;
maxRect.bottom -= 5;
maxRect.right -= 5;
hItems = (hItemList)(((DialogPeek) theDialog)-> items); firstItem = (**hItems).dlgMaxIndex + 2;
newItems = (**hDITL).dlgMaxIndex + 1;
pItem = (DITLItem *)&((**hDITL).DITLItems);
for(i = 1; i <= newItems; i++)
{
OffsetRect(&(pItem->itmRect), offset.h, offset.v); UnionRect(&(pItem->itmRect), &maxRect, &maxRect); switch((pItem->itmType) & 0x7F){
pItem->itmHndl = nil;
break;
case ctrlItem + btnCtrl:
case ctrlItem + chkCtrl:
case ctrlItem + radCtrl:
pItem->itmHndl =
pItem->itmData, true, 0, 0, 1, pItem->itmType & 0x3, 0);
break;
case ctrlItem + resCtrl:
pItem->itmHndl =
pItem->itmRect;
break;
case statText:
case editText:
pItem->itmHndl, pItem->itmData[0]);
break;
case iconItem:
pItem->itmHndl = GetIcon(*pItem->itmData); break;
case picItem:
pItem->itmHndl = (Handle)GetPicture(pItem->itmData[1]);
break;
default:
pItem->itmHndl = nil;
}
dataSize = (pItem->itmData[0] + 1) & 0xFFFE;
pItem = (DITLItem *)(((char *)pItem) + dataSize +
sizeof(DITLItem));
}
(**hItems).dlgMaxIndex = (**hItems).dlgMaxIndex + newItems;
maxRect.bottom += 5;
maxRect.right += 5;
SizeWindow( theDialog, maxRect.right, maxRect.bottom, true); return firstItem;
}