Compartir a través de


Controles ActiveX MFC: Temas avanzados

En este artículo se tratan temas avanzados relacionados con el desarrollo de controles ActiveX. Entre ellas se incluyen las siguientes:

Importante

ActiveX es una tecnología heredada que no se debe usar para el nuevo desarrollo. Para más información sobre las tecnologías modernas que reemplazan a ActiveX, vea Controles ActiveX.

Uso de clases de base de datos en controles ActiveX

Dado que las clases de control ActiveX forman parte de la biblioteca de clases, puede aplicar los mismos procedimientos y reglas para usar clases de base de datos en una aplicación MFC estándar para desarrollar controles ActiveX que usan las clases de base de datos MFC.

Para información general sobre las clases de base de datos de MFC, consulte Clases de base de datos de MFC (DAO y ODBC). En el artículo se presentan las clases ODBC de MFC y las clases DAO de MFC y se le dirige a más detalles sobre cualquiera de las dos.

Nota:

DAO se admite mediante Office 2013. DAO 3.6 es la versión final y se considera obsoleta. El entorno y los asistentes de Visual C++ no admiten DAO (aunque se incluyen las clases DAO y todavía se pueden usar). Microsoft recomienda usar plantillas OLE DB o bien ODBC y MFC para proyectos nuevos. Solo debe usar DAO para mantener las aplicaciones existentes.

Implementación de una propiedad parametrizada

Una propiedad parametrizada (a veces denominada matriz de propiedades) es un método para exponer una colección homogénea de valores como una sola propiedad del control. Por ejemplo, puede usar una propiedad parametrizada para exponer una matriz o un diccionario como una propiedad. En Visual Basic, se obtiene acceso a esta propiedad mediante notación de matriz:

x = o.Array(2, 3) ' gets element of 2D array
o.Array(2, 3) = 7 ' sets element of 2D array

Use el Asistente para agregar propiedades para implementar una propiedad parametrizada. El Asistente para agregar propiedades implementa la propiedad agregando un par de funciones Get/Set que permiten al usuario de control tener acceso a la propiedad mediante la notación anterior o de forma estándar.

De forma similar a los métodos y las propiedades, las propiedades parametrizadas también tienen un límite en cuanto al número de parámetros permitidos. En el caso de las propiedades parametrizadas, el límite es de 15 parámetros (con un parámetro reservado para almacenar el valor de propiedad).

El procedimiento siguiente agrega una propiedad parametrizada, denominada Array, a la que se puede tener acceso como una matriz bidimensional de enteros.

Para agregar una propiedad parametrizada mediante el Asistente para agregar propiedades, siga estos pasos:

  1. Cargue el proyecto del control.

  2. En la vista de clases, expanda el nodo de biblioteca del control.

  3. Haga clic con el botón derecho en el nodo de interfaz del control (el segundo nodo del nodo de biblioteca) para abrir el menú contextual.

  4. En el menú contextual, haga clic en Agregar y después en Agregar propiedad.

  5. En el cuadro Nombre de propiedad, escriba Array.

  6. En el cuadro Tipo de propiedad, seleccione short.

  7. En Tipo de implementación, haga clic en Métodos Get/Set.

  8. En los cuadros Función Get y Función Set, escriba nombres únicos para las funciones Get y Set o acepte los nombres predeterminados.

  9. Agregue un parámetro denominado row (tipo short), mediante los controles Nombre de parámetro y Tipo de parámetro.

  10. Agregue un segundo parámetro denominado column (tipo short).

  11. Haga clic en Finalizar

Cambios realizados por el Asistente para agregar propiedades

Al agregar una propiedad personalizada, el Asistente para agregar propiedades realiza cambios en los archivos de encabezado (.H) e implementación (.CPP) de la clase de control.

Las líneas siguientes se agregan al archivo .H de clase de control:

SHORT GetArray(SHORT row, SHORT column);
void SetArray(SHORT row, SHORT column, SHORT newVal);

Este código declara dos funciones llamadas GetArray y SetArray que permiten al usuario solicitar una fila y una columna específicas al acceder a la propiedad.

