Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
ListInDialog.c
/* |
ListInDialog |
A snippet that shows how to (uuuhhhhh) put a list in a dialog. |
I thought we had this one, but I guess not. It's easy, just create the list |
right after you create the dialog, then call LUpdate and LClick in a |
dialog filter to respond to user events. |
Please see the snippet DialogBits for a more comprehensive treatment of |
everything you can do in a dialog (well, almost). |
This is a 680x0 version, built with the Universal Headers. |
C.K. Haun |
April '94 |
Are you sure we don't already have a snippet like this???? |
Oh, I rememeber, that was on the //gs |
*/ |
#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 <Gestalt.h> |
#include <Memory.h> |
#include <Scrap.h> |
#include <TextEdit.h> |
#include <Lists.h> |
#include <Events.h> |
#include <string.h> |
#include "TestPrinterClass.h" |
#include "SafeNameRegistry.h" |
enum { |
kSampleDialog = 512 |
}; |
enum { |
kModelListItem = 3, |
kNameListItem, |
kStatTextItem1, |
kBlocksizePopupItem, |
kRepeatPopupItem, |
kAlignPopupItem |
}; |
enum { |
appleID = 128, |
fileID, |
editID, |
blockID |
}; |
enum { |
mApple = 0, |
mFile, |
mEdit, |
mBlocksize, |
MENU_COUNT |
}; |
#include "ListInDialog.h" |
ListHandle gPrinterList, gModelList; /* making the list handle a global */ |
MenuHandle menus[MENU_COUNT]; |
Boolean done; |
void |
SetupMenus( void ) |
{ |
short i; |
MenuHandle *pMenu; |
menus[mApple] = GetMenu(appleID); |
AppendResMenu( menus[mApple], (ResType) 'DRVR'); |
InsertMenu( menus[mApple], 0 ); |
for (pMenu = &menus[1], i = 1; i < MENU_COUNT; i++ ) { |
*pMenu = GetMenu( i + appleID ); |
InsertMenu(*pMenu++, 0); |
} |
DrawMenuBar(); |
} |
ListHandle |
MakeDialogList( DialogPtr dlg, int item ) |
{ |
// this "rect" defines the data bounds of the list. In this case, a |
// one column list |
Rect tempRect; |
short tempItem; |
Handle tempHandle; |
Rect listRect2 = { 0, 0, 0, 1 }; |
Cell cp = { 0, 0 }; |
// setting it up in the Dialog manager's records, |
GetDialogItem( dlg, item, &tempItem, &tempHandle, &tempRect); |
/* inset the rect by 16, which is the width of the scroll bar that will be attached */ |
/* to this list */ |
tempRect.right -= 16; |
/* set the current port to this dialog */ |
SetPort(dlg); |
/* create the list */ |
return LNew(&tempRect, // in the tempRect bounds |
&listRect2, // with a sinngle column |
cp, // default cell size (a cell of 0,0 says that) |
0, // no special LDEF, use the standard one |
dlg, // put it in this port |
false, // do NOT draw initially |
false, // does NOT have a grow box space |
false, // does NOT scroll horizontally |
true); // DOES have a verticle scroll bar |
} |
/* Here is the filter that handles any List activity */ |
pascal Boolean theListFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit) |
{ |
Rect tempR; |
Boolean returnValue = false; // defaults to me not saying I handled anything |
Boolean theBoolean; |
WindowPtr oldP; |
// get the current port, set the port to this dialog |
GetPort(&oldP); |
SetPort(theDialog); |
// was this an update event for this dialog? |
if ((theEvent->what == updateEvt) && (theEvent->message == (UInt32)theDialog)) { |
FrameOk( theDialog ); |
// Update the list. |
LUpdate(theDialog->visRgn, gModelList); |
LUpdate(theDialog->visRgn, gPrinterList); |
// get the list rectangle |
// push it outwards one pixel and frame the list |
tempR = (*gModelList)->rView; |
InsetRect(&tempR, -1, -1); |
FrameRect(&tempR); |
tempR = (*gPrinterList)->rView; |
InsetRect(&tempR, -1, -1); |
FrameRect(&tempR); |
// NOTE: Do !NOT! return 'true' if you did SOME drawing in response to a dialog update |
// event in your filter! |
// ONLY if you did EVERYTHING should you return 'true', or else you can cause other updating |
// not to occur, which would be Bad |
} else { |
// see if this was a mouseDown event |
if (theEvent->what == mouseDown) { |
Point theP; |
// we set the port to the dialog on entry to the filter, so a GetMouse will work |
GetMouse(&theP); |
// get the list rectangle |
tempR = (*gModelList)->rView; |
// add the scroll bar back in for hit testing (remember we took it out earlier) |
tempR.right += 16; |
// See if they clicked in our list! |
if (PtInRect(theP, &tempR)) |
{ |
theBoolean = LClick(theP, 0, gModelList); |
// if they double-clicked the list, return 1, as if the OK button had been pressed |
if (theBoolean) |
*itemHit = ok; |
else |
*itemHit = kModelListItem; |
// tell the Dialog Manager that we handled this click, it can stop searching for a click-owner |
returnValue = true; |
} |
if ( returnValue != true ) |
{ |
// get the list rectangle |
tempR = (*gPrinterList)->rView; |
// add the scroll bar back in for hit testing (remember we took it out earlier) |
tempR.right += 16; |
// See if they clicked in our list! |
if (PtInRect(theP, &tempR)) |
{ |
theBoolean = LClick(theP, 0, gPrinterList); |
// if they double-clicked the list, return 1, as if the OK button had been pressed |
if (theBoolean) |
*itemHit = ok; |
else |
*itemHit = kNameListItem; |
// tell the Dialog Manager that we handled this click, it can stop searching for a click-owner |
returnValue = true; |
} |
} |
if ( returnValue == true ) |
{ |
HiliteOk( theDialog ); |
} |
} |
} |
// reset the original port |
SetPort(oldP); |
return(returnValue); |
} |
/* |
Sys7CDEFPopupPrivateDataHdl theMenuData = (Sys7CDEFPopupPrivateDataHdl) (**(ControlHandle)fHItem).contrlData; |
return (**theMenuData).mHandle; |
*/ |
void |
HiliteOk( DialogPtr dlg ) |
{ |
// |
// enable/disable the okay button if we have an item selected in each list |
// |
Cell cp; |
Boolean enableOk; |
Rect tempRect; |
short tempItem; |
Handle tempHandle; |
cp.h = 0; |
cp.v = 0; |
enableOk = LGetSelect( true, &cp, gModelList); |
if ( enableOk ) |
{ |
cp.h = 0; |
cp.v = 0; |
enableOk = LGetSelect( true, &cp, gPrinterList); |
} |
GetDialogItem( dlg, ok, &tempItem, &tempHandle, &tempRect); |
HiliteControl( (ControlHandle) tempHandle, enableOk? 0: 255 ); |
} |
void |
FrameOk( DialogPtr dlg ) |
{ |
// |
// outline the default ok button |
// |
Cell cp; |
Boolean enableOk; |
Rect tempRect; |
short tempItem; |
Handle tempHandle; |
RGBColor gray = { 0x3FFF, 0x3FFF, 0x3FFF }, |
black = { 0, 0, 0 }; |
cp.h = 0; |
cp.v = 0; |
enableOk = LGetSelect( true, &cp, gModelList); |
if ( enableOk ) |
{ |
cp.h = 0; |
cp.v = 0; |
enableOk = LGetSelect( true, &cp, gPrinterList); |
} |
GetDialogItem( dlg, ok, &tempItem, &tempHandle, &tempRect); |
if ( !enableOk ) |
RGBForeColor( &gray ); |
InsetRect( &tempRect, -3, -3 ); |
PenSize( 3, 3 ); |
FrameRoundRect( &tempRect, 16, 16 ); |
if ( !enableOk ) |
RGBForeColor( &black ); |
PenNormal(); |
} |
void |
GetNameFromCell (StringPtr theString, Cell cell, ListHandle hList) |
{ |
short length; |
/* |
The maximum length of the string is the size of a Str255, minus the |
length byteÉ |
*/ |
length = sizeof(Str255) - 1; |
LGetCell((StringPtr)(theString + 1), &length, cell, hList); |
/* |
Set the length byte. |
*/ |
*theString = (unsigned char) length; |
} |
int |
GetDialogPopupValue( DialogPtr dlg, int item ) |
{ |
Rect tempRect; |
short tempItem; |
Handle tempHandle; |
GetDialogItem( dlg, item, &tempItem, &tempHandle, &tempRect); |
return GetControlValue( (ControlHandle) tempHandle); |
} |
void |
SetDialogPopupValue( DialogPtr dlg, int item, int value ) |
{ |
Rect tempRect; |
short tempItem; |
Handle tempHandle; |
GetDialogItem( dlg, item, &tempItem, &tempHandle, &tempRect); |
SetControlValue( (ControlHandle) tempHandle, value ); |
} |
int |
ChoosePrinter( char *name, long *blocksize, int *repeats) |
//ChoosePrinter( char *name, long *blocksize, int *repeats, int *align ) |
{ |
char model[255]; |
short length; |
Cell cp = { 0, 0 }; // cell to initialize with |
DialogPtr myDialog = nil; // the dialog we're using |
short hitItem = 0; // hitItem for ModalDialog call |
static ModalFilterUPP modalFilterUPP; |
modalFilterUPP = NewModalFilterProc(theListFilter); |
/* get our dialog. It is created HIDDEN, and shown after I set the */ |
/* user item that will hold the list */ |
myDialog = GetNewDialog(kSampleDialog, nil, (WindowPtr)-1); |
// list all the known printer models |
gModelList = MakeDialogList( myDialog, kModelListItem ); |
gPrinterList = MakeDialogList( myDialog, kNameListItem ); |
SetUpList( gModelList, ""); // list all the known printer of the first model |
SetDialogPopupValue( myDialog, kBlocksizePopupItem, 6 ); // 512 byte default blocksize |
SetDialogPopupValue( myDialog, kRepeatPopupItem, 1 ); // only send file down once |
cp.h = 0; |
cp.v = 0; |
length = sizeof(model); |
LGetCell( model, &length, cp, gModelList); |
if ( length > 0 ) |
{ |
LSetSelect( true, cp, gModelList); // select the first model |
model[ length ] = 0; // null terminate c-string |
SetUpList( gPrinterList, model ); |
length = sizeof(model); |
cp.h = 0; |
cp.v = 0; |
LGetCell( model, &length, cp, gPrinterList); |
if ( length > 0 ) |
{ |
LSetSelect( true, cp, gPrinterList); // select the first printer name |
} |
} |
// turn drawing on after the list has been filled |
LSetDrawingMode(true, gModelList); |
LSetDrawingMode(true, gPrinterList); |
HiliteOk( myDialog ); // enable/disable ok button |
// show the dialog |
ShowWindow((WindowPtr)myDialog); |
/* draw it once */ |
DrawDialog(myDialog); |
// loop until ModalDialog is done |
do { |
// we have to use a ModalDialog filter, since ModalDialog doesn't |
// automatically handle lists |
ModalDialog(modalFilterUPP, &hitItem); |
// switch off what item was hit |
switch (hitItem) { |
case kModelListItem: |
// |
// rebuild the list of specific printers |
// |
cp.h = 0; |
cp.v = 0; |
if ( LGetSelect( true, &cp, gModelList) ) |
{ |
length = sizeof(model); |
LGetCell( model, &length, cp, gModelList); |
model[ length ] = 0; |
// create a new list of printer names |
LDispose( gPrinterList ); |
gPrinterList = MakeDialogList( myDialog, kNameListItem ); |
SetUpList( gPrinterList, model ); |
cp.h = 0; |
cp.v = 0; |
LGetCell( model, &length, cp, gPrinterList); |
if ( length > 0 ) |
{ |
LSetSelect( true, cp, gPrinterList); // select the first printer name |
} |
LSetDrawingMode(true, gPrinterList); |
LUpdate( myDialog->visRgn, gPrinterList ); |
} |
break; |
default: |
break; |
} |
// wait for an OK or Cancel |
} while (hitItem != ok && hitItem != cancel); |
if ( hitItem == ok ) |
{ |
// |
// save a reference to the requested printer |
// |
cp.h = 0; |
cp.v = 0; |
if ( LGetSelect( true, &cp, gModelList) ) |
{ |
length = sizeof(model); |
LGetCell( model, &length, cp, gPrinterList); |
model[ length ] = 0; |
strcpy( name, "Devices:device-tree:PRINTER:" ); |
strcat( name, model ); |
cp.h = 0; |
cp.v = 0; |
if ( LGetSelect( true, &cp, gPrinterList) > 0 ) |
{ |
length = sizeof(model); |
LGetCell( model, &length, cp, gPrinterList); |
model[ length ] = 0; |
strcat( name, ":" ); |
strcat( name, model ); |
} |
} |
// |
// get the current blocksize |
// |
*blocksize = 1L<< (GetDialogPopupValue( myDialog, kBlocksizePopupItem ) - 1); |
// |
// get the number of times to send the file |
// |
switch( GetDialogPopupValue( myDialog, kRepeatPopupItem ) ) |
{ |
case 2: *repeats = 2; break; |
case 3: *repeats = 5; break; |
case 4: *repeats = 10; break; |
case 5: *repeats = 20; break; |
case 6: *repeats = 30; break; |
case 7: *repeats = 50; break; |
case 8: *repeats =100; break; |
default: |
case 1: *repeats = 1; break; |
} |
switch( GetDialogPopupValue( myDialog, kAlignPopupItem ) ) |
{ |
case 1: |
case 2: |
case 3: |
case 4: |
case 5: |
case 6: |
default: |
break; |
} |
} |
// don't do anything in this sample |
LDispose( gModelList ); |
LDispose( gPrinterList ); |
DisposeDialog(myDialog); |
return hitItem; |
} |
/*-----------------------------------------------------------------------------* |
SearchForUSBPrinters |
Desc: Searches thru a printer model entry in the name registry |
looking for a model's printers. When one is found a call is |
issued to the clients callback routine for further processing |
In: - A pstring full path in the name registry of a printer model |
- A callback routine which gets called when a printer is found |
- A ptr to user data |
Out: None |
History: |
17 Apr 98 oja modified to use list manager instead of Chooser |
24 Feb 98 gp Created |
*-----------------------------------------------------------------------------*/ |
void |
SetUpList( ListHandle theList, char *modelPath ) |
{ |
RegEntryID theModelEntry; // the model node supported by the driver |
RegEntryID aPrinterEntry; // a printer node in the name registry |
RegEntryIterationOp iterOp; // name registry iterator op code |
RegEntryIter printerIterator; // used to iterate child nodes of printer model |
Boolean donePrinters = false; // NameRegistry param tell when we're done |
OSStatus err = noErr; // error from name registry calls |
char path[256]; |
short listCount = 0; |
Cell cp; |
// name registry only deals with c strings |
strcpy( path, "Devices:device-tree:PRINTER" ); |
if ( modelPath[0] != 0 ) |
{ |
strcat( path, ":" ); |
strcat( path, modelPath ); |
} |
// look up the node for the printer model requested |
err = SafeRegistryEntryIDInit(&theModelEntry); |
if( err == noErr ) |
err = SafeRegistryCStrEntryLookup( nil, path, &theModelEntry ); |
if( err == noErr ) |
{ |
// create an iterator to look at the child nodes for our printer model entry |
iterOp = kRegIterChildren; |
err = SafeRegistryEntryIterateCreate( &printerIterator ); |
err = SafeRegistryEntryIterateSet(&printerIterator, &theModelEntry); |
if( err == noErr ) |
{ |
// look for a model's connected printers |
do |
{ |
Str255 nodeName; // the name of the printer |
RegPropertyValueSize nameSize; // size of name buffer |
err = SafeRegistryEntryIterate( &printerIterator, iterOp, &aPrinterEntry, &donePrinters ); |
// grab name of printer in name registyr |
nameSize = sizeof( nodeName ); |
if( !donePrinters && err == noErr ) |
err = SafeRegistryPropertyGet( &aPrinterEntry, "name", &nodeName, &nameSize ); |
if( !donePrinters && err == noErr ) |
{ |
// add the printer to the list |
listCount = LAddRow(1, listCount + 1, theList); |
cp.h = 0; |
cp.v = listCount; |
LAddToCell(&nodeName, nameSize-1, cp, theList); |
} |
iterOp = kRegIterContinue; |
} while( !donePrinters && err == noErr ); |
// end while for printers |
} |
SafeRegistryEntryIterateDispose(&printerIterator); |
} |
SafeRegistryEntryIDDispose( &theModelEntry ); |
} |
// eof |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-26