TN026 : routines DDX et DDV
Remarque
La note technique suivante n'a pas été mise à jour depuis son inclusion initiale dans la documentation en ligne. Par conséquent, certaines procédures et rubriques peuvent être obsolètes ou incorrectes. Pour obtenir les informations les plus récentes, il est recommandé de rechercher l'objet qui vous intéresse dans l'index de la documentation en ligne.
Cette note décrit l’architecture d’échange de données de dialogue (DDX) et de validation des données de dialogue (VDD). Il décrit également comment écrire une procédure DDX_ ou VDD_ et comment étendre ClassWizard pour utiliser vos routines.
Vue d’ensemble de l’échange de données de boîte de dialogue
Toutes les fonctions de données de boîte de dialogue sont effectuées avec du code C++. Il n’y a pas de ressources spéciales ni de macros magiques. Le cœur du mécanisme est une fonction virtuelle qui est substituée dans chaque classe de dialogue qui effectue l’échange et la validation de données de dialogue. Elle est toujours trouvée sous cette forme :
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
}
Le format spécial des commentaires AFX permet à ClassWizard de localiser et de modifier le code dans cette fonction. Le code qui n’est pas compatible avec ClassWizard doit être placé en dehors des commentaires de format spéciaux.
Dans l’exemple ci-dessus, <data_exchange_function_call> se présente sous la forme suivante :
DDX_Custom(pDX, nIDC, field);
et <data_validation_function_call> est facultatif et se présente sous la forme suivante :
DDV_Custom(pDX, field, ...);
Plusieurs paires DDX_/VDD_ peuvent être incluses dans chaque DoDataExchange
fonction.
Consultez « afxdd_.h » pour obtenir la liste de toutes les routines d’échange de données de dialogue et les routines de validation des données de dialogue fournies avec MFC.
Les données de boîte de dialogue sont simplement les suivantes : données membres dans la CMyDialog
classe. Il n’est pas stocké dans un struct ou quelque chose de similaire.
Notes
Bien que nous appelons cette « données de dialogue », toutes les fonctionnalités sont disponibles dans n’importe quelle classe dérivée CWnd
et ne sont pas limitées aux dialogues uniquement.
Les valeurs initiales des données sont définies dans le constructeur C++ standard, généralement dans un bloc avec //{{AFX_DATA_INIT
et //}}AFX_DATA_INIT
des commentaires.
CWnd::UpdateData
est l’opération qui effectue l’initialisation et la gestion des erreurs autour de l’appel à DoDataExchange
.
Vous pouvez appeler CWnd::UpdateData
à tout moment pour effectuer l’échange et la validation des données. Par défaut (TRUE) est appelé dans le gestionnaire par CDialog::OnOK
défaut UpdateData
et UpdateData
(FALSE) est appelé dans la valeur par défautCDialog::OnInitDialog
.
La routine VDD_ doit immédiatement suivre la routine de DDX_ pour ce champ.
Fonctionnement
Vous n’avez pas besoin de comprendre ce qui suit pour utiliser les données de boîte de dialogue. Toutefois, comprendre comment cela fonctionne en arrière-plan vous aidera à écrire votre propre procédure d’échange ou de validation.
La DoDataExchange
fonction membre est similaire à la Serialize
fonction membre : elle est chargée d’obtenir ou de définir des données vers/à partir d’un formulaire externe (dans ce cas, les contrôles d’une boîte de dialogue) de/vers les données membres de la classe. Le paramètre pDX est le contexte d’échange de données et est similaire au CArchive
paramètre .CObject::Serialize
Le pDX (un CDataExchange
objet) a un indicateur de direction semblable CArchive
à celui d’un indicateur de direction :
Si
!m_bSaveAndValidate
, chargez l’état des données dans les contrôles.Si
m_bSaveAndValidate
, définissez l’état des données à partir des contrôles.
La validation se produit uniquement quand m_bSaveAndValidate
elle est définie. La valeur de m_bSaveAndValidate
est déterminée par le paramètre BOOL sur CWnd::UpdateData
.
Il existe trois autres membres intéressants CDataExchange
:
m_pDlgWnd
: fenêtre (généralement une boîte de dialogue) qui contient les contrôles. Cela permet d’empêcher les appelants des fonctions globales DDX_ et VDD_ de devoir passer « ceci » à chaque routine DDX/VDD.PrepareCtrl
, etPrepareEditCtrl
: prépare un contrôle de dialogue pour l’échange de données. Stocke le handle de ce contrôle pour définir le focus en cas d’échec d’une validation.PrepareCtrl
est utilisé pour les contrôles non modifiés etPrepareEditCtrl
est utilisé pour les contrôles d’édition.Fail
: appelé après avoir affiché une boîte de message indiquant à l’utilisateur l’erreur d’entrée. Cette routine restaure le focus sur le dernier contrôle (le dernier appel versPrepareCtrl
ouPrepareEditCtrl
) et lève une exception. Cette fonction membre peut être appelée à partir des routines DDX_ et VDD_.
Extensions utilisateur
Il existe plusieurs façons d’étendre le mécanisme DDX/VDD par défaut. Vous pouvez :
Ajoutez de nouveaux types de données.
CTime
Ajouter de nouvelles procédures d’échange (DDX_).
void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
Ajouter de nouvelles procédures de validation (VDD_).
void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture); // make sure time is in the future or past
Passez des expressions arbitraires aux procédures de validation.
DDV_MinMax(pDX, age, 0, m_maxAge);
Remarque
Ces expressions arbitraires ne peuvent pas être modifiées par ClassWizard et doivent donc être déplacées en dehors des commentaires de format spécial (//{AFX_DATA_MAP(CMyClass)).
DoDataExchange
La fonction membre inclut des conditions ou d’autres instructions C++ valides avec des appels de fonction d’échange et de validation mélangés.
//{{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);
Remarque
Comme indiqué ci-dessus, ce code ne peut pas être modifié par ClassWizard et ne doit être utilisé qu’en dehors des commentaires de format spécial.
Prise en charge de ClassWizard
ClassWizard prend en charge un sous-ensemble de personnalisations DDX/VDD en vous permettant d’intégrer vos propres routines DDX_ et VDD_ dans l’interface utilisateur ClassWizard. Cela n’est avantageux que si vous envisagez de réutiliser des routines DDX et VDD particulières dans un projet ou dans de nombreux projets.
Pour ce faire, des entrées spéciales sont effectuées dans DDX.CLW (versions antérieures de Visual C++ stockées ces informations dans APSTUDIO. INI) ou dans le projet . Fichier CLW. Les entrées spéciales peuvent être entrées dans la section [Informations générales] de votre projet . Fichier CLW ou dans la section [ExtraDDDX] du fichier DDX.CLW dans le répertoire \Program Files\Microsoft Visual Studio\Visual C++\bin. Vous devrez peut-être créer le fichier DDX.CLW s’il n’existe pas déjà. Si vous envisagez d’utiliser les routines DDX_/VDD_ personnalisées uniquement dans un certain projet, ajoutez les entrées à la section [Informations générales] de votre projet. Fichier CLW à la place. Si vous envisagez d’utiliser les routines sur de nombreux projets, ajoutez les entrées à la section [ExtraDDDX] de DDX.CLW.
Le format général de ces entrées spéciales est le suivant :
ExtraDDDXCount=n
où n est le nombre de lignes ExtraDDX à suivre, du formulaire
ExtraDDDX ?=keys ; vb-keys ; invite ; type ; initValue ; DDX_Proc [ ; VDD_Proc ; prompt1 ; arg1 [ ; invite2 ; fmt2]]
Où? est un nombre 1 - n indiquant le type DDX dans la liste en cours de définition.
Chaque champ est délimité par un caractère « ; ». Les champs et leur objectif sont décrits ci-dessous.
keys
Liste de caractères uniques indiquant pour quelle boîte de dialogue contrôle ce type de variable est autorisée.
Caractère Contrôle autorisé E edit C boîte de case activée à deux états c zone de case activée tri-état R première case d’option dans un groupe L Zone de liste non triée l Zone de liste triée M zone de liste modifiable (avec élément d’édition) N Liste déroulante non triée n Liste déroulante triée 1 si l’insertion DDX doit être ajoutée à la tête de liste (la valeur par défaut est ajoutée à la fin) Elle est généralement utilisée pour les routines DDX qui transfèrent la propriété « Control ». vb-keys
Ce champ est utilisé uniquement dans le produit 16 bits pour les contrôles VBX (les contrôles VBX ne sont pas pris en charge dans le produit 32 bits)
prompt
Chaîne à placer dans la zone de liste déroulante Propriété (sans guillemets)
type
Identificateur unique pour le type à émettre dans le fichier d’en-tête. Dans notre exemple ci-dessus avec DDX_Time, cette valeur est définie sur CTime.
vb-keys
Non utilisé dans cette version et doit toujours être vide
initValue
Valeur initiale : 0 ou vide. S’il est vide, aucune ligne d’initialisation n’est écrite dans la section //{AFX_DATA_INIT du fichier d’implémentation. Une entrée vide doit être utilisée pour les objets C++ (tels que
CString
,CTime
etc.) qui ont des constructeurs qui garantissent une initialisation correcte.DDX_Proc
Identificateur unique de la procédure DDX_. Le nom de la fonction C++ doit commencer par « DDX_ », mais n’incluez pas « DDX_ » dans l’identificateur <DDX_Proc> . Dans l’exemple ci-dessus, l’identificateur <DDX_Proc> serait Time. Lorsque ClassWizard écrit l’appel de fonction dans le fichier d’implémentation dans la section {{AFX_DATA_MAP, il ajoute ce nom à DDX_, ce qui arrive à DDX_Time.
commentaire
Commentaire à afficher dans la boîte de dialogue pour la variable avec ce DDX. Placez le texte souhaité ici et fournissez généralement quelque chose qui décrit l’opération effectuée par la paire DDX/VDD.
VDD_Proc
La partie VDD de l’entrée est facultative. Toutes les routines DDX n’ont pas toutes des routines de VDD correspondantes. Souvent, il est plus pratique d’inclure la phase de validation dans le cadre du transfert. Cela est souvent le cas lorsque votre routine de VDD ne nécessite aucun paramètre, car ClassWizard ne prend pas en charge VDD routines sans aucun paramètre.
arg
Identificateur unique de la procédure VDD_. Le nom de la fonction C++ doit commencer par « VDD_ », mais n’incluez pas « DDX_ » dans l’identificateur <DDX_Proc>.
arg est suivi de 1 ou 2 VDD arguments :
promptN
Chaîne à placer au-dessus de l’élément de modification (avec & pour l’accélérateur).
fmtN
Caractère de format pour le type d’argument, l’un des suivants :
Caractère Type j int u nombre entier non signé D long int (c’est-à-dire long) U long non signé (autrement dit, DWORD) f virgule flottante F double s string