Compartir a través de


Agregar un evento (Tutorial de ATL, Parte 5)

En este paso, agregará un evento ClickIn y ClickOut al control ATL. Activará el evento ClickIn si el usuario hace clic en el polígono y se activa ClickOut si el usuario hace clic fuera. Las tareas para agregar un evento son las siguientes:

  • Adición de los métodos ClickIn y ClickOut

  • Generación de la biblioteca de tipos

  • Implementación de las interfaces de punto de conexión

Adición de los métodos ClickIn y ClickOut

Al crear el control ATL en el paso 2, ha seleccionado la casilla Puntos de conexión. Esto creó la interfaz _IPolyCtlEvents en el archivo Polygon.idl. Tenga en cuenta que el nombre de la interfaz comienza con un carácter de subrayado. Se trata de una convención para indicar que la interfaz es una interfaz interna. Por lo tanto, los programas que permiten examinar objetos COM pueden optar por no mostrar la interfaz al usuario. Tenga en cuenta también que al seleccionar Puntos de conexión se ha agregado la siguiente línea en el archivo Polygon.idl para indicar que _IPolyCtlEvents es la interfaz de origen predeterminada:

[default, source] dispinterface _IPolyCtlEvents;

El atributo de origen indica que el control es el origen de las notificaciones, por lo que llamará a esta interfaz en el contenedor.

Ahora agregue los métodos ClickIn y ClickOut a la interfaz _IPolyCtlEvents.

Para agregar los métodos ClickIn y ClickOut

  1. En el Explorador de soluciones, abra Polygon.idl y agregue el código siguiente en methods: en la declaración dispInterface_IPolyCtlEvents de la biblioteca PolygonLib:

    [id(1), helpstring("method ClickIn")] void ClickIn([in] LONG x,[in] LONG y);
    [id(2), helpstring("method ClickOut")] void ClickOut([in] LONG x,[in] LONG y);
    

Los métodos ClickIn y ClickOut toman las coordenadas x e y del punto en el que se hace clic como parámetros.

Generación de la biblioteca de tipos

Genere la biblioteca de tipos en este momento, ya que el proyecto lo usará para obtener la información que necesita para construir una interfaz de punto de conexión y una interfaz de contenedor de punto de conexión para el control.

Para generar la biblioteca de tipos

  1. Vuelva a compilar el proyecto.

    O bien

  2. Haga clic con el botón derecho en el archivo Polygon.idl en Explorador de soluciones y haga clic en Compilar en el menú contextual.

Esto creará el archivo Polygon.tlb, que es la biblioteca de tipos. El archivo Polygon.tlb no es visible desde Explorador de soluciones, ya que es un archivo binario y no se puede ver ni editar directamente.

Implementación de las interfaces de punto de conexión

Implemente una interfaz de punto de conexión y una interfaz de contenedor de punto de conexión para el control. En COM, los eventos se implementan a través del mecanismo de puntos de conexión. Para recibir eventos de un objeto COM, un contenedor establece una conexión de asesoramiento al punto de conexión que implementa el objeto COM. Dado que un objeto COM puede tener varios puntos de conexión, el objeto COM también implementa una interfaz de contenedor de punto de conexión. A través de esta interfaz, el contenedor puede determinar qué puntos de conexión se admiten.

La interfaz que implementa un punto de conexión se denomina IConnectionPoint y la interfaz que implementa un contenedor de puntos de conexión se denomina IConnectionPointContainer.

Para ayudar a implementar IConnectionPoint, usará el Asistente para implementar el punto de conexión. Este asistente genera la interfaz IConnectionPoint leyendo la biblioteca de tipos e implementando una función para cada evento que se puede desencadenar.

Para implementar los puntos de conexión

  1. En el Explorador de soluciones, abra _IPolyCtlEvents_CP.h y agregue el código siguiente en la instrucción public: de la clase CProxy_IPolyCtlEvents:

    VOID Fire_ClickIn(LONG x, LONG y)
    {
        T* pT = static_cast<T*>(this);
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[2];
        int nConnections = m_vec.GetSize();
    
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
        {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL)
            {
                pvars[1].vt = VT_I4;
                pvars[1].lVal = x;
                pvars[0].vt = VT_I4;
                pvars[0].lVal = y;
                DISPPARAMS disp = { pvars, NULL, 2, 0 };
                pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            }
        }
        delete[] pvars;
    
    }
    VOID Fire_ClickOut(LONG x, LONG y)
    {
        T* pT = static_cast<T*>(this);
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[2];
        int nConnections = m_vec.GetSize();
    
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
        {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL)
            {
                pvars[1].vt = VT_I4;
                pvars[1].lVal = x;
                pvars[0].vt = VT_I4;
                pvars[0].lVal = y;
                DISPPARAMS disp = { pvars, NULL, 2, 0 };
                pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            }
        }
        delete[] pvars;
    
    }
    