Además, el Asistente para agregar propiedades agrega las líneas siguientes al mapa de distribución de controles, ubicado en el archivo de implementación de la clase de control (.CPP):

DISP_PROPERTY_PARAM_ID(CMyAxUICtrl, "Array", dispidArray, GetArray, SetArray, VT_I2, VTS_I2 VTS_I2)

Por último, las implementaciones de las funciones GetArray y SetArray se agregan al final del archivo .CPP. En la mayoría de los casos, modificará la función Get para devolver el valor de la propiedad. La función Set normalmente contendrá código que se debe ejecutar, ya sea antes o después de que la propiedad cambie.

Para que esta propiedad sea útil, puede declarar una variable miembro de matriz bidimensional en la clase de control, de tipo short, para almacenar valores para la propiedad parametrizada. Después, podría modificar la función Get para devolver el valor almacenado en la fila y la columna adecuadas, como se indica en los parámetros, y modificar la función Set para actualizar el valor al que hacen referencia los parámetros de fila y columna.

Control de errores en el control ActiveX

Si se producen condiciones de error en el control, es posible que tenga que notificar el error al contenedor de controles. Hay dos métodos para notificar errores, dependiendo de la situación en la que se produzca el error. Si el error se produce dentro de la función Get o Set de una propiedad, o dentro de la implementación de un método de automatización OLE, el control debe llamar a COleControl::ThrowError, que indica al usuario del control que se ha producido un error. Si el error se produce en cualquier otro momento, el control debe llamar a COleControl::FireError, que desencadena un evento de error de existencias.

Para indicar el tipo de error que se ha producido, el control debe pasar un código de error a ThrowError o FireError. Un código de error es un código de estado OLE, que tiene un valor de 32 bits. Cuando sea posible, elija un código de error del conjunto estándar de códigos definidos en el archivo de encabezado OLECTL.H. Estos códigos se resumen en la tabla siguiente.

Códigos de error de los controles ActiveX

Error Descripción
CTL_E_ILLEGALFUNCTIONCALL Llamada de función no válida
CTL_E_OVERFLOW Desbordamiento
CTL_E_OUTOFMEMORY No hay memoria suficiente
CTL_E_DIVISIONBYZERO División por cero
CTL_E_OUTOFSTRINGSPACE Espacio de cadena insuficiente
CTL_E_OUTOFSTACKSPACE Espacio de pila insuficiente
CTL_E_BADFILENAMEORNUMBER Número o nombre de archivo incorrecto
CTL_E_FILENOTFOUND Archivo no encontrado
CTL_E_BADFILEMODE Modo de archivo incorrecto
CTL_E_FILEALREADYOPEN Archivo ya abierto
CTL_E_DEVICEIOERROR Error de E/S del dispositivo
CTL_E_FILEALREADYEXISTS El archivo ya existe
CTL_E_BADRECORDLENGTH Longitud de registro incorrecta
CTL_E_DISKFULL Disco lleno
CTL_E_BADRECORDNUMBER Número de registro incorrecto
CTL_E_BADFILENAME Modo de archivo incorrecto
CTL_E_TOOMANYFILES Demasiados archivos
CTL_E_DEVICEUNAVAILABLE Dispositivo no disponible
CTL_E_PERMISSIONDENIED Permiso denegado
CTL_E_DISKNOTREADY Disco no preparado
CTL_E_PATHFILEACCESSERROR Error de acceso a la ruta o al archivo
CTL_E_PATHNOTFOUND No se encuentra la ruta de acceso
CTL_E_INVALIDPATTERNSTRING Cadena de patrón no válida
CTL_E_INVALIDUSEOFNULL Uso no válido de NULL
CTL_E_INVALIDFILEFORMAT Formato de archivo no válido
CTL_E_INVALIDPROPERTYVALUE Valor de propiedad no válido
CTL_E_INVALIDPROPERTYARRAYINDEX Índice de matriz de propiedades no válido
CTL_E_SETNOTSUPPORTEDATRUNTIME No se admite Set en tiempo de ejecución
CTL_E_SETNOTSUPPORTED No se admite Set (propiedad de solo lectura).
CTL_E_NEEDPROPERTYARRAYINDEX Se necesita un índice de matriz de propiedades
CTL_E_SETNOTPERMITTED No se permite establecer
CTL_E_GETNOTSUPPORTEDATRUNTIME No se admite Get en tiempo de ejecución
CTL_E_GETNOTSUPPORTED No se admite Get (propiedad de solo escritura)
CTL_E_PROPERTYNOTFOUND Propiedad no encontrada
CTL_E_INVALIDCLIPBOARDFORMAT Formato de Portapapeles no válido
CTL_E_INVALIDPICTURE Imagen no válida
CTL_E_PRINTERERROR Error en la impresora
CTL_E_CANTSAVEFILETOTEMP No se puede guardar el archivo en TEMP
CTL_E_SEARCHTEXTNOTFOUND No se encuentra el texto de la búsqueda
CTL_E_REPLACEMENTSTOOLONG Los reemplazos son demasiado largos

