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 DoDataExchange
ausführt.
Sie können jederzeit anrufen CWnd::UpdateData
, um den Datenaustausch und die Validierung durchzuführen. Standardmäßig UpdateData
wird (TRUE) im Standardhandler CDialog::OnOK
aufgerufen, und UpdateData
(FALSE) wird in der Standardeinstellung CDialog::OnInitDialog
aufgerufen.
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.PrepareCtrl
undPrepareEditCtrl
: 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 undPrepareEditCtrl
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 AufrufPrepareCtrl
oderPrepareEditCtrl
) 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. ,CTime
usw.) 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