Verá que este archivo tiene una clase denominada CProxy_IPolyCtlEvents que deriva de IConnectionPointImpl. _IPolyCtlEvents_CP.h define ahora los dos métodos Fire_ClickIn y Fire_ClickOut, que toman los dos parámetros de coordenada. Se llama a estos métodos cuando se desea desencadenar un evento desde el control.

Al crear el control con la opción Puntos de conexión seleccionada, el archivo _IPolyCtlEvents_CP.h se generó automáticamente. También se ha agregado CProxy_PolyEvents y IConnectionPointContainerImpl a la lista de herencia múltiple del control y se IConnectionPointContainer expone automáticamente agregando las entradas adecuadas al mapa COM.

Ha terminado de implementar el código para admitir eventos. Ahora, agregue código para activar los eventos en el momento adecuado. Recuerde que va a activar un evento ClickIn o ClickOut cuando el usuario haga clic en el botón izquierdo del mouse en el control. Para averiguar cuándo el usuario hace clic en el botón, agregue un controlador para el mensaje WM_LBUTTONDOWN.

Para agregar un controlador para el mensaje de WM_LBUTTONDOWN

  1. En Vista de clases, haga clic en el botón derecho en la clase CPolyCtl y haga clic en Propiedades en el menú contextual.

  2. En la ventana Propiedades, haga clic en el icono Mensajes y, a continuación, haga clic en WM_LBUTTONDOWN de la lista de la izquierda.

  3. En la lista desplegable que aparece, haga clic en <Agregar> OnLButtonDown. La declaración del controlador OnLButtonDown se agregará a Polyprop.h y la implementación del controlador a Polyprop.cpp.

A continuación, modificará el controlador.

Para modificar el método OnLButtonDown

  1. Cambie el código que consta del método OnLButtonDown en PolyCtl.cpp (eliminando cualquier código colocado por el asistente) para que tenga el siguiente aspecto:

    LRESULT CPolyCtl::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, 
       BOOL& /*bHandled*/)
    {
       HRGN hRgn;
       WORD xPos = LOWORD(lParam);  // horizontal position of cursor
       WORD yPos = HIWORD(lParam);  // vertical position of cursor
    
       CalcPoints(m_rcPos);
    
       // Create a region from our list of points
       hRgn = CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING);
    
       // If the clicked point is in our polygon then fire the ClickIn
       //  event otherwise we fire the ClickOut event
       if (PtInRegion(hRgn, xPos, yPos))
          Fire_ClickIn(xPos, yPos);
       else
          Fire_ClickOut(xPos, yPos);
    
       // Delete the region that we created
       DeleteObject(hRgn);
       return 0;
    }
    

Este código usa los puntos calculados en la función OnDraw para crear una región que detecte los clics del mouse del usuario con la llamada a PtInRegion.

El parámetro uMsg es el identificador del mensaje de Windows que se está controlando. Esto le permite tener una función que controle un intervalo de mensajes. Los parámetros wParam y lParam son los valores estándar del mensaje que se controla. El parámetro bHandled permite especificar si la función controló el mensaje o no. De forma predeterminada, el valor se establece en TRUE para indicar que la función controló el mensaje, pero puede establecerlo en FALSE. Esto hará que ATL siga buscando otra función de controlador de mensajes a la que enviar el mensaje.

Compilar y probar el control

Ahora pruebe sus eventos. Compile el control e inicie el contenedor de pruebas de control ActiveX de nuevo. Esta vez, vea la ventana del registro de eventos. Para enrutar eventos a la ventana de salida, haga clic en Registro en el menú Opciones y seleccione Registrar en la ventana de salida. Inserte el control e intente hacer clic en la ventana. Tenga en cuenta que ClickIn se desencadena si hace clic dentro del polígono rellenado y ClickOut se desencadena al hacer clic fuera de él.

A continuación, agregará una página de propiedades.

Volver al paso 4 | Avanzar al paso 6

Consulte también

Tutorial