Praca z oknami dialogowymi

Transkrypt

Praca z oknami dialogowymi
MICROSOFT FOUNDATION CLASSES
PRACA Z OKNAMI DIALOGOWYMI
PROSTE, MODALNE OKNA DIALOGOWE
Najczęściej okna dialogowe tworzy się w edytorze zasobów. Należy utworzyć klasę dialogową przy użyciu
ClassWizarda (w poniższym przykładzie CMyDlg). Za pomocą ClassWizarda można też dodać do klasy
zmienne powiązane z poszczególnymi oknami kontrolnymi (podwójny klik + ctrl, lub też korzystając z zakładki
Member variables). Wówczas użycie okna może przedstawiać się następująco:
#include "MyDlg.h"
...
void CXxxx::OnShowDialog()
{
CMyDlg dlg;
dlg.m_data = m_data;
dlg.DoModal();
m_data = dlg.m_data;
}
// definicja klasy
// funkcja powiązana z opcją menu
// inicjalizacja danych dialogu
// wywołanie dialogu
// zachowanie danych dialogu
Funkcja DoModal uruchamia pętlę modalną dialogu i zwraca wartość określającą jej wynik, najczęściej kod
klawisza, którym zakończono pracę z dialogiem (IDOK, IDCANCEL, w istocie jest to wartość przekazana do
funkcji EndDialog, por. niżej).
INICJALIZACJA I ZAKOŃCZENIE PRACY DIALOGU
Właściwym miejscem dla umieszczenia sekwencji inicjalizującej jest funkcja reagująca na komunikat
WM_INITDIALOG – najczęściej OnInitDialog. Na zakończenie pracy z dialogiem jest wywoływana, odpowiednio, funkcja OnOk lub OnCancel. Istotnym ich elementem jest, iż obie wywołują EndDialog – funkcję kończącą
pętlę modalną okna. W analogiczny sposób można wymusić zakończenie pracy okna dialogowego w dowolnej
sytuacji.
DDX I DDV
Opisane w pierwszym punkcie powiązanie zmiennych składowych klasy okna dialogowego z oknami
kontrolnymi następuje poprzez zastosowanie techniki DDX (dialog data exchange). Bliźniacza technika, zwana
DDV (dialog data verification) pozwala na zweryfikowanie poprawności wprowadzanych danych. Działalność
ClassWizarda sprowadza się w tym zakresie do wstawienia wywołań funkcji DDX/DDV do standardowej funkcji
wirtualnej dialogów, DoDataExchange.
Mechanizm DDX/DDV pobudza się do działania wywołując odpowiednio:
UpdateData(FALSE);
UpdateData(TRUE);
// inicjalizacja zawartości okien kontrolnych
// zapamiętanie zawartości okien kontrolnych (jak przy OK)
Pierwsze z powyższych wywołań jest znajduje się domyślnie w OnInitDialog, drugie – w OnOk (ale nie w
OnCancel), dzięki czemu w przypadkach tak prostych, jak podany w pierwszym punkcie, wydaje się, że cały
mechanizm działa w pełni automatycznie. Jednak w przypadku, gdy z DDX/DDV chcemy skorzystać w trakcie
pracy pętli modalnej, będziemy zmuszeni do jawnego wywołania UpdateData. Alternatywną możliwością jest
pominięcie tego mechanizmu i zastosowanie funkcji GetDlgItemText, SetDlgItemText, GetDlgItemInt
i SetDlgItemInt. Jest to szczególnie zalecane, gdy pracujemy tylko z jednym oknem kontrolnym, a dialog
zawiera ich wiele (UpdateData(FALSE) może wtedy powodować migotanie).
PRACA Z OKNAMI NIEMODALNYMI
Oto kilka zasad, których trzymać się należy tworząc okna niemodalne:
1. Okna niemodalne nie zakładają pętli modalnej, zatem zamiast DoModal stosujemy po prostu Create.
2. Okna niemodalne żyją zwykle dłużej, niż zmienne automatyczne w funkcji, która je tworzy; stosujemy
zatem zmienne dynamiczne zamiast automatycznych.
3. Funkcja EndDialog ustawia flagę, która powoduje wyjście z pętli modalnej. Okna niemodalne nie posiadają
pętli modalnej, nie należy więc w stosunku do nich stosować EndDialog. Zamiast tego wywołujemy De-
stroyWindow. Wymaga to jednak zwykle przepisania OnOk, OnCancel i OnClose, które domyślnie wywołują EndDialog.
4. Skoro dialog jest zmienną tworzoną dynamicznie, należy ją kiedyś usunąć: właściwym miejscem jest PostNcDestroy().
5. W zasobach dialogu należy zaznaczyć opcję Visible (STYLE WS_VISIBLE).
Przykład:
class CModelessDlg : public CDialog
{
...
void OnOk()
{
UpdateData(TRUE);
DestroyWindow();
}
// analogicznie przepisać też OnCancel i OnClose
void PostNcDestroy()
{
delete this;
// wygląda okropnie, ale działa dobrze
}
};
CModelessDlg pDlg = new CModelessDlg;
pDlg->Create(IDD_DIALOG1);
// utworzenie zmiennej dynamicznej
// utworzenie okna dialogowego
WSPÓŁPRACA Z OKNAMI KONTROLNYMI
Operacje wykonywane przez użytkownika w stosunku do okien kontrolnych (na przykład naciśnięcie przycisku
lub zmiana zawartości okna edycyjnego) powodują wysłanie do właściciela (na ogół okna dialogowego) specjalnego komunikatu, zwanego notyfikacją. W przypadku starszych okien kontrolnych, zachowujących zgodność z
Windows 3.1, jest to szczególna forma komunikatu WM_COMMAND. Nowsze kontrolki (common controls)
stosują specjalny komunikat WM_NOTIFY. W jednym i drugim przypadku nie trudno wprowadzić do klasy okna
dialogowego funkcje reagujące na notyfikacje – oczywiście za pomocą ClassWizarda.
Mechanizm notyfikacji daje możliwość reagowania na zdarzenia dotyczące okien potomnych przez okno rodzicielskie. Unikamy w ten sposób często potrzeby tworzenia klas potomnych dla okien kontrolnych nawet, jeśli ich
zachowanie ma w istotny sposób odbiegać od standardu – wystarczy, że klasę okna rodzicielskiego odpowiednio
uwrażliwimy na notyfikacje nadchodzące od okien potomnych.
TWORZENIE WŁASNYCH KLAS OKIEN KONTROLNYCH – SUBCLASSING
Tworzenie własnych klas okien kontrolnych ma sens wtedy, gdy chcemy wielokrotnie używać specyficznych
okien bez konieczności każdorazowego modyfikowania okna rodzica.
Własne klasy okien kontrolnych można implementować w oparciu o istniejące klasy, stosując normalne
dziedziczenie C++. Warto skorzystać z mechanizmu odbitych notyfikacji (message reflection): każdą notyfikację
przesłaną do rodzica można przechwycić na poziomie okna potomnego wysyłającego tę notyfikację (w praktyce
sprowadza się to jak zwykle do wykorzystania ClassWizarda).
Aby powiązać obiekt własnej klasy potomnej z elementem zasobu dialogowego, należy stworzyć odpowiednią
zmienną składową i zainicjalizować ją, najlepiej w obrębie OnInitDialog, w następujący sposób:
m_myControl.SubclassDlgItem(IDC_MY_CTRL_ID, this);
PODSUMOWANIE
Uwaga! Tak zainicjalizowana zmienna nie może być zadeklarowana jednocześnie w technice DDX/DDV!
DoModal
Create
UpdateData(BOOL)
Set/GetDlgItemText/Int
EndDialog
DestroyWindow
SubclassDlgItem
OnInitDialog
OnOk OnCancel OnClose
PostNcDestroy
uruchamia dialog – przeprowadza modalną pętlę komunikatów
tworzy dialog niemodalny
uruchamia – na żądanie – mechanizm DDX/DDV (TRUE jak przy OK)
bezpośredni dostęp do zawartości okien kontrolnych
kończy modalną pętlę komunikatów (nieprzydatne dla dialogów niemodalnych)
usuwa okno (nieprzydatne dla dialogów modalnych)
przydziela zasobowi wskazany obiekt okna kontrolnego dowolnej klasy
wywoływana podczas inicjalizacji dialogu
wywoływane na zakończenie dialogu (przy różnych okazjach)
w dialogach niemodalnych – miejsce na umieszczenie delete this

Podobne dokumenty