TN026: routine DDX e DDV

Nota

La seguente nota tecnica non è stata aggiornata da quando è stata inclusa per la prima volta nella documentazione online. Di conseguenza, alcune procedure e argomenti potrebbero essere non aggiornati o errati. Per le informazioni più recenti, è consigliabile cercare l'argomento di interesse nell'indice della documentazione online.

Questa nota descrive l'architettura DDX (Dialog Data Exchange) e DDV (Dialog Data Validation). Descrive anche come scrivere una routine DDX_ o DDV_ e come estendere ClassWizard per usare le routine.

Panoramica di Dialog Data Exchange

Tutte le funzioni di dati della finestra di dialogo vengono eseguite con il codice C++. Non ci sono risorse speciali o macro magiche. Il cuore del meccanismo è una funzione virtuale sottoposta a override in ogni classe del dialogo che esegue lo scambio di dati e la convalida dei dialoghi. Si trova sempre in questo formato:

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
}

Il formato speciale I commenti AFX consentono a ClassWizard di individuare e modificare il codice all'interno di questa funzione. Il codice non compatibile con ClassWizard deve essere inserito all'esterno dei commenti in formato speciale.

Nell'esempio precedente, <data_exchange_function_call> è nel formato :

DDX_Custom(pDX, nIDC, field);

e <data_validation_function_call> è facoltativo ed è nel formato:

DDV_Custom(pDX, field, ...);

In ogni DoDataExchange funzione possono essere incluse più coppie di DDX_/DDV_.

Vedere "afxdd_.h" per un elenco di tutte le routine di scambio dei dati della finestra di dialogo e le routine di convalida dei dati delle finestre di dialogo fornite con MFC.

I dati della finestra di dialogo sono solo i dati dei membri nella CMyDialog classe . Non è archiviato in uno struct o in un elemento simile.

Note

Anche se si chiama questo "dati di dialogo", tutte le funzionalità sono disponibili in qualsiasi classe derivata da CWnd e non sono limitate solo ai dialoghi.

I valori iniziali dei dati vengono impostati nel costruttore C++ standard, in genere in un blocco con //{{AFX_DATA_INIT commenti e //}}AFX_DATA_INIT .

CWnd::UpdateData è l'operazione che esegue l'inizializzazione e la gestione degli errori intorno alla chiamata a DoDataExchange.

È possibile chiamare CWnd::UpdateData in qualsiasi momento per eseguire lo scambio e la convalida dei dati. Per impostazione predefinita UpdateData(TRUE) viene chiamato nel gestore predefinito CDialog::OnOK e UpdateData(FAL edizione Standard) viene chiamato nel valore predefinito CDialog::OnInitDialog.

La routine DDV_ deve seguire immediatamente la routine DDX_ per tale campo.

Funzionamento

Non è necessario comprendere quanto segue per usare i dati delle finestre di dialogo. Tuttavia, capire come funziona dietro le quinte consente di scrivere la propria procedura di scambio o convalida.

La DoDataExchange funzione membro è molto simile alla Serialize funzione membro. È responsabile del recupero o dell'impostazione di dati da/verso una maschera esterna (in questo caso controlli in una finestra di dialogo) da/a dati membro nella classe . Il parametro pDX è il contesto per lo scambio di dati ed è simile al CArchive parametro a CObject::Serialize. PDX (oggetto CDataExchange ) ha un flag di direzione molto simile CArchive a quello di un flag di direzione:

  • Se !m_bSaveAndValidate, caricare lo stato dei dati nei controlli.

  • Se m_bSaveAndValidate, impostare lo stato dei dati dai controlli .

La convalida viene eseguita solo quando m_bSaveAndValidate è impostata. Il valore di m_bSaveAndValidate è determinato dal parametro BOOL in CWnd::UpdateData.

Ci sono altri tre membri interessanti CDataExchange :

  • m_pDlgWnd: finestra (in genere una finestra di dialogo) che contiene i controlli. Ciò impedisce ai chiamanti della DDX_ e DDV_ funzioni globali di passare "this" a ogni routine DDX/DDV.

  • PrepareCtrl, e PrepareEditCtrl: prepara un controllo finestra di dialogo per lo scambio di dati. Archivia l'handle del controllo per impostare lo stato attivo in caso di esito negativo di una convalida. PrepareCtrl viene utilizzato per i controlli non di modifica e PrepareEditCtrl viene utilizzato per i controlli di modifica.

  • Fail: Chiamato dopo l'attivazione di una finestra di messaggio che avvisa l'utente dell'errore di input. Questa routine ripristina lo stato attivo sull'ultimo controllo (l'ultima chiamata a PrepareCtrl o PrepareEditCtrl) e genera un'eccezione. Questa funzione membro può essere chiamata da routine DDX_ e DDV_.

Estensioni utente

Esistono diversi modi per estendere il meccanismo DDX/DDV predefinito. È possibile:

  • Aggiungere nuovi tipi di dati.

    CTime
    
  • Aggiungere nuove procedure di scambio (DDX_).

    void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
    
  • Aggiungere nuove procedure di convalida (DDV_).

    void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
    // make sure time is in the future or past
    
  • Passare espressioni arbitrarie alle procedure di convalida.

    DDV_MinMax(pDX, age, 0, m_maxAge);
    

    Nota

    Tali espressioni arbitrarie non possono essere modificate da ClassWizard e pertanto devono essere spostate all'esterno dei commenti in formato speciale (//{{AFX_DATA_MAP(CMyClass)).

DoDataExchange La funzione membro include le istruzioni condizionali o qualsiasi altra istruzione C++ valida con chiamate di funzione di convalida e scambio intermixed.

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

Nota

Come illustrato in precedenza, tale codice non può essere modificato da ClassWizard e deve essere usato solo all'esterno dei commenti in formato speciale.

Supporto classWizard

ClassWizard supporta un subset di personalizzazioni DDX/DDV consentendo di integrare le proprie routine DDX_ e DDV_ nell'interfaccia utente ClassWizard. Questa operazione è vantaggiosa solo se si prevede di riutilizzare routine DDX e DDV specifiche in un progetto o in molti progetti.

A tale scopo, le voci speciali vengono eseguite in DDX.CLW (versioni precedenti di Visual C++ archiviate in piattaforma di strumenti analitici TUDIO. INI) o nel progetto . File CLW. Le voci speciali possono essere immesse nella sezione [Informazioni generali] del progetto. File CLW o nella sezione [ExtraDDX] del file DDX.CLW nella directory \Programmi\Microsoft Visual Studio\Visual C++\bin. Potrebbe essere necessario creare il file DDX.CLW se non esiste già. Se si prevede di usare le routine di DDX_/DDV_ personalizzate solo in un determinato progetto, aggiungere le voci alla sezione [Informazioni generali] del progetto. File CLW. Se si prevede di usare le routine in molti progetti, aggiungere le voci alla sezione [ExtraDDX] di DDX.CLW.

Il formato generale di queste voci speciali è:

ExtraDDXCount=n

dove n è il numero di righe ExtraDDX da seguire, del modulo

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

Dove? è un numero 1 - n che indica il tipo DDX nell'elenco definito.

Ogni campo è delimitato da un carattere ';'. I campi e i relativi scopi sono descritti di seguito.

  • keys

    Elenco di caratteri singoli che indicano per quale finestra di dialogo controlla questo tipo di variabile.

    Carattere Controllo consentito
    E Modifica…
    A casella di controllo a due stati
    c casella di controllo tri-state
    R primo pulsante di opzione in un gruppo
    L casella di riepilogo non ordinato
    l casella di riepilogo ordinata
    M casella combinata (con modifica elemento)
    N elenco a discesa non ordinato
    n elenco a discesa ordinato
    1 se l'inserimento DDX deve essere aggiunto all'intestazione dell'elenco (l'impostazione predefinita è aggiunta alla coda) Viene in genere utilizzato per le routine DDX che trasferiscono la proprietà 'Control'.
  • vb-keys

    Questo campo viene usato solo nel prodotto a 16 bit per i controlli VBX (i controlli VBX non sono supportati nel prodotto a 32 bit)

  • prompt

    Stringa da inserire nella casella combinata Proprietà (senza virgolette)

  • type

    Identificatore singolo per il tipo da generare nel file di intestazione. Nell'esempio precedente con DDX_Time, questa opzione verrà impostata su CTime.

  • vb-keys

    Non usato in questa versione e deve essere sempre vuoto

  • initValue

    Valore iniziale: 0 o vuoto. Se è vuoto, non verrà scritta alcuna riga di inizializzazione nella sezione //{{AFX_DATA_INIT del file di implementazione. Per gli oggetti C++ (ad esempio CString, CTimee così via) deve essere usata una voce vuota con costruttori che garantiscono l'inizializzazione corretta.

  • DDX_Proc

    Identificatore singolo per la routine DDX_. Il nome della funzione C++ deve iniziare con "DDX_", ma non includere "DDX_" nell'identificatore <DDX_Proc> . Nell'esempio precedente, l'identificatore <DDX_Proc> sarà Time. Quando ClassWizard scrive la chiamata di funzione al file di implementazione nella sezione {{AFX_DATA_MAP, aggiunge questo nome a DDX_, arrivando così a DDX_Time.

  • comment

    Commento da visualizzare nella finestra di dialogo per la variabile con questo DDX. Inserire il testo desiderato qui e in genere specificare un elemento che descrive l'operazione eseguita dalla coppia DDX/DDV.

  • DDV_Proc

    La parte DDV della voce è facoltativa. Non tutte le routine DDX hanno routine DDV corrispondenti. Spesso, è più conveniente includere la fase di convalida come parte integrante del trasferimento. Questo è spesso il caso in cui la routine DDV non richiede parametri, perché ClassWizard non supporta routine DDV senza parametri.

  • arg

    Identificatore singolo per la routine DDV_. Il nome della funzione C++ deve iniziare con "DDV_", ma non includere "DDX_" nell'identificatore <DDX_Proc> .

    arg è seguito da 1 o 2 argomenti DDV:

    • promptN

      Stringa da posizionare sopra l'elemento di modifica (con e per acceleratore).

    • fmtN

      Formattare il carattere per il tipo arg, uno dei seguenti:

      Carattere Type
      d int
      u unsigned int
      D long int (ovvero long)
      U long unsigned (ovvero DWORD)
      f float
      F double
      s string

Vedi anche

Note tecniche per numero
Note tecniche per categoria