Udostępnij za pośrednictwem


TN026: procedury DDX i DDV

Uwaga / Notatka

Następująca uwaga techniczna nie została zaktualizowana, ponieważ została po raz pierwszy uwzględniona w dokumentacji online. W związku z tym niektóre procedury i tematy mogą być nieaktualne lub nieprawidłowe. Aby uzyskać najnowsze informacje, zaleca się wyszukanie interesującego tematu w indeksie dokumentacji online.

W tej notatce opisano architekturę wymiany danych okna dialogowego (DDX) i weryfikacji danych dialogowych (DDV). Opisuje również, jak napisać procedurę DDX_ lub DDV_ oraz jak rozszerzyć ClassWizard w celu korzystania z rutyn.

Przegląd wymiany danych dialogowych

Wszystkie funkcje danych okna dialogowego są wykonywane przy użyciu kodu C++. Brak specjalnych zasobów ani makr magicznych. Sercem mechanizmu jest funkcja wirtualna, która jest zastępowana w każdej klasie okna dialogowego, która wykonuje wymianę i walidację danych okna dialogowego. Zawsze można go znaleźć w tej formie:

void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);   // call base class

    //{{AFX_DATA_MAP(CMyDialog)
        <data_exchange_function_call>
        <data_validation_function_call>
    //}}AFX_DATA_MAP
}

Komentarze AFX w specjalnym formacie umożliwiają ClassWizardowi lokalizowanie i edytowanie kodu w tej funkcji. Kod niekompatybilny z ClassWizard powinien być umieszczony poza specjalnymi komentarzami formatowymi.

W powyższym przykładzie <data_exchange_function_call> ma postać:

DDX_Custom(pDX, nIDC, field);

i <data_validation_function_call> jest opcjonalny i ma postać:

DDV_Custom(pDX, field, ...);

W każdej DoDataExchange funkcji może znajdować się więcej niż jedna para DDX_/DDV_.

Zobacz „afxdd_.h”, aby uzyskać listę wszystkich rutyn wymiany danych w oknach dialogowych oraz rutyn weryfikacji danych dialogowych dostępnych w MFC.

Dane dialogu to właśnie te dane członkowskie w klasie CMyDialog. Nie jest przechowywany w strukturze ani w nic podobnego.

Notatki

Chociaż nazywamy to "danymi dialogowymi", wszystkie funkcje są dostępne w dowolnej klasie pochodnej CWnd i nie są ograniczone tylko do okien dialogowych.

Początkowe wartości danych są ustawiane w standardowym konstruktorze języka C++, zwykle w bloku z komentarzami //{{AFX_DATA_INIT i //}}AFX_DATA_INIT .

CWnd::UpdateData to operacja, która wykonuje inicjowanie i obsługę błędów wokół wywołania metody DoDataExchange.

Możesz wywołać metodę CWnd::UpdateData w dowolnym momencie, aby przeprowadzić wymianę i walidację danych. Domyślnie UpdateData(TRUE) jest wywoływana w domyślnej CDialog::OnOK procedurze obsługi i UpdateData(FALSE) jest wywoływana w domyślnym CDialog::OnInitDialog.

Rutyna DDV_ powinna natychmiast postępować zgodnie z procedurą DDX_ dla tego pola.

Jak to działa

Nie musisz rozumieć następujących informacji, aby użyć danych okna dialogowego. Jednak zrozumienie, jak to działa w tle, pomoże Ci napisać własną procedurę wymiany lub weryfikacji.

DoDataExchange funkcja składowa jest podobna do Serialize funkcji składowej — jest odpowiedzialna za pobieranie lub ustawianie danych z/do formy zewnętrznej (w tym przypadku kontrolek w oknie dialogowym) z/do danych składowych w klasie. Parametr pDX jest kontekstem do wymiany danych i jest podobny do parametru CArchive do CObject::Serialize. PDX (CDataExchangeobiekt) ma flagę kierunku, podobnie jak CArchive ma flagę kierunku.

  • Jeśli !m_bSaveAndValidate, wczytaj stan danych do kontrolek.

  • Jeśli m_bSaveAndValidate jest spełnione, ustaw stan danych z elementów sterujących.

