FAQ VC++ et MFCConsultez toutes les FAQ

Nombre d'auteurs : 20, nombre de questions : 546, dernière mise à jour : 5 avril 2013  Ajouter une question

 

Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++

Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.

Sur ce, je vous souhaite une bonne lecture. Farscape


SommaireContrôlesMécanisme d'échange des données (DoDataExchange) (1)
précédent sommaire suivant
 

Code c++ : Sélectionner tout
1
2
3
  
CWnd::UpdateData 
BOOL UpdateData( BOOL bSaveAndValidate = TRUE );
Cette fonction comme son nom l'indique permet :

  • La mise à jour des variables attachées aux contrôles lorsque bSaveAndValidate est égal à TRUE ;
  • La mise à jour des contrôles depuis les variables lorsque bSaveAndValidate est égal à FALSE.

Jusque là rien d'extraordinaire.
Il faut quand même savoir que ce mécanisme de mise à jour dans les deux sens est assujetti à une fonction essentielle dans la classe fenêtre où sont situés les contrôles :

Code c++ : Sélectionner tout
1
2
3
  
CWnd::DoDataExchange   
virtual void DoDataExchange( CDataExchange* pDX );
Cette fonction virtuelle sera générée automatiquement par ClassWizard lors de la génération d'une classe Fenêtre. Le code de conversion approprié sera placé automatiquement en fonction des types de variables que l'utilisateur aura sélectionnées. Les fichiers include et source étant bien sûr mis à jour automatiquement.
Exemple de DoDataExchange

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
void CBnqView::DoDataExchange(CDataExchange* pDX) 
{ 
    CMyFormView::DoDataExchange(pDX); 
    //{{AFX_DATA_MAP(CBnqView) 
    DDX_Control(pDX, IDC_CEDITCDEBNQ, m_EditCdeBnq); 
    DDX_Control(pDX, IDC_CEDITCDEGUICHET, m_EditCdeGuichet); 
    DDX_Control(pDX, IDC_CEDITDOM, m_EditDom); 
   //…………………………………………………. 
   //}}AFX_DATA_MAP 
}
Il existe d'autres formes d'échanges :contrôle vers entiers,string .
DoDataExchange sera appelée chaque fois que UpdateData sera invoquée,
L'échange des données se fera par la fonction DDX_xxxx qui établira le lien entre le numéro d'identité du contrôle (IDC_) et sa variable.
Dans le cas de la fonction DDX_Control d'autres mécanismes sont mis en jeu.

Code c++ : Sélectionner tout
1
2
3
4
  
// header afxdd_.h 
// for getting access to the actual controls 
void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl);
Au premier UpdateData le contrôle est « subclassé » ,c'est-à-dire qu'on va intercepter les messages Windows à destination du contrôle (tous les processus par défaut de Windows) pour lui donner un autre « moteur » de gestion des messages ,celui de l'objet mentionné dans la fonction DDX_Control .
Ce travail est fait par la fonction CWnd ::SubclassWindow(HWND hWnd) qui fait appel elle-même à

Code c++ : Sélectionner tout
1
2
3
4
5
  
LONG SetWindowLong(  
HWND hWnd,  
int nIndex,  
LONG dwNewLong);
C'est à la fin de ce traitement dont je viens de résumer les grandes lignes que la donnée membre m_hWnd de la variable contrôle sera affectée.
Autre point un UpdateData est fait à votre « insu » dans la fonction CDialog ::OnInitDialog

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
BOOL CDialog::OnInitDialog() 
{ 
    //-…………………………………………………………..Extrait 
    // transfer data into the dialog from member variables 
    if (!UpdateData(FALSE)) 
   { 
       TRACE0("Warning: UpdateData failed during dialog init.\n"); 
       EndDialog(-1); 
       return FALSE; 
   } 
   //-…………………………………………………………..Extrait 
}
Les conséquences de ce qui vient d'être dit sont nombreuses :

  • Toute variable contrôle déclarée dans une fenêtre dialogue (CDialog ou CFormView etc ..) qui ne fera pas partie de la fonction DoDataExchange ne sera pas « subclassée » son handle de fenêtre sera égal à NULL et son utilisation provoquera une assertion.
  • Toute variable contrôle non présente dans la fonction DoDataExchange ne sera pas affectée par l'action de UpdateData.
  • Pour subclasser un contrôle manuellement on pourra utiliser la fonction SubClassDlgItem :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
  
BOOL CAboutDlg::OnInitDialog()  
{ 
   CDialog::OnInitDialog(); 
   // IDC_BUTTON1 is the ID for a button on the  
   // dialog template used for CAboutDlg. 
   m_myButton.SubclassDlgItem(IDC_BUTTON1, this);    
//…………………………………
Pour placer dans la fonction DoDataExchange une variable dynamique utiliser la technique suivante :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  
void CBnqView::DoDataExchange(CDataExchange* pDX) 
{ 
    CMyFormView::DoDataExchange(pDX); 
    //{{AFX_DATA_MAP(CBnqView) 
    DDX_Control(pDX, IDC_CEDITCDEBNQ, m_EditCdeBnq); 
    // m_pEditDynamique mis à null dans le constructeur et initialiser dans OnInitialUpdate. 
    if(m_pEditDynamique) 
    { 
        DDX_Control(pDX, IDC_CEDITDYN, *m_pEditDynamique); 
    } 
    DDX_Control(pDX, IDC_CEDITCDEGUICHET, m_EditCdeGuichet); 
    DDX_Control(pDX, IDC_CEDITDOM, m_EditDom); 
   //…………………………………………………. 
   //}}AFX_DATA_MAP 
}
L'appel à la fonction DDX_Control se fera uniquement si le pointeur est différent de NULL.
Une cause de plantage classique :le contrôle est enlevé dans la ressource et on oublie de supprimer la variable par ClassWizard au premier UpdateData on aura une belle assertion d'erreur dans le source DLGDATA.CPP.
Pour clôturer la question, il existe dans la documentation MSDN une note d'information intéressante sur tous les problèmes d'assertions avec les macros DDX_ :

Code c++ : Sélectionner tout
1
2
3
  
INFO: Foundation Classes Common Asserts, Causes, and Solutions 
Q117326

Mis à jour le 5 avril 2013 farscape

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Contacter le responsable de la rubrique C++