TN026: DDX- und DDV-Routinen

Hinweis

Der folgende technische Hinweis wurde seit dem ersten Erscheinen in der Onlinedokumentation nicht aktualisiert. Daher können einige Verfahren und Themen veraltet oder falsch sein. Um aktuelle Informationen zu erhalten, wird empfohlen, das gewünschte Thema im Index der Onlinedokumentation zu suchen.

In diesem Hinweis werden die Architektur des Dialogdatenaustauschs (Dialog Data Exchange, DDX) und die DDV-Architektur (Dialog Data Exchange) beschrieben. Außerdem wird beschrieben, wie Sie eine DDX_- oder DDV_Prozedur schreiben und wie Sie ClassWizard erweitern können, um Ihre Routinen zu verwenden.

Übersicht über Dialogdatenaustausch

Alle Dialogfelddatenfunktionen werden mit C++-Code ausgeführt. Es gibt keine speziellen Ressourcen oder magischen Makros. Das Herzstück des Mechanismus ist eine virtuelle Funktion, die in jeder Dialogklasse außer Kraft gesetzt wird, die Dialogdatenaustausch und Validierung durchführt. Sie wird immer in dieser Form gefunden:

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
}

Mit dem speziellen Format von AFX-Kommentaren kann ClassWizard den Code in dieser Funktion suchen und bearbeiten. Code, der nicht mit ClassWizard kompatibel ist, sollte außerhalb der Speziellen Formatkommentare platziert werden.

Im obigen> Beispiel <befindet sich data_exchange_function_call in der Form:

DDX_Custom(pDX, nIDC, field);

und <data_validation_function_call> ist optional und befindet sich in der Form:

DDV_Custom(pDX, field, ...);

Mehrere DDX_/DDV_ Paar können in jeder DoDataExchange Funktion enthalten sein.

Eine Liste aller Dialogdatenaustauschroutinen und Dialogdatenüberprüfungsroutinen, die mit MFC bereitgestellt werden, finden Sie unter "afxdd_.h".

Dialogdaten sind nur das: Memberdaten in der CMyDialog Klasse. Sie wird nicht in einer Struktur oder in einer ähnlichen Struktur gespeichert.

Hinweise

Obwohl wir diese "Dialogdaten" nennen, sind alle Features in allen von ihnen abgeleiteten CWnd Klassen verfügbar und sind nicht nur auf Dialogfelder beschränkt.

Anfangswerte von Daten werden im C++-Standardkonstruktor festgelegt, in der Regel in einem Block mit //{{AFX_DATA_INIT und //}}AFX_DATA_INIT Kommentaren.

CWnd::UpdateData ist der Vorgang, der die Initialisierung und Fehlerbehandlung rund um den Aufruf DoDataExchangeausführt.

Sie können jederzeit anrufen CWnd::UpdateData , um den Datenaustausch und die Validierung durchzuführen. Standardmäßig UpdateDatawird (TRUE) im Standardhandler CDialog::OnOK aufgerufen, und UpdateData(FALSE) wird in der Standardeinstellung CDialog::OnInitDialogaufgerufen.

Die DDV_ Routine sollte sofort der DDX_ Routine für dieses Feld folgen.

Funktionsweise

Sie müssen folgendes nicht verstehen, um Dialogdaten zu verwenden. Wenn Sie jedoch wissen, wie dies im Hintergrund funktioniert, können Sie Ihr eigenes Austausch- oder Validierungsverfahren schreiben.

Die DoDataExchange Memberfunktion ähnelt der Serialize Memberfunktion - sie ist für das Abrufen oder Festlegen von Daten auf/aus einem externen Formular (in diesem Fall Steuerelemente in einem Dialogfeld) von/zu Memberdaten in der Klasse verantwortlich. Der pDX-Parameter ist der Kontext für den Datenaustausch und ähnelt dem CArchive Parameter CObject::Serialize. Das pDX-Element (ein CDataExchange Objekt) weist eine Richtungskennzeichnung auf, ähnlich wie CArchive eine Richtungskennzeichnung:

  • Wenn !m_bSaveAndValidate, laden Sie den Datenstatus in die Steuerelemente.

  • Wenn m_bSaveAndValidate, legen Sie den Datenstatus aus den Steuerelementen fest.

Die Überprüfung erfolgt nur, wenn m_bSaveAndValidate sie festgelegt ist. Der Wert von m_bSaveAndValidate wird durch den BOOL-Parameter bestimmt zu CWnd::UpdateData.