Walidacja występuje tylko wtedy, gdy m_bSaveAndValidate jest ustawiona. Wartość parametru m_bSaveAndValidate jest określana przez parametr BOOL na CWnd::UpdateData.

Istnieją trzy inni interesujący CDataExchange członkowie.

  • m_pDlgWnd: okno (zazwyczaj okno dialogowe), które zawiera kontrolki. Zapobiega to temu, aby wywołania funkcji globalnych DDX_ i DDV_ nie musiały przekazywać wskaźnika 'this' do każdej operacji DDX/DDV.

  • PrepareCtrl, i PrepareEditCtrl: przygotowuje kontrolkę okna dialogowego do wymiany danych. Przechowuje uchwyt tej kontrolki do ustawiania fokusu, jeśli walidacja zakończy się niepowodzeniem. PrepareCtrl jest używany w przypadku kontrolek nieedytacyjnych i PrepareEditCtrl jest używany do edycji kontrolek.

  • Fail: wywoływana po wywołaniu pola komunikatu ostrzegającego użytkownika o błędzie wejściowym. Ta procedura przywróci fokus do ostatniej kontrolki (ostatnie wywołanie metody PrepareCtrl lub PrepareEditCtrl), a następnie zgłosi wyjątek. Ta funkcja składowa może być wywoływana zarówno z procedur DDX_, jak i DDV_.

Rozszerzenia użytkownika

Istnieje kilka sposobów rozszerzenia domyślnego mechanizmu DDX/DDV. Masz następujące możliwości:

  • Dodaj nowe typy danych.

    CTime
    
  • Dodaj nowe procedury wymiany (DDX_).

    void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
    
  • Dodaj nowe procedury weryfikacji (DDV_).

    void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
    // make sure time is in the future or past
    
  • Przekaż dowolne wyrażenia do procedur walidacji.

    DDV_MinMax(pDX, age, 0, m_maxAge);
    

    Uwaga / Notatka

    Takie dowolne wyrażenia nie mogą być edytowane przez ClassWizard i dlatego powinny być przenoszone poza specjalne komentarze formatu (//{{AFX_DATA_MAP(CMyClass)).

Niech funkcja składowa DoDataExchange zawiera instrukcje warunkowe lub inne prawidłowe instrukcje C++ z przeplatanymi wywołaniami funkcji wymiany i walidacji.

//{{AFX_DATA_MAP(CMyClass)
DDX_Check(pDX, IDC_SEX, m_bFemale);
DDX_Text(pDX, IDC_EDIT1, m_age);
//}}AFX_DATA_MAP
if (m_bFemale)
    DDV_MinMax(pDX, age, 0, m_maxFemaleAge);
else
    DDV_MinMax(pDX, age, 0, m_maxMaleAge);

Uwaga / Notatka

Jak pokazano powyżej, taki kod nie może być edytowany przez ClassWizard i powinien być używany tylko poza komentarzami o specjalnym formacie.

Wsparcie ClassWizard

ClassWizard obsługuje podzestaw dostosowań DDX/DDV, umożliwiając integrację własnych procedur DDX_ i DDV_ z interfejsem użytkownika ClassWizard. Jest to opłacalne tylko wtedy, gdy planujesz ponownie używać określonych procedur DDX i DDV w projekcie lub w wielu projektach.

W tym celu w pliku DDX.CLW są tworzone specjalne wpisy (poprzednie wersje Visual C++ przechowywały te informacje w pliku APSTUDIO.INI) lub w pliku .CLW twojego projektu. Wpisy specjalne można wprowadzić w sekcji [Informacje ogólne] pliku projektu .CLW lub w sekcji [ExtraDDX] pliku DDX.CLW w katalogu \Program Files\Microsoft Visual Studio\Visual C++\bin. Może być konieczne utworzenie pliku DDX.CLW, jeśli jeszcze nie istnieje. Jeśli planujesz używać niestandardowych procedur DDX_/DDV_ tylko w określonym projekcie, zamiast tego dodaj wpisy do sekcji [Informacje ogólne] w pliku projektu .CLW. Jeśli planujesz używać procedur w wielu projektach, dodaj wpisy do sekcji [ExtraDDX] DDX.CLW.

Ogólny format tych wpisów specjalnych to:

ExtraDDXCount=n

gdzie n jest liczbą wierszy ExtraDDX? do wprowadzenia

ExtraDDX?=keys; vb-keys; monit; typ; initValue; DDX_Proc [; DDV_Proc; prompt1; arg1 [; prompt2; fmt2]]

gdzie? jest liczbą 1 — n wskazującą typ DDX na zdefiniowanej liście.

Każde pole jest rozdzielane znakiem ";". Pola i ich przeznaczenie zostały opisane poniżej.

  • Klucze

    Lista pojedynczych znaków wskazująca, dla którego okno dialogowe steruje tym typem zmiennej, jest dozwolona.

    Charakter Dozwolona kontrola
    E Edytuj…
    C pole wyboru dwustanowe
    Bez kontekstu nie można zapewnić adekwatnego tłumaczenia litery "c". pole wyboru trzy-stanowe
    R pierwszy przycisk radiowy w grupie
    L pole listy niesortowanej
    l okno listy posortowanej
    M pole kombi (z elementem edycji)
    N lista rozwijana bez sortowania
    n posortowana lista rozwijana
    1 Jeśli wstawka DDX powinna zostać dodana do nagłówka listy (domyślnie jest dodawana do końca) Jest to zwykle używane w przypadku procedur DDX, które przenoszą właściwość "Control".
  • vb-keys

    To pole jest używane tylko w 16-bitowym produkcie dla kontrolek VBX (kontrolki VBX nie są obsługiwane w produkcie 32-bitowym)

  • zachęta

    Ciąg do umieszczenia w polu rozwijanym Właściwości (bez cudzysłowów)

  • typ

    Pojedynczy identyfikator typu do umieszczenia w pliku nagłówkowym. W naszym przykładzie powyżej z DDX_Time, będzie to ustawione na CTime.

  • vb-keys

    Nieużytne w tej wersji i zawsze powinny być puste

  • initValue

    Wartość początkowa — 0 lub pusta. Jeśli jest on pusty, w sekcji //{{AFX_DATA_INIT pliku implementacji nie zostanie zapisany wiersz inicjowania. Pusty wpis powinien być używany dla obiektów języka C++ (takich jak CString, CTimei tak dalej), które mają konstruktory, które gwarantują poprawną inicjację.

  • DDX_Proc

    Pojedynczy identyfikator procedury DDX_. Nazwa funkcji języka C++ musi zaczynać się od ciągu "DDX_", ale nie zawieraj "DDX_" w identyfikatorze <DDX_Proc>. W powyższym przykładzie identyfikator <DDX_Proc> to Czas. Gdy klasa ClassWizard zapisuje wywołanie funkcji do pliku implementacji w sekcji {{AFX_DATA_MAP, dołącza tę nazwę do DDX_, w ten sposób docierając do DDX_Time.

  • komentarz

    Komentarz do wyświetlenia w oknie dialogowym dla zmiennej z tym DDX. Umieść tutaj dowolny tekst i zazwyczaj podaj coś, co opisuje operację wykonywaną przez parę DDX/DDV.

  • DDV_Proc

    Część DDV wpisu jest opcjonalna. Nie wszystkie procedury DDX mają odpowiednie procedury DDV. Często bardziej wygodne jest uwzględnienie fazy weryfikacji jako integralnej części transferu. Jest to często przypadek, gdy rutyna DDV nie wymaga żadnych parametrów, ponieważ KlasaWizard nie obsługuje procedur DDV bez żadnych parametrów.

  • Arg

    Pojedynczy identyfikator procedury DDV_. Nazwa funkcji języka C++ musi zaczynać się od "DDV_", ale nie należy dołączać "DDX_" w identyfikatorze <DDX_Proc> .

    arg następuje 1 lub 2 args DDV:

    • promptN

      Ciąg do umieszczenia nad elementem edycji (ze znakiem & jako skrót).

    • fmtN

      Formatuj znak dla typu arg, jeden z:

      Charakter Typ
      d int (integer)
      u niepodpisane int
      D długi int (czyli długi)
      U long unsigned (czyli DWORD)
      f unoszenie się
      F podwójny
      s sznurek

Zobacz także

Uwagi techniczne według numeru
Uwagi techniczne według kategorii