Si es necesario, use la macro CUSTOM_CTL_SCODE para definir un código de error personalizado para una condición que no esté cubierta por uno de los códigos estándar. El parámetro de esta macro debe ser un entero entre 1000 y 32767, ambos incluidos. Por ejemplo:

#define MYCTL_E_SPECIALERROR CUSTOM_CTL_SCODE(1000)

Si va a crear un control ActiveX para reemplazar un control VBX existente, defina los códigos de error del control ActiveX con los mismos valores numéricos que usa el control VBX para asegurarse de que los códigos de error son compatibles.

Control de teclas especiales en el control

En algunos casos, es posible que quiera controlar ciertas combinaciones de pulsaciones de teclas de una manera especial; por ejemplo, insertar una nueva línea cuando se presione la tecla ENTRAR en un control de cuadro de texto de varias líneas o moverse entre un grupo de controles de edición cuando se presione un identificador de tecla direccional.

Si la clase base del control ActiveX es COleControl, puede invalidar CWnd::P reTranslateMessage para controlar los mensajes antes de que el contenedor los procese. Al usar esta técnica, siempre se devuelve TRUE si el mensaje se controla en la invalidación de PreTranslateMessage.

En el ejemplo de código siguiente se muestra una manera posible de controlar los mensajes relacionados con las teclas direccionales.

BOOL CMyAxUICtrl::PreTranslateMessage(MSG* pMsg)
{
   BOOL bHandleNow = FALSE;

   switch (pMsg->message)
   {
   case WM_KEYDOWN:
      switch (pMsg->wParam)
      {
      case VK_UP:
      case VK_DOWN:
      case VK_LEFT:
      case VK_RIGHT:
         bHandleNow = TRUE;
         break;
      }
      if (bHandleNow)
      {
         OnKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
      }
      break;
   }
   return bHandleNow;
}

Para más información sobre cómo controlar las interfaces de teclado para un control ActiveX, consulte la documentación del SDK de ActiveX.

Acceso a controles de cuadro de diálogo que son invisibles en tiempo de ejecución

Puede crear controles de cuadro de diálogo que no tengan ninguna interfaz de usuario y que sean invisibles en tiempo de ejecución. Si agrega un control ActiveX invisible en tiempo de ejecución a un cuadro de diálogo y usa CWnd::GetDlgItem para acceder al control, el control no funcionará correctamente. En su lugar, debe usar una de las técnicas siguientes para obtener un objeto que represente el control:

  • Con el Asistente para agregar variables miembro, seleccione Variable de control y, luego, elija el identificador del control. Escriba un nombre de variable miembro y seleccione la clase contenedora del control en Tipo de control.

    o bien

  • Declare una variable local y una subclase como elemento de cuadro de diálogo. Inserte código similar al siguiente (CMyCtrl es la clase contenedora, IDC_MYCTRL1 es el identificador del control):

    CCirc myCirc;
    myCirc.SubclassDlgItem(IDC_CIRCCTRL2, this);
    // ... use myCirc ...
    myCirc.UnsubclassWindow();
    

Consulte también

Controles ActiveX de MFC