Sekmeli İletişim Kutusu Oluşturma
Bu bölümdeki örnekte, birden çok denetim sayfası sağlamak için sekmeleri kullanan bir iletişim kutusunun nasıl oluşturulacağı gösterilmektedir. Ana iletişim kutusu bir modal iletişim kutusudur. Denetimlerin her sayfası, WS_CHILD stiline sahip bir iletişim kutusu şablonuyla tanımlanır. Bir sekme seçildiğinde, gelen sayfa için modsuz bir iletişim kutusu oluşturulur ve giden sayfanın iletişim kutusu yok edilir.
Not
Çoğu durumda, özellik sayfalarını kullanarak birden çok sayfalı iletişim kutularını daha kolay uygulayabilirsiniz. Özellik sayfaları hakkında daha fazla bilgi için bkz. Özellik Sayfaları Hakkında.
Ana iletişim kutusunun şablonu yalnızca iki düğme denetimini tanımlar. WM_INITDIALOG iletisini işlerken, iletişim kutusu yordamı bir sekme denetimi oluşturur ve alt iletişim kutularının her biri için iletişim kutusu şablonu kaynaklarını yükler.
Bilmeniz gerekenler
Teknolojileri
Önkoşullar
- C/C++
- Windows Kullanıcı Arabirimi Programlama
Talimatlar
Sekmeli İletişim Kutusu Oluşturma
Bilgiler DLGHDR adlı uygulama tanımlı bir yapıya kaydedilir. Bu yapıya ilişkin bir işaretçi, SetWindowLong işlevi kullanılarak iletişim kutusu penceresiyle ilişkilendirilir. Yapı, uygulamanın üst bilgi dosyasında aşağıdaki gibi tanımlanır.
#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;
Aşağıdaki işlev, ana iletişim kutusu için WM_INITDIALOG iletisini işler. İşlev DLGHDR
yapısını ayırır, alt iletişim kutuları için iletişim kutusu şablon kaynaklarını yükler ve sekme denetimini oluşturur.
Her alt iletişim kutusunun boyutu DLGTEMPLATEEX yapısı tarafından belirtilir. İşlev, her iletişim kutusunun boyutunu inceler ve sekme denetimi için uygun bir boyut hesaplamak üzere TCM_ADJUSTRECT iletisinin makrosunu kullanır. Ardından iletişim kutusunu boyutlandırıp iki düğmeyi uygun şekilde konumlandırıyor. Bu örnek, TabCtrl_AdjustRect makroyu kullanarak TCM_ADJUSTRECT gönderir.
// 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);
}
Aşağıdaki işlev, ana iletişim kutusu için TCN_SELCHANGE bildirim kodunu işler. İşlev, varsa giden sayfanın iletişim kutusunu yok eder. Ardından, gelen sayfa için modsuz bir iletişim kutusu oluşturmak üzere CreateDialogIndirect işlevini kullanır.
// 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;
}
Aşağıdaki fonksiyon, alt dialog kutularının her biri için WM_INITDIALOG mesajını işler. CreateDialogIndirect işlevi kullanılarak oluşturulan iletişim kutusunun konumunu belirtemezsiniz. Bu işlev, SetWindowPos işlevini kullanarak alt iletişim kutusunu sekme denetiminin görüntüleme alanına yerleştirir.
// 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;
}
İlgili konular