Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Im Beispiel in diesem Abschnitt wird veranschaulicht, wie Sie ein Dialogfeld erstellen, das Mithilfe von Registerkarten mehrere Seiten mit Steuerelementen bereitstellt. Das Dialogfeld Standard ist ein modales Dialogfeld. Jede Seite von Steuerelementen wird durch eine Dialogfeldvorlage definiert, die den WS_CHILD Stil aufweist. Wenn eine Registerkarte ausgewählt wird, wird ein dialogfeld ohne Modus für die eingehende Seite erstellt, und das Dialogfeld für die ausgehende Seite wird zerstört.
Hinweis
In vielen Fällen können Sie dialogfelder mit mehreren Seiten einfacher implementieren, indem Sie Eigenschaftenblätter verwenden. Weitere Informationen zu Eigenschaftenblättern finden Sie unter Informationen zu Eigenschaftenblättern.
Die Vorlage für das Dialogfeld Standard definiert einfach zwei Schaltflächensteuerelemente. Bei der Verarbeitung der WM_INITDIALOG Meldung erstellt die Dialogfeldprozedur ein Registerkartensteuerelement und lädt die Ressourcen der Dialogfeldvorlagen für jedes untergeordnete Dialogfeld.
Wichtige Informationen
Technologien
Voraussetzungen
- C/C++
- Programmierung der Windows-Benutzeroberfläche
Anweisungen
Dialogfeld "Registerkartenformat erstellen"
Die Informationen werden in einer anwendungsdefinierten Struktur namens DLGHDR gespeichert. Ein Zeiger auf diese Struktur wird dem Dialogfeldfenster mithilfe der SetWindowLong-Funktion zugeordnet. Die Struktur wird in der Headerdatei der Anwendung wie folgt definiert.
#define C_PAGES 3
typedef struct tag_dlghdr {
HWND hwndTab; // tab control
HWND hwndDisplay; // current child dialog box
RECT rcDisplay; // display rectangle for the tab control
DLGTEMPLATEEX *apRes[C_PAGES];
} DLGHDR;
Die folgende Funktion verarbeitet die WM_INITDIALOG-Meldung für das Dialogfeld Standard. Die Funktion ordnet die DLGHDR Struktur zu, lädt die Ressourcen der Dialogfeldvorlagen für die untergeordneten Dialogfelder und erstellt das Registerkartensteuerelement.
Die Größe jedes untergeordneten Dialogfelds wird durch die DLGTEMPLATEEX-Struktur angegeben. Die Funktion untersucht die Größe der einzelnen Dialogfelder und verwendet das Makro für die TCM_ADJUSTRECT Meldung, um eine geeignete Größe für das Registerkartensteuerelement zu berechnen. Anschließend wird das Dialogfeld angepasst und die beiden Schaltflächen entsprechend positioniert. In diesem Beispiel wird TCM_ADJUSTRECT mithilfe des Makros TabCtrl_AdjustRect gesendet.
// Handles the WM_INITDIALOG message for a dialog box that contains
// a tab control used to select among three child dialog boxes.
// Returns a result code.
// hwndDlg - handle of the dialog box.
//
HRESULT OnTabbedDialogInit(HWND hwndDlg)
{
INITCOMMONCONTROLSEX iccex;
DWORD dwDlgBase = GetDialogBaseUnits();
int cxMargin = LOWORD(dwDlgBase) / 4;
int cyMargin = HIWORD(dwDlgBase) / 8;
TCITEM tie;
RECT rcTab;
HWND hwndButton;
RECT rcButton;
int i;
// Initialize common controls.
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&iccex);
// Allocate memory for the DLGHDR structure. Remember to
// free this memory before the dialog box is destroyed.
DLGHDR *pHdr = (DLGHDR *) LocalAlloc(LPTR, sizeof(DLGHDR));
// Save a pointer to the DLGHDR structure in the window
// data of the dialog box.
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pHdr);
// Create the tab control. Note that g_hInst is a global
// instance handle.
pHdr->hwndTab = CreateWindow(
WC_TABCONTROL, L"",
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
0, 0, 100, 100,
hwndDlg, NULL, g_hInst, NULL
);
if (pHdr->hwndTab == NULL)
{
return HRESULT_FROM_WIN32(GetLastError());
}
// Add a tab for each of the three child dialog boxes.
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = L"First";
TabCtrl_InsertItem(pHdr->hwndTab, 0, &tie);
tie.pszText = L"Second";
TabCtrl_InsertItem(pHdr->hwndTab, 1, &tie);
tie.pszText = L"Third";
TabCtrl_InsertItem(pHdr->hwndTab, 2, &tie);
// Lock the resources for the three child dialog boxes.
pHdr->apRes[0] = DoLockDlgRes(MAKEINTRESOURCE(IDD_FIRSTDLG));
pHdr->apRes[1] = DoLockDlgRes(MAKEINTRESOURCE(IDD_SECONDDLG));
pHdr->apRes[2] = DoLockDlgRes(MAKEINTRESOURCE(IDD_THIRDDLG));
// Determine a bounding rectangle that is large enough to
// contain the largest child dialog box.
SetRectEmpty(&rcTab);
for (i = 0; i < C_PAGES; i++)
{
if (pHdr->apRes[i]->cx > rcTab.right)
rcTab.right = pHdr->apRes[i]->cx;
if (pHdr->apRes[i]->cy > rcTab.bottom)
rcTab.bottom = pHdr->apRes[i]->cy;
}
// Map the rectangle from dialog box units to pixels.
MapDialogRect(hwndDlg, &rcTab);
// Calculate how large to make the tab control, so
// the display area can accommodate all the child dialog boxes.
TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab);
OffsetRect(&rcTab, cxMargin - rcTab.left, cyMargin - rcTab.top);
// Calculate the display rectangle.
CopyRect(&pHdr->rcDisplay, &rcTab);
TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay);
// Set the size and position of the tab control, buttons,
// and dialog box.
SetWindowPos(pHdr->hwndTab, NULL, rcTab.left, rcTab.top,
rcTab.right - rcTab.left, rcTab.bottom - rcTab.top,
SWP_NOZORDER);
// Move the first button below the tab control.
hwndButton = GetDlgItem(hwndDlg, IDB_CLOSE);
SetWindowPos(hwndButton, NULL,
rcTab.left, rcTab.bottom + cyMargin, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
// Determine the size of the button.
GetWindowRect(hwndButton, &rcButton);
rcButton.right -= rcButton.left;
rcButton.bottom -= rcButton.top;
// Move the second button to the right of the first.
hwndButton = GetDlgItem(hwndDlg, IDB_TEST);
SetWindowPos(hwndButton, NULL,
rcTab.left + rcButton.right + cxMargin,
rcTab.bottom + cyMargin, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
// Size the dialog box.
SetWindowPos(hwndDlg, NULL, 0, 0,
rcTab.right + cyMargin + (2 * GetSystemMetrics(SM_CXDLGFRAME)),
rcTab.bottom + rcButton.bottom + (2 * cyMargin)
+ (2 * GetSystemMetrics(SM_CYDLGFRAME))
+ GetSystemMetrics(SM_CYCAPTION),
SWP_NOMOVE | SWP_NOZORDER);
// Simulate selection of the first item.
OnSelChanged(hwndDlg);
return S_OK;
}
// Loads and locks a dialog box template resource.
// Returns the address of the locked dialog box template resource.
// lpszResName - name of the resource.
//
DLGTEMPLATEEX* DoLockDlgRes(LPCTSTR lpszResName)
{
HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG);
// Note that g_hInst is the global instance handle
HGLOBAL hglb = LoadResource(g_hInst, hrsrc);
return (DLGTEMPLATEEX *) LockResource(hglb);
}
Die folgende Funktion verarbeitet den TCN_SELCHANGE Benachrichtigungscode für das Dialogfeld Standard. Die Funktion zerstört ggf. das Dialogfeld für die ausgehende Seite. Anschließend wird die CreateDialogIndirect-Funktion verwendet, um ein modusloses Dialogfeld für die eingehende Seite zu erstellen.
// Processes the TCN_SELCHANGE notification.
// hwndDlg - handle to the parent dialog box.
//
VOID OnSelChanged(HWND hwndDlg)
{
// Get the dialog header data.
DLGHDR *pHdr = (DLGHDR *) GetWindowLongPtr(
hwndDlg, GWLP_USERDATA);
// Get the index of the selected tab.
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
// Destroy the current child dialog box, if any.
if (pHdr->hwndDisplay != NULL)
DestroyWindow(pHdr->hwndDisplay);
// Create the new child dialog box. Note that g_hInst is the
// global instance handle.
pHdr->hwndDisplay = CreateDialogIndirect(g_hInst,
(DLGTEMPLATE *)pHdr->apRes[iSel], hwndDlg, ChildDialogProc);
return;
}
Die folgende Funktion verarbeitet die WM_INITDIALOG-Meldung für jedes der untergeordneten Dialogfelder. Sie können die Position eines Dialogfelds, das mit der CreateDialogIndirect-Funktion erstellt wird, nicht angeben. Diese Funktion verwendet die SetWindowPos-Funktion , um das untergeordnete Dialogfeld im Anzeigebereich des Registerkartensteuerelements zu positionieren.
// Positions the child dialog box to occupy the display area of the
// tab control.
// hwndDlg - handle of the dialog box.
//
VOID WINAPI OnChildDialogInit(HWND hwndDlg)
{
HWND hwndParent = GetParent(hwndDlg);
DLGHDR *pHdr = (DLGHDR *) GetWindowLongPtr(
hwndParent, GWLP_USERDATA);
SetWindowPos(hwndDlg, NULL, pHdr->rcDisplay.left,
pHdr->rcDisplay.top,//-2,
(pHdr->rcDisplay.right - pHdr->rcDisplay.left),
(pHdr->rcDisplay.bottom - pHdr->rcDisplay.top),
SWP_SHOWWINDOW);
return;
}
Zugehörige Themen