Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
U gebruikt dialoogvensters om informatie weer te geven en om invoer van de gebruiker te vragen. Uw toepassing laadt en initialiseert het dialoogvenster, verwerkt gebruikersinvoer en vernietigt het dialoogvenster wanneer de gebruiker de taak heeft voltooid. Het proces voor het verwerken van dialoogvensters varieert, afhankelijk van of het dialoogvenster modaal of modusloos is. Voor een modaal dialoogvenster moet de gebruiker het dialoogvenster sluiten voordat een ander venster in de toepassing wordt geactiveerd. De gebruiker kan echter vensters in verschillende toepassingen activeren. Voor een modeless dialoogvenster is geen onmiddellijke reactie van de gebruiker vereist. Het is vergelijkbaar met een hoofdvenster met besturingselementen.
In de volgende secties wordt beschreven hoe u beide typen dialoogvensters gebruikt.
- een berichtvak weergeven
- Een modaal dialoogvenster maken
- Een dialoogvenster zonder modus maken
- een dialoogvenster initialiseren
- Een sjabloon maken in het geheugen
Een berichtvak weergeven
De eenvoudigste vorm van modaal dialoogvenster is het berichtvak. De meeste toepassingen gebruiken berichtvakken om de gebruiker te waarschuwen voor fouten en om aanwijzingen te vragen over hoe u doorgaat nadat er een fout is opgetreden. U maakt een berichtvak met behulp van de functie MessageBox of MessageBoxEx, waarbij u het bericht en het aantal knoppen en het type knoppen opgeeft dat moet worden weergegeven. Het systeem maakt een modaal dialoogvenster met een eigen dialoogvenstersjabloon en -procedure. Nadat de gebruiker het berichtvak heeft gesloten, retourneert MessageBox of MessageBoxEx een waarde die de door de gebruiker gekozen knop identificeert om het berichtvak te sluiten.
In het volgende voorbeeld wordt in de toepassing een berichtvak weergegeven waarin de gebruiker wordt gevraagd een actie uit te voeren nadat er een foutvoorwaarde is opgetreden. In het berichtvak wordt het bericht weergegeven waarin de foutvoorwaarde wordt beschreven en hoe u dit kunt oplossen. De stijl MB_YESNO zorgt ervoor dat MessageBox- twee knoppen biedt waarmee de gebruiker kan kiezen hoe verder te gaan:
int DisplayConfirmSaveAsMessageBox()
{
int msgboxID = MessageBox(
NULL,
L"temp.txt already exists.\nDo you want to replace it?",
L"Confirm Save As",
MB_ICONEXCLAMATION | MB_YESNO
);
if (msgboxID == IDYES)
{
// TODO: add code
}
return msgboxID;
}
In de volgende afbeelding ziet u de uitvoer uit het voorgaande codevoorbeeld:
Een modaal dialoogvenster maken
U maakt een modaal dialoogvenster met behulp van de functie Dialoogvenster. U moet de identifier of de naam van een bron voor een dialoogvenstersjabloon en een aanwijzer voor de procedure van het dialoogvenster specificeren. De Dialoogvenster functie laadt de sjabloon, geeft het dialoogvenster weer en verwerkt alle gebruikersinvoer totdat de gebruiker het dialoogvenster sluit.
In het volgende voorbeeld wordt in de toepassing een modaal dialoogvenster weergegeven wanneer de gebruiker klikt op Item verwijderen uit een toepassingsmenu. Het dialoogvenster bevat een invoerveld (waarin de gebruiker de naam van een item invoert) en de knoppen OK en Annuleren. De besturings-id's voor deze besturingselementen zijn respectievelijk ID_ITEMNAME, IDOK en IDCANCEL.
Het eerste deel van het voorbeeld bestaat uit de instructies waarmee het modale dialoogvenster wordt gemaakt. Met deze verklaringen in de vensterprocedure voor het hoofdvenster van de toepassing wordt het dialoogvenster gemaakt wanneer het systeem een WM_COMMAND bericht met de IDM_DELETEITEM menu-identificatie ontvangt. Het tweede deel van het voorbeeld is de procedure voor het dialoogvenster, waarmee de inhoud van het besturingselement bewerken wordt opgehaald en het dialoogvenster wordt gesloten bij het ontvangen van een WM_COMMAND bericht.
Met de volgende instructies maakt u het modale dialoogvenster. De dialoogvenstersjabloon is een resource in het uitvoerbare bestand van de toepassing en bevat de resource-id DLG_DELETEITEM.
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_DELETEITEM:
if (DialogBox(hinst,
MAKEINTRESOURCE(DLG_DELETEITEM),
hwnd,
(DLGPROC)DeleteItemProc)==IDOK)
{
// Complete the command; szItemName contains the
// name of the item to delete.
}
else
{
// Cancel the command.
}
break;
}
return 0L;
In dit voorbeeld geeft de toepassing het hoofdvenster op als het eigenaarsvenster voor het dialoogvenster. Wanneer het systeem in eerste instantie het dialoogvenster weergeeft, is de positie ervan relatief ten opzichte van de linkerbovenhoek van het clientgebied van het eigenaarvenster. De toepassing gebruikt de retourwaarde uit dialoogvenster om te bepalen of de bewerking moet worden voortgezet of geannuleerd. Met de volgende instructies wordt de procedure voor het dialoogvenster gedefinieerd.
char szItemName[80]; // receives name of item to delete.
BOOL CALLBACK DeleteItemProc(HWND hwndDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (!GetDlgItemText(hwndDlg, ID_ITEMNAME, szItemName, 80))
*szItemName=0;
// Fall through.
case IDCANCEL:
EndDialog(hwndDlg, wParam);
return TRUE;
}
}
return FALSE;
}
In dit voorbeeld wordt in de procedure GetDlgItemText gebruikt om de huidige tekst op te halen uit de bewerkingscontrole, geïdentificeerd door ID_ITEMNAME. Met de procedure wordt vervolgens de functie EndDialog aangeroepen om de retourwaarde van het dialoogvenster in te stellen op IDOK of IDCANCEL, afhankelijk van het ontvangen bericht en om het proces van het sluiten van het dialoogvenster te starten. De id's IDOK en IDCANCEL komen overeen met de knoppen OK en Annuleren. Nadat de procedure EndDialogaanroept, verzendt het systeem extra berichten naar de procedure om het dialoogvenster te vernietigen en retourneert de retourwaarde van het dialoogvenster terug naar de functie die het dialoogvenster heeft gemaakt.
Een modusloos dialoogvenster maken
U maakt een modeless dialoogvenster met behulp van de functie CreateDialog waarbij u de id of naam van een dialoogvenstersjabloonresource en een pointer naar de dialoogvensterprocedure opgeeft. CreateDialog de sjabloon laadt, het dialoogvenster maakt en optioneel weergeeft. Uw toepassing is verantwoordelijk voor het ophalen en verzenden van gebruikersinvoerberichten naar de dialoogvensterprocedure.
In het volgende voorbeeld wordt in de toepassing een modusloos dialoogvenster weergegeven ( als dit nog niet wordt weergegeven) wanneer de gebruiker in een toepassingsmenu op Ga naar klikt. Het dialoogvenster bevat een besturingselement voor bewerken, een selectievakje en de knoppen OK en Annuleren. De dialoogvenstersjabloon is een resource in het uitvoerbare bestand van de toepassing en bevat de resource-id DLG_GOTO. De gebruiker voert een regelnummer in het bewerkingsbesturingselement in en schakelt het selectievakje in om op te geven dat het regelnummer ten opzichte van de huidige regel is. De besturings-id's zijn ID_LINE, ID_ABSREL, IDOK en IDCANCEL.
De instructies in het eerste deel van het voorbeeld maken het modeless dialoogvenster aan. Met deze verklaringen in de vensterprocedure voor het hoofdvenster van de toepassing wordt het dialoogvenster gemaakt wanneer de vensterprocedure een WM_COMMAND bericht ontvangt met de IDM_GOTO menu-identificatie, maar alleen als de globale variabele nog geen geldige handle bevat. Het tweede deel van het voorbeeld is de hoofdberichtlus van de toepassing. De lus bevat de IsDialogMessage functie om ervoor te zorgen dat de gebruiker de toetsenbordinterface van het dialoogvenster kan gebruiken in dit niet-modale dialoogvenster. Het derde deel van het voorbeeld is de procedure voor het dialoogvenster. Met de procedure worden de inhoud van het bewerkingselement en het selectievakje opgehaald wanneer de gebruiker op de knop OK klikt. De procedure vernietigt het dialoogvenster wanneer de gebruiker op de knop Annuleren klikt.
HWND hwndGoto = NULL; // Window handle of dialog box
...
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_GOTO:
if (!IsWindow(hwndGoto))
{
hwndGoto = CreateDialog(hinst,
MAKEINTRESOURCE(DLG_GOTO),
hwnd,
(DLGPROC)GoToProc);
ShowWindow(hwndGoto, SW_SHOW);
}
break;
}
return 0L;
In de voorgaande instructies wordt CreateDialog- alleen aangeroepen als hwndGoto geen geldige venstergreep bevat. Dit zorgt ervoor dat de toepassing niet tegelijkertijd twee dialoogvensters weergeeft. Ter ondersteuning van deze manier van controleren moet de dialoogvensterprocedure zijn ingesteld op NULL bij het vernietigen van het dialoogvenster.
De berichtenlus voor een toepassing bestaat uit de volgende instructies.
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
// Handle the error and possibly exit
}
else if (!IsWindow(hwndGoto) || !IsDialogMessage(hwndGoto, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
De lus controleert de geldigheid van de vensterhandle naar het dialoogvenster en roept alleen de IsDialogMessage- functie aan als de handle geldig is. IsDialogMessage alleen het bericht verwerkt als het hoort bij het dialoogvenster. Anders geeft het ONWAAR terug en stuurt de lus het bericht door naar het juiste venster.
Met de volgende instructies wordt de procedure voor het dialoogvenster gedefinieerd.
int iLine; // Receives line number.
BOOL fRelative; // Receives check box status.
BOOL CALLBACK GoToProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL fError;
switch (message)
{
case WM_INITDIALOG:
CheckDlgButton(hwndDlg, ID_ABSREL, fRelative);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
fRelative = IsDlgButtonChecked(hwndDlg, ID_ABSREL);
iLine = GetDlgItemInt(hwndDlg, ID_LINE, &fError, fRelative);
if (fError)
{
MessageBox(hwndDlg, SZINVALIDNUMBER, SZGOTOERR, MB_OK);
SendDlgItemMessage(hwndDlg, ID_LINE, EM_SETSEL, 0, -1L);
}
else
// Notify the owner window to carry out the task.
return TRUE;
case IDCANCEL:
DestroyWindow(hwndDlg);
hwndGoto = NULL;
return TRUE;
}
}
return FALSE;
}
In de voorgaande instructies verwerkt de procedure de WM_INITDIALOG en WM_COMMAND berichten. Tijdens de verwerking van WM_INITDIALOG initialiseert de procedure het selectievakje door de huidige waarde van de globale variabele toe te passen op CheckDlgButton. De procedure retourneert vervolgens TRUE om het systeem om te leiden om de standaardinvoerfocus in te stellen.
Tijdens WM_COMMAND verwerking sluit de procedure het dialoogvenster alleen als de gebruiker op de knop Annuleren klikt, dat wil zeggen de knop met de IDCANCEL-id. De procedure moet DestroyWindow aanroepen om een modeless dialoogvenster te sluiten. U ziet dat de procedure ook de variabele instelt op NULL- om ervoor te zorgen dat andere instructies die afhankelijk zijn van deze variabele correct werken.
Als de gebruiker op de knop OK klikt, haalt de procedure de huidige status van het selectievakje op en wijst deze toe aan de variabele fRelative. Vervolgens wordt de variabele gebruikt om het regelnummer op te halen uit de bewerkingscontrole. GetDlgItemInt vertaalt de tekst in het bewerkingsveld in een geheel getal. De waarde van fRelative bepaalt of de functie het getal interpreteert als een ondertekende of niet-ondertekende waarde. Als de tekst van het besturingselement bewerken geen geldig getal is, stelt GetDlgItemInt de waarde van de variabele fError in op niet-nul. De procedure controleert deze waarde om te bepalen of er een foutbericht moet worden weergegeven of de taak moet worden uitgevoerd. In het geval van een fout verzendt de dialoogvensterprocedure een bericht naar het besturingselement bewerken, waarbij deze wordt omgeleid om de tekst in het besturingselement te selecteren, zodat de gebruiker het eenvoudig kan vervangen. Als GetDlgItemInt- geen fout retourneert, kan de procedure de aangevraagde taak zelf uitvoeren of een bericht verzenden naar het eigenaarsvenster, waarbij deze wordt doorgestuurd om de bewerking uit te voeren.
Dialoogvenster initialiseren
U initialiseert het dialoogvenster en de inhoud ervan tijdens het verwerken van het WM_INITDIALOG bericht. De meest voorkomende taak is het initialiseren van de besturingselementen om de huidige dialoogvensterinstellingen weer te geven. Een andere veelvoorkomende taak is het centreren van een dialoogvenster op het scherm of in het venster van de eigenaar. Een nuttige functie van sommige dialoogvensters is het instellen van de invoerfocus op een gespecificeerd element in plaats van de standaardinvoerfocus te accepteren.
In het volgende voorbeeld centreert de dialoogvensterprocedure het dialoogvenster en wordt de invoerfocus ingesteld tijdens het verwerken van het WM_INITDIALOG bericht. Als u het dialoogvenster wilt centreren, worden met de procedure de rechthoeken van het venster voor het dialoogvenster en het eigenaarsvenster opgehaald en wordt een nieuwe positie voor het dialoogvenster berekend. Als u de invoerfocus wilt instellen, controleert de procedure de parameter wParam om de id van de standaardinvoerfocus te bepalen.
HWND hwndOwner;
RECT rc, rcDlg, rcOwner;
....
case WM_INITDIALOG:
// Get the owner window and dialog box rectangles.
if ((hwndOwner = GetParent(hwndDlg)) == NULL)
{
hwndOwner = GetDesktopWindow();
}
GetWindowRect(hwndOwner, &rcOwner);
GetWindowRect(hwndDlg, &rcDlg);
CopyRect(&rc, &rcOwner);
// Offset the owner and dialog box rectangles so that right and bottom
// values represent the width and height, and then offset the owner again
// to discard space taken up by the dialog box.
OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect(&rc, -rc.left, -rc.top);
OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining space and the owner's
// original position.
SetWindowPos(hwndDlg,
HWND_TOP,
rcOwner.left + (rc.right / 2),
rcOwner.top + (rc.bottom / 2),
0, 0, // Ignores size arguments.
SWP_NOSIZE);
if (GetDlgCtrlID((HWND) wParam) != ID_ITEMNAME)
{
SetFocus(GetDlgItem(hwndDlg, ID_ITEMNAME));
return FALSE;
}
return TRUE;
In de voorgaande instructies gebruikt de procedure de functie GetParent om de vensterhandle van de eigenaar op te vragen voor een dialoogvenster. De functie retourneert de venstergreep van de eigenaar naar dialoogvensters en de bovenliggende venstergreep naar onderliggende vensters. Omdat een toepassing een dialoogvenster kan maken dat geen eigenaar heeft, controleert de procedure de geretourneerde ingang en gebruikt de GetDesktopWindow-functie om de bureaubladvenstergreep op te halen, indien nodig. Na het berekenen van de nieuwe positie gebruikt de procedure de functie SetWindowPos om het dialoogvenster te verplaatsen, waarbij de HWND_TOP waarde wordt opgegeven om ervoor te zorgen dat het dialoogvenster boven het venster van de eigenaar blijft.
Voordat u de invoerfocus instelt, controleert de procedure de besturings-id van de standaardinvoerfocus. Het systeem geeft de venstergreep van de standaardinvoerfocus door in de parameter wParam. De functie GetDlgCtrlID retourneert de id voor het besturingselement dat is geïdentificeerd door de venstergreep. Als de id niet overeenkomt met de juiste id, gebruikt de procedure de functie SetFocus om de invoerfocus in te stellen. De functie GetDlgItem is vereist om de window handle van het gewenste controle-element op te halen.
Een sjabloon maken in het geheugen
Toepassingen passen soms de inhoud van dialoogvensters aan of wijzigen, afhankelijk van de huidige status van de gegevens die worden verwerkt. In dergelijke gevallen is het niet praktisch om alle mogelijke dialoogvenstersjablonen als resources in het uitvoerbare bestand van de toepassing op te geven. Maar het maken van sjablonen in het geheugen biedt de toepassing meer flexibiliteit om zich aan te passen aan alle omstandigheden.
In het volgende voorbeeld maakt de toepassing een sjabloon in het geheugen voor een modaal dialoogvenster met een bericht en OK en Help- knoppen.
In een dialoogvenstersjabloon moeten alle tekenreeksen, zoals het dialoogvenster en knoptitels, Unicode-tekenreeksen zijn. In dit voorbeeld wordt de functie MultiByteToWideChar gebruikt om deze Unicode-tekenreeksen te genereren.
De DLGITEMTEMPLATE structuren in een dialoogvenstersjabloon moeten worden uitgelijnd op DWORD grenzen. Als u deze structuren wilt uitlijnen, gebruikt dit voorbeeld een helperroutine die een invoeraanwijzer gebruikt en de dichtstbijzijnde aanwijzer retourneert die is uitgelijnd op een DWORD- grens.
#define ID_HELP 150
#define ID_TEXT 200
LPWORD lpwAlign(LPWORD lpIn)
{
ULONG ul;
ul = (ULONG)lpIn;
ul ++;
ul >>=1;
ul <<=1;
return (LPWORD)ul;
}
LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, LPSTR lpszMessage)
{
HGLOBAL hgbl;
LPDLGTEMPLATE lpdt;
LPDLGITEMTEMPLATE lpdit;
LPWORD lpw;
LPWSTR lpwsz;
LRESULT ret;
int nchar;
hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
if (!hgbl)
return -1;
lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
// Define a dialog box.
lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION;
lpdt->cdit = 3; // Number of controls
lpdt->x = 10; lpdt->y = 10;
lpdt->cx = 100; lpdt->cy = 100;
lpw = (LPWORD)(lpdt + 1);
*lpw++ = 0; // No menu
*lpw++ = 0; // Predefined dialog box class (by default)
lpwsz = (LPWSTR)lpw;
nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "My Dialog", -1, lpwsz, 50);
lpw += nchar;
//-----------------------
// Define an OK button.
//-----------------------
lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
lpdit = (LPDLGITEMTEMPLATE)lpw;
lpdit->x = 10; lpdit->y = 70;
lpdit->cx = 80; lpdit->cy = 20;
lpdit->id = IDOK; // OK button identifier
lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
lpw = (LPWORD)(lpdit + 1);
*lpw++ = 0xFFFF;
*lpw++ = 0x0080; // Button class
lpwsz = (LPWSTR)lpw;
nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "OK", -1, lpwsz, 50);
lpw += nchar;
*lpw++ = 0; // No creation data
//-----------------------
// Define a Help button.
//-----------------------
lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
lpdit = (LPDLGITEMTEMPLATE)lpw;
lpdit->x = 55; lpdit->y = 10;
lpdit->cx = 40; lpdit->cy = 20;
lpdit->id = ID_HELP; // Help button identifier
lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
lpw = (LPWORD)(lpdit + 1);
*lpw++ = 0xFFFF;
*lpw++ = 0x0080; // Button class atom
lpwsz = (LPWSTR)lpw;
nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "Help", -1, lpwsz, 50);
lpw += nchar;
*lpw++ = 0; // No creation data
//-----------------------
// Define a static text control.
//-----------------------
lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
lpdit = (LPDLGITEMTEMPLATE)lpw;
lpdit->x = 10; lpdit->y = 10;
lpdit->cx = 40; lpdit->cy = 20;
lpdit->id = ID_TEXT; // Text identifier
lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
lpw = (LPWORD)(lpdit + 1);
*lpw++ = 0xFFFF;
*lpw++ = 0x0082; // Static class
for (lpwsz = (LPWSTR)lpw; *lpwsz++ = (WCHAR)*lpszMessage++;);
lpw = (LPWORD)lpwsz;
*lpw++ = 0; // No creation data
GlobalUnlock(hgbl);
ret = DialogBoxIndirect(hinst,
(LPDLGTEMPLATE)hgbl,
hwndOwner,
(DLGPROC)DialogProc);
GlobalFree(hgbl);
return ret;
}