Liten Datorhandbok För Målmedvetna
Academic Computer Club, Umeå Universitet, 2000
Dialogrutor och kontroller
Du tar fram en dialogruta som har sparats i en DLOG-resurs genom att ge kommandot:
dialogPtr = GetNewDialog(dialogID, 0L, (WindowPtr)-1L);
För att bli av med dialogrutan igen ger du kommandot:
DisposDialog(dialogPtr);
Efter att du har skapat en dialogruta vill du i allmänhet låta användaren göra val i dialogrutan och sedan hantera dessa. Det gör du genom att ge kommandot:
ModalDialog(0L, &item);
item är en short som efter det här anropet får värdet av numret på det föremål i dialogrutan som användaren klickade på. Du måste sedan tolka det här numret och agera på lämpligt sätt. Notera att om användaren klickar i en kryssruta, så kryssas inte rutan för automatiskt utan det måste du göra manuellt. För att göra det måste du först få tag i ett handtag för kontrollen som användaren klickade i med anropet:
GetDItem(dialogPtr, itemNo, &itemType, &controlHandle, &rect);
Den här funktionen talar om vilken sorts föremål det aktuella föremålet är, vilken rektangel det visas inom och ger även ett handtag till föremålet. Detta handtag kan du sedan använda för att till exempel sätta ett kryss i kryssrutan:
SetCtlValue(controlHandle, 1);
Du kan använda kommandot ParamText för att ersätta de speciella strängarna ^0, ^1, ^2, ^3 i en efterföljande dialogruta, med någon text som specificeras av dig. Anropet ser ut som:
ParamText(str255_1, str255_2, str255_3, str255_4);
För textobjekt kan du använda följande funktioner för att hämta och sätta föremålets text:
GetIText(handle, textStr255);
SetIText(handle, textStr255);
Det föremål i dialogrutan som har ID-numret 1 kallas för standardvalsknappen. Om du bara trycker på returtangenten, så är det den knappen som kommer att väljas. Standardvalsknappen markeras med en svart ram. Den här ramen är själv ett objekt, men tyvärr finns det ingen funktion för att rita den, utan du måste själv skapa den funktionen. Det gör du genom att i ResEdit lägga in ett userItem där ramen ska sitta. Sedan används följande funktion för att rita ramen:
pascal void drawDefault (WindowPtr theWindow, short item)
{
Handle aHandle;
short type;
Rect displayRect;
GetDItem(theWindow,1,&type,&aHandle,&displayRect);
PenSize(3,3);
InsetRect(&displayRect,-4,-4);
FrameRoundRect(&displayRect,16,16);
PenNormal();
}
För att datorn skall veta om att denna funktion skall användas när objektet skall ritas måste du sätta handtaget för objektet till denna rutin, det görs genom anropen:
GetDItem(dialogPtr, userItemID, &type, &aHandle, &aRect);
SetDItem(dialogPtr, userItemID, type, (Handle)drawDefault,&aRect);
(Notera att du bara kan göra på detta sätt om du kompilerar en 68k-version. Om du kompilerar en PowerPC-version måste du använda dig av något som heter Universal Procedure Pointers istället. Dessa finns bekskrivna i Inside Macintosh-boken om PowerPC, i avsnittet om Mixed Mode Manager.)
Sammanfattningsvis, för att hantera en dialogruta behöver du göra följande:
- Ladda in den från resursfilen med GetNewDialog. (Eventuellt kan du välja i resursfilen att inte visa den direkt, sedan räkna ut en lämplig placering, flytta den dit och anropa ShowWindow.)
- Initialisera ett userItem till att rita en svart ram runt standardvalsknappen.
- Sätt korrekta startvärden på alla kontroller. När dialogrutan tas fram är inga alternativ markerade. Du måste därför manuellt sätta de markeringar du vill ska vara förvalda.
- I en slinga anropa funktionen ModalDialog, tills du upptäcker att användaren har klickat på OK eller Avbryt-knappen.
- När du får ett klick i ett visst element, se till att uppdatera elementets utseende. Om användaren klickar i en kryssruta så skall dess tillstånd inverteras. Om användaren klickar i en radioknapp så skall den markeras, och alla andra radioknappar som hör till samma grupp skall avmarkeras.
Här är ett exempel på en generell rutin för att hantera dialogrutor innehållande textfält, kryssknappar, radioknappar och tryckknappar.
/*
Den här rutinen hanterar enkla dialogrutor som innehåller kryssrutor, radioknappar,
textfält och tryckknappar.
Efter dialogID så skall du skicka en lista av argument som avlustas med -1. Listan
skall beskriva alla element i dialogrutan. Varje element beskrivs av sin typ, efter
det följer ytterligare data som beskriver föremålet, som kan variera från föremål
till föremål.
Typ Ytterligare argument Beskrivning
--------------------------------------------------------------------------------------
defaultOutline long itemID ID för ramen kring standardvalsknappen
checkBox long itemID ID för kryssrutan
Boolean* checked Pekare till sant/falskt värde
radioGroup long firstItemID ID för första elementet i radiogruppen
long buttonsInGroup Antal knappar i radiogruppen
short * groupSel Pekar till vald knapp, första = 0
textItem long itemID ID för textfältet
Str255 text Pekare till textsträng för fältet
Notera att alla värden som pekarna pekar på skall initialiseras av anroparen.
Funktionen returnerar när den mottar ett klick i ett aktivt föremål som inte finns
i listan ovan. Den returnerar ID-numret för föremålet som klickades. (Vanligtvis
en OK- eller Avbryt-knapp.)
Exempel på anrop: knappVal= dialogMgr (128, defaultOutline, 15L, checkBox, 3L,
&colorPrinting, radioGroup, 4L, 3L, &printStyle, radioGroup, 7L,
3L, &quality, -1L);
VIKTIGT! Ingen typkontroll av argumenten görs när du anropar argument med varierande
antal argument. Därför måste du själv se till att alla dina argument har precis den
typ som angivits i listan ovan. Annars kommer fel att uppstå.
*/
const long defaultOutline=1;
const long checkBox=2;
const long radioGroup=3;
const long textItem=4;
#define MAX_ITEMS 10 // Maximalt antal föremål av samma typ.
short dialogMgr(short dialogID,...)
{
va_list ap;
long userItemID; // Data för standardvalsramen.
long noCheck, checkID[MAX_ITEMS]; // Data for kryssrutor.
Boolean *checked[MAX_ITEMS];
// Data för radiogrupper.
long noGroup, groupID[MAX_ITEMS], noRadio[MAX_ITEMS];
short *groupSel[MAX_ITEMS];
long noEdit, editID[MAX_ITEMS]; // Data för textfält.
unsigned char *text[10];
long arg; // Ytterligare data.
short i,item,type;
ControlHandle itemHandle;
Rect box;
DialogPtr theDialog;
SetCursor(&qd.arrow);
// Ta fram dialogrutan.
theDialog=GetNewDialog(dialogID,0L,(WindowPtr)-1L);
if (ptrErr((Ptr)theDialog,false))
{
// Om dialogrutan inte kan användas, antag klick i standardvalet.
if (theDialog!=0L) DisposeDialog(theDialog);
return 1;
}
centerWindow(theDialog,50,30,false); // Centrera fönstret.
userItemID=noCheck=noGroup=noEdit=0;
va_start(ap,dialogID); // Stega genom argumenten.
do
{
arg=va_arg(ap,long);
switch(arg)
{
case defaultOutline: // Installera standrardvalsramen.
userItemID=va_arg(ap,long);
defaultButton(theDialog,userItemID);
break;
case checkBox: // Sätt initialvärden för kryssruta.
checkID[noCheck]=va_arg(ap,long);
checked[noCheck]=va_arg(ap,Boolean *);
GetDItem(theDialog,checkID[noCheck],&type,
(Handle *)&itemHandle,&box);
SetCtlValue(itemHandle,*checked[noCheck]);
noCheck++;
break;
case radioGroup: // Sätt initialvärden för radiogrupp
groupID[noGroup]=va_arg(ap,long);
noRadio[noGroup]=va_arg(ap,long);
groupSel[noGroup]=va_arg(ap,short *);
GetDItem(theDialog,groupID[noGroup]+*groupSel[noGroup],
&type,(Handle *)&itemHandle,&box);
SetCtlValue(itemHandle,1);
noGroup++;
break;
case textItem: // Sätt initialvärden för textfält.
editID[noEdit]=va_arg(ap,long);
text[noEdit]=va_arg(ap, unsigned char *);
GetDItem(theDialog,editID[noEdit],&type,
(Handle *)&itemHandle,&box);
SetIText((Handle)itemHandle,text[i]);
noEdit++;
break;
}
if (noEdit>MAX_ITEMS || noGroup>MAX_ITEMS || noCheck>MAX_ITEMS)
DebugStr("\pFel! Öka MAX_ITEMS i rutinen dialogMgr.");
} while (arg!=-1); // Tills argumenten tar slut
while(1) // Tills användaren klickar i ett föremål
{
ModalDialog(0L,&item);
GetDItem(theDialog,item,&type,(Handle *)&itemHandle,&box);
switch(type)
{
case ctrlItem+chkCtrl: // Hantera kryssruteklick
for (i=0; i<noCheck; i++)
{
if (item==checkID[i])
{
*checked[i]=(*checked[i]+1)&1;
SetCtlValue(itemHandle,*checked[i]);
}
}
break;
case ctrlItem+radCtrl: // Hantera radioknappsklick
for (i=0; i<noGroup; i++)
{
if (item>=groupID[i] && item<=groupID[i] + noRadio[i] - 1)
{
SetCtlValue(itemHandle,1);
GetDItem(theDialog,groupID[i]+*groupSel[i],
&type,(Handle *)&itemHandle,&box);
SetCtlValue(itemHandle,0);
*groupSel[i]=item-groupID[i];
}
}
break;
case editText: // Vi bryr oss inte om klick i textfält, vi
break; // läser av deras värden innan vi returnerar
// istället.
case btnCtrl+ctrlItem: // Nu skall vi returnera.
case iconItem:
case picItem:
// Lagra innehållet i textfälten.
for(i=0;i<noEdit;i++)
{
GetDItem(theDialog,editID[i],&type,(Handle *)&itemHandle,&box);
GetIText((Handle)itemHandle,text[i]);
}
DisposeDialog(theDialog);
// Returnera.
return(item);
break;
}
}
}
Författat av Niklas Frykholm
Bakåt , Framåt , Upp, Huvudsida
Denna sida ändrades sist av
handbok den
26/05 1996 12:37:19.
Last modified Sunday, 26-May-1996 12:37:19 CEST