Es gibt drei weitere interessante CDataExchange Mitglieder:

  • m_pDlgWnd: Das Fenster (in der Regel ein Dialogfeld), das die Steuerelemente enthält. Dadurch soll verhindert werden, dass Aufrufer der DDX_ und DDV_ globalen Funktionen "this" an jede DDX/DDV-Routine übergeben müssen.

  • PrepareCtrlund PrepareEditCtrl: Bereitet ein Dialogfeldsteuerelement für den Datenaustausch vor. Speichert das Handle dieses Steuerelements zum Festlegen des Fokus, wenn eine Überprüfung fehlschlägt. PrepareCtrl wird für Nichtbearbeitungssteuerelemente verwendet und PrepareEditCtrl wird für Bearbeitungssteuerelemente verwendet.

  • Fail: Wird aufgerufen, nachdem ein Meldungsfeld angezeigt wurde, in dem der Benutzer auf den Eingabefehler hingewiesen wird. Mit dieser Routine wird der Fokus auf das letzte Steuerelement (der letzte Aufruf PrepareCtrl oder PrepareEditCtrl) wiederhergestellt und eine Ausnahme ausgelöst. Diese Memberfunktion kann sowohl von DDX_ als auch von DDV_ Routinen aufgerufen werden.

Benutzererweiterungen

Es gibt mehrere Möglichkeiten, den DDX/DDV-Standardmechanismus zu erweitern. Sie können Folgendes ausführen:

  • Fügen Sie neue Datentypen hinzu.

    CTime
    
  • Hinzufügen neuer Exchange-Verfahren (DDX_).

    void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
    
  • Hinzufügen neuer Überprüfungsverfahren (DDV_).

    void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
    // make sure time is in the future or past
    
  • Übergeben Sie beliebige Ausdrücke an die Überprüfungsprozeduren.

    DDV_MinMax(pDX, age, 0, m_maxAge);
    

    Hinweis

    Solche willkürlichen Ausdrücke können nicht von ClassWizard bearbeitet werden und sollten daher außerhalb der speziellen Formatkommentare (//{{AFX_DATA_MAP(CMyClass)) verschoben werden.

Weisen Sie die DoDataExchange Memberfunktion bedingungsbedingte Oder andere gültige C++-Anweisungen mit intermixierten Austausch- und Überprüfungsfunktionsaufrufen auf.

//{{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);

Hinweis

Wie oben gezeigt, kann dieser Code nicht von ClassWizard bearbeitet werden und sollte nur außerhalb der Speziellen Formatkommentare verwendet werden.

ClassWizard-Unterstützung

ClassWizard unterstützt eine Teilmenge von DDX/DDV-Anpassungen, indem Sie Ihre eigenen DDX_ und DDV_ Routinen in die ClassWizard-Benutzeroberfläche integrieren können. Dies ist nur kostengünstig, wenn Sie beabsichtigen, bestimmte DDX- und DDV-Routinen in einem Projekt oder in vielen Projekten wiederzuverwenden.

Dazu werden spezielle Einträge in DDX.CLW (frühere Versionen von Visual C++ gespeichert diese Informationen in APSTUDIO gespeichert. INI) oder im Projekt . CLW-Datei. Die speziellen Einträge können entweder im Abschnitt [Allgemeine Informationen] des Projekts eingegeben werden. CLW-Datei oder im Abschnitt [ExtraDDX] der Datei "DDX.CLW" im Verzeichnis "\Programme\Microsoft Visual Studio\Visual C++\bin". Möglicherweise müssen Sie die Datei DDX.CLW erstellen, wenn sie noch nicht vorhanden ist. Wenn Sie beabsichtigen, die benutzerdefinierten DDX_/DDV_ Routinen nur in einem bestimmten Projekt zu verwenden, fügen Sie die Einträge zum Abschnitt [Allgemeine Informationen] Ihres Projekts hinzu. STATTDESSEN CLW-Datei. Wenn Sie die Routinen für viele Projekte verwenden möchten, fügen Sie die Einträge zum Abschnitt [ExtraDDX] von DDX.CLW hinzu.

Das allgemeine Format dieser speziellen Einträge lautet:

ExtraDDXCount=n

Wo n ist die Anzahl der folgenden ExtraDDX-Zeilen des Formulars

ExtraDDX?=Schlüssel; vb-keys; eingabeaufforderung; typ;initValue; DDX_Proc [; DDV_Proc; prompt1; arg1 [; prompt2; fmt2]]

Wo? ist eine Zahl 1 - n , die angibt, welcher DDX-Typ in der Liste definiert wird.

Jedes Feld wird durch ein ";"-Zeichen getrennt. Die Felder und deren Zweck werden unten beschrieben.

  • keys

    Eine Liste mit einzelnen Zeichen, die angeben, für welche Dialogfeldsteuerelemente dieser Variablentyp zulässig ist.

    Zeichen Zulässiges Steuerelement
    E edit
    C Kontrollkästchen mit zwei Status
    c Kontrollkästchen "Tri-State"
    R Erstes Optionsfeld in einer Gruppe
    L nicht sortiertes Listenfeld
    l Sortiertes Listenfeld
    M Kombinationsfeld (mit Bearbeitungselement)
    N Nicht sortierte Dropdownliste
    n Sortierte Dropdownliste
    1 wenn das DDX-Einfügen dem Listenkopf hinzugefügt werden soll (Standard wird dem Tail hinzugefügt) Wird dies in der Regel für DDX-Routinen verwendet, die die Eigenschaft "Control" übertragen.
  • vb-keys

    Dieses Feld wird nur im 16-Bit-Produkt für VBX-Steuerelemente verwendet (VBX-Steuerelemente werden im 32-Bit-Produkt nicht unterstützt)

  • prompt

    Zeichenfolge, die im Kombinationsfeld "Eigenschaft" platziert werden soll (keine Anführungszeichen)

  • type

    Einzelner Bezeichner für den Typ, der in der Headerdatei ausgegeben werden soll. In unserem obigen Beispiel mit DDX_Time wäre dies auf "CTime" festgelegt.

  • vb-keys

    In dieser Version nicht verwendet und sollte immer leer sein

  • initValue

    Anfangswert - 0 oder leer. Wenn sie leer ist, wird keine Initialisierungszeile im Abschnitt "//{{AFX_DATA_INIT" der Implementierungsdatei geschrieben. Ein leerer Eintrag sollte für C++-Objekte (z CString. B. , CTimeusw.) verwendet werden, die über Konstruktoren verfügen, die eine korrekte Initialisierung garantieren.

  • DDX_Proc

    Einzelner Bezeichner für die DDX_-Prozedur. Der C++-Funktionsname muss mit "DDX_" beginnen, aber nicht "DDX_" in den <DDX_Proc> Bezeichner einschließen. Im obigen Beispiel wäre die <DDX_Proc-ID> "Time". Wenn ClassWizard den Funktionsaufruf in die Implementierungsdatei im Abschnitt "{AFX_DATA_MAP" schreibt, fügt sie diesen Namen an DDX_ an und gelangt somit zu DDX_Time.

  • Kommentar

    Kommentar, der im Dialogfeld für Variable mit diesem DDX angezeigt werden soll. Platzieren Sie hier beliebigen Text, und geben Sie in der Regel etwas an, das den vorgang beschreibt, der vom DDX/DDV-Paar ausgeführt wird.

  • DDV_Proc

    Der DDV-Teil des Eintrags ist optional. Nicht alle DDX-Routinen verfügen über entsprechende DDV-Routinen. Häufig ist es praktischer, die Validierungsphase als integraler Bestandteil der Übertragung einzuschließen. Dies ist häufig der Fall, wenn Ihre DDV-Routine keine Parameter erfordert, da ClassWizard keine DDV-Routinen ohne Parameter unterstützt.

  • arg

    Einzelner Bezeichner für die DDV_-Prozedur. Der C++-Funktionsname muss mit "DDV_" beginnen, aber nicht "DDX_" in den <DDX_Proc> Bezeichner einschließen.

    arg folgt 1 oder 2 DDV Args:

    • promptN

      Zeichenfolge, die oberhalb des Bearbeitungselements platziert werden soll (mit & für Zugriffstaste).

    • fmtN

      Formatzeichen für den Argetyp, einer von:

      Zeichen Typ
      d INT
      n unsigned int
      D long int (das heißt, lang)
      U long unsigned (dword)
      f float
      F double
      s Zeichenfolge

Siehe auch

Technische Hinweise – nach Nummern geordnet
Technische Hinweise – nach Kategorien geordnet