Compartir a través de


TN026: rutinas DDX y DDV

Nota:

La nota técnica siguiente no se ha actualizado desde que se incluyó por primera vez en la documentación en línea. Como resultado, algunos procedimientos y temas podrían estar obsoletos o incorrectos. Para obtener la información más reciente, se recomienda buscar el tema de interés en el índice de documentación en línea.

En esta nota se describe la arquitectura de intercambio de datos de diálogo (DDX) y validación de datos de diálogo (DDV). También describe cómo escribir un procedimiento DDX_ o DDV_ y cómo puede ampliar ClassWizard para usar las rutinas.

Información general sobre el intercambio de datos de cuadro de diálogo

Todas las funciones de datos de diálogo se realizan con código de C++. No hay recursos especiales ni macros mágicas. El centro del mecanismo es una función virtual que se invalida en cada clase de cuadro de diálogo que realiza el intercambio de datos de cuadro de diálogo y la validación. Siempre se encuentra en este 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
}

Los comentarios de AFX de formato especial permiten que ClassWizard busque y edite el código dentro de esta función. El código que no es compatible con ClassWizard debe colocarse fuera de los comentarios de formato especial.

En el ejemplo anterior, <data_exchange_function_call> tiene el formato :

DDX_Custom(pDX, nIDC, field);

y <data_validation_function_call> es opcional y tiene el formato :

DDV_Custom(pDX, field, ...);

Puede incluirse más de un par DDX_/DDV_ en cada DoDataExchange función.

Consulte "afxdd_.h" para obtener una lista de todas las rutinas de intercambio de datos de diálogo y rutinas de validación de datos de diálogo proporcionadas con MFC.

Los datos del cuadro de diálogo son solo eso: datos de miembro de la CMyDialog clase . No se almacenan en una estructura ni en nada similar.

Notas

Aunque llamamos a estos "datos de diálogo", todas las características están disponibles en cualquier clase derivada de CWnd y no se limitan solo a diálogos.

Los valores iniciales de los datos se establecen en el constructor estándar de C++, normalmente en un bloque con //{{AFX_DATA_INIT comentarios y //}}AFX_DATA_INIT .

CWnd::UpdateData es la operación que realiza la inicialización y el control de errores en torno a la llamada a DoDataExchange.

Puede llamar a CWnd::UpdateData en cualquier momento para realizar el intercambio y la validación de datos. De manera predeterminada se llama a UpdateData(TRUE) en el controlador CDialog::OnOK predeterminado y a UpdateData(FALSE) en el valor predeterminado CDialog::OnInitDialog.

La rutina DDV_ debe seguir inmediatamente la rutina de DDX_ para ese campo.

Cómo funciona

No es necesario comprender lo siguiente para usar los datos del cuadro de diálogo. Sin embargo, comprender cómo funciona en segundo plano le ayudará a escribir su propio procedimiento de intercambio o validación.

La función miembro DoDataExchange es muy similar a la función miembro Serialize: se encarga de obtener o establecer datos en un formulario externo, o desde este (en este caso, los controles de un cuadro de diálogo) desde los datos de miembro de la clase o hacia estos. El parámetro pDX es el contexto para realizar el intercambio de datos y es similar al CArchive parámetro a CObject::Serialize. El pDX (un CDataExchange objeto) tiene una marca de dirección, al igual que CArchive tiene una marca de dirección.

  • Si es !m_bSaveAndValidate, cargue el estado de datos en los controles.

  • Si es m_bSaveAndValidate, establezca el estado de datos de los controles.

La validación solo se produce cuando m_bSaveAndValidate se establece. El valor de m_bSaveAndValidate viene determinado por el parámetro BOOL en CWnd::UpdateData.

Hay otros tres miembros interesantes CDataExchange :

  • m_pDlgWnd: ventana (normalmente un cuadro de diálogo) que contiene los controles. Este miembro sirve para evitar que los autores de llamadas del funciones globales DDX_ y DDV_ tengan que pasar "this" a todas las rutinas DDX/DDV.

  • PrepareCtrl, y PrepareEditCtrl: prepara un control de diálogo para el intercambio de datos. Almacena el identificador del control para establecer el foco si se produce un error en una validación. PrepareCtrl se usa para controles que no son de edición y PrepareEditCtrl se usa para los controles de edición.

  • Fail: Se llama cuando aparece un cuadro de mensaje que avise al usuario sobre el error de entrada. Esta rutina restaurará el foco en el último control (la última llamada a PrepareCtrl o PrepareEditCtrl) y producirá una excepción. Se puede llamar a esta función miembro desde las rutinas DDX_ y DDV_.

Extensiones de usuario

Hay varias maneras de ampliar el mecanismo predeterminado DDX/DDV. Ustedes pueden:

  • Agregue nuevos tipos de datos.

    CTime
    
  • Agregue nuevos procedimientos de intercambio (DDX_).

    void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
    
  • Agregue nuevos procedimientos de validación (DDV_).

    void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
    // make sure time is in the future or past
    
  • Pasar expresiones arbitrarias a los procedimientos de validación.

    DDV_MinMax(pDX, age, 0, m_maxAge);
    

    Nota:

    ClassWizard no puede editar estas expresiones arbitrarias y, por tanto, deben moverse fuera de los comentarios de formato especial (//{{{AFX_DATA_MAP(CMyClass)).

Hacer que la DoDataExchange función miembro incluya condicionales o cualquier otra instrucción válida de C++ con llamadas a funciones de intercambio y validación entremezcladas.

//{{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:

Como se muestra anteriormente, ClassWizard no puede editar este código y solo debe usarse fuera de los comentarios de formato especial.

Compatibilidad con ClassWizard

ClassWizard admite un subconjunto de personalizaciones de DDX/DDV al permitirle integrar sus propias rutinas de DDX_ y DDV_ en la interfaz de usuario classWizard. Esto solo resulta económicamente beneficioso si planea reutilizar rutinas de DDX y DDV concretas en un proyecto o en muchos proyectos.

Para ello, se realizan entradas especiales en DDX.CLW (las versiones anteriores de Visual C++ almacenaban esta información en APSTUDIO.INI) o en el archivo .CLW de tu proyecto. Las entradas especiales se pueden introducir ya sea en la sección [Información general] del archivo .CLW de tu proyecto o en la sección [ExtraDDX] del archivo DDX.CLW en el directorio \Program Files\Microsoft Visual Studio\Visual C++\bin. Es posible que tenga que crear el archivo DDX.CLW si aún no existe. Si planea usar las rutinas DDX_/DDV_ personalizadas solo en un proyecto determinado, agregue las entradas a la sección [Información general] de su archivo .CLW del proyecto en su lugar. Si tiene previsto usar las rutinas en muchos proyectos, agregue las entradas a la sección [ExtraDDX] de DDX.CLW.

El formato general de estas entradas especiales es:

ExtraDDXCount=n

donde n es el número de líneas ExtraDDX? que se van a seguir, del formato

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

¿Dónde? es un número 1-n que indica el tipo DDX que es de la lista que se está definiendo.

Cada campo está delimitado por un carácter ';'. Los campos y su finalidad se describen a continuación.

  • Llaves

    Lista de caracteres únicos que indican para qué controles de cuadros de diálogo se permite este tipo de variable.

    Carácter Control permitido
    E edición
    C Casilla de dos estados
    c Casilla de tres estados
    R Primer botón de radio de un grupo
    L cuadro de lista no ordenado
    l Cuadro de lista ordenado
    M Cuadro combinado (con editar elemento)
    N Lista desplegable no ordenada
    n Lista desplegable ordenada
    1 Si se debe agregar la inserción DDX al encabezado de la lista (el valor predeterminado se agrega al final) Esto se usa generalmente para las rutinas DDX que transfieren la propiedad 'Control'.
  • vb-keys

    Este campo solo se usa en el producto de 16 bits para los controles VBX (los controles VBX no se admiten en el producto de 32 bits).

  • solicitud

    Cadena que se va a colocar en el cuadro combinado Propiedad (sin comillas)

  • tipo

    Identificador único del tipo que se va a emitir en el archivo de encabezado. En nuestro ejemplo anterior con DDX_Time, esto se establecería en CTime.

  • vb-keys

    No se usa en esta versión y siempre debe estar vacío

  • initValue

    Valor inicial: 0 o en blanco. Si está en blanco, no se escribirá ninguna línea de inicialización en la sección //{{AFX_DATA_INIT del archivo de implementación. Se debe usar una entrada en blanco para los objetos de C++ (como CString, CTime, etc.) que tienen constructores que garantizan la inicialización correcta.

  • DDX_Proc

    Identificador único para el procedimiento de DDX_. El nombre de la función de C++ debe comenzar con "DDX_", pero no incluya "DDX_" en el <identificador de DDX_Proc> . En el ejemplo anterior, el <identificador de DDX_Proc> sería Hora. Cuando ClassWizard escribe la llamada de función al archivo de implementación en la sección {{AFX_DATA_MAP, agrega este nombre a DDX_, llegando así a DDX_Time.

  • comentario

    Comentario que se mostrará en el cuadro de diálogo para la variable con este DDX. Coloque cualquier texto que desee aquí y, por lo general, proporcione algo que describa la operación realizada por el par DDX/DDV.

  • DDV_Proc

    La parte DDV de la entrada es opcional. No todas las rutinas DDX tienen rutinas DDV correspondientes. A menudo, es más conveniente incluir la fase de validación como parte integral de la transferencia. Esto suele ocurrir cuando la rutina DDV no requiere ningún parámetro, ya que ClassWizard no admite rutinas DDV sin parámetros.

  • Arg

    Identificador único para el procedimiento DDV_. El nombre de la función de C++ debe comenzar con "DDV_", pero no incluya "DDX_" en el <identificador de DDX_Proc> .

    arg va seguido de 1 o 2 argumentos DDV:

    • promptN

      Cadena para colocar encima del elemento de edición (con el símbolo '&' para el acelerador).

    • fmtN

      Carácter de formato para el tipo arg, uno de los siguientes:

      Carácter Tipo
      d Int
      u int sin firma
      D long int (es decir, long)
      U long unsigned (es decir, DWORD)
      f flotante
      F doble
      s cuerda / cadena

Consulte también

Notas técnicas por número
Notas Técnicas por Categoría