Windows Programmierung: Property Sheet |
Das Property Sheet ist kein Kontrollelement, sondern ein kompletter Dialog. Man kann ihn also nicht einfach in einem normalen Fenster unterbringen. Ein Property Sheet besteht aus mehreren Seiten, die jeweils wie eine Dialogbox in den Ressourcen definiert wird. Es werden lediglich der Ok- und der Abbruch-Buttonweggelassen, da diese vom Property-Sheet geliefert werden.
Zur Vereinfachung des Beispiels wird nur ein Dialog und eine Dialogfensterfunktion für mehrere Seiten verwendet. Die Ressource-ID ist IDD_PERSON und die Fensterfunktion des Dialoges ist DataInput.
#include <COMMCTRL.H> extern HINSTANCE hInst; HWND CreatePropertySheet (HWND hwndOwner) { PROPSHEETPAGE psp [2]; PROPSHEETHEADER psh = {0}; psp[0].dwSize = sizeof (PROPSHEETPAGE); psp[0].dwFlags = PSP_USETITLE; psp[0].hInstance = hInst; psp[0].pszTemplate = MAKEINTRESOURCE (IDD_PERSON); psp[0].pszIcon = NULL; psp[0].pfnDlgProc = DataInput; psp[0].pszTitle = "Person"; psp[0].lParam = 0; psp[1].dwSize = sizeof (PROPSHEETPAGE); psp[1].dwFlags = PSP_USETITLE; psp[1].hInstance = hInst; psp[1].pszTemplate = MAKEINTRESOURCE (IDD_PERSON); psp[1].pszIcon = NULL; psp[1].pfnDlgProc = DataInput; psp[1].pszTitle = "Vater"; psp[1].lParam = 0; psh.dwSize = PROPSHEETHEADER_V1_SIZE; psh.dwFlags = PSH_PROPSHEETPAGE; psh.hwndParent = hwndOwner; psh.hInstance = hInst; psh.pszIcon = NULL; psh.pszCaption = (LPSTR)"Family"; psh.nPages = sizeof (psp) / sizeof (PROPSHEETPAGE); psh.ppsp = (LPCPROPSHEETPAGE) &psp; return (HWND)PropertySheet (&psh); ); |
Wird im dwFlags-Element PSH_NOAPPLYNOW hinzugenommen (durch Odern mit | ), erscheint der Apply-Button nicht.
Bei der Bestimmung der Grösse der PROPSHEETHEADER-Struktur ist die Angabe ungewöhnlich. Hier verwendet man üblicherweise eine Konstruktion wie
psh.dwSize = sizeof(PROPSHEETHEADER);Allerdings besteht das Problem, daß mit der Version 4.71 der COMCTL32.DLL die Struktur etwas größer geworden ist. Da sizeof eine Konstante zur Laufzeit liefert, würde ein Entwicklungssystem, das einen Update hat, ein Programm erzeugen, das unter alten Versionen nicht läuft. Man kann dies verhindern, indem man
psh.dwSize = PROPSHEETHEADER_V1_SIZE;verwendet. Will man dynamisch arbeiten, muß die Funktion DllGetVersion verwendet werden, um zu ermitteln, welche Version auf dem aktuellen System läuft.
BOOL APIENTRY DataInput(HWND hDlg, UINT message, UINT wParam, LONG lParam) { PROPSHEETPAGE *ps; switch (message) { case WM_INITDIALOG: // Save the PROPSHEETPAGE information. ps = (PROPSHEETPAGE *)lParam; // sichere das in den Fensterdaten... return TRUE; case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE: break; case PSN_APPLY: if (AllOk()) { SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR); } else { SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); } return TRUE; case PSN_KILLACTIVE: SetWindowLong(hDlg, DWL_MSGRESULT, FALSE); return 1; case PSN_RESET: SetWindowLong(hDlg, DWL_MSGRESULT, FALSE); break; } } return FALSE; } |
Bei der Initialisierung wird der Zeiger auf die PropertyPage, also die Seite übergeben. Da dieser Dialog mehrfach verwendet wird, muss man die Daten für jedes Objekt in den Fensterdaten sichern. Dies wird an anderer Stelle beschrieben. Wird für jede Seite eine andere Dialogfensterfunktion verwendet, ist das nicht notwendig.
Die Fensterfunktion darf nicht EndDialog aufrufen. Statt der Behandlung von OK und Abbruch werden die WM_NOTIFY-Ereignisse PSN_SETACTIVE, PSN_APPLY, PSN_KILLACTIVE und PSN_RESET bearbeitet
Wird PSNRET_INVALID_NOCHANGEPAGE zurückgegeben, wird verhindert, dass die Daten übernommen werden und der Fokus wird auf diese Seite gebracht. Die Rückgabe von PSNRET_NOERROR akzeptiert die Änderungen.
Die Rückgabe erfolgt in diesem Fall dadurch, dass SetWindowLong mit dem Parameter DWL_MSGRESULT gerufen wird. Der dritte Parameter sind die oben genannten PSNRET-Konstanten. Damit dies gelesen wird, muss TRUE returniert werden.
Auf die gleiche Weise wie bei PSN_APPLY kann ein Wechseln der Seite verhindert werden. Es sollte eine Messagebox erscheinen, die dieses Verhalten dem Anwender erläutert.
PSM_ADDPAGE wParam = 0; lParam = (LPARAM) (HPROPSHEETPAGE) hpage; oder BOOL PropSheet_AddPage(HWND hPropSheetDlg, HPROPSHEETPAGE hpage);
HPROPSHEETPAGE CreatePropertySheetPage(LPCPROPSHEETPAGE lppsp);Als Parameter erwartet CreatePropertySheetPage die Adresse der PROPSHEETPAGE-Struktur, die die Seite definiert. Der Rückgabewert ist das gesuchte Handle.
PSM_REMOVEPAGE wParam = (WPARAM) (int) index; lParam = (LPARAM) (HPROPSHEETPAGE) hpage); oder VOID PropSheet_RemovePage(HWND hPropSheetDlg, int index, HPROPSHEETPAGE hpage);
Homepage - Windows-API-Programmierung | (C) Copyright 1999 Arnold Willemer |