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
yClickOut
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
En el Explorador de soluciones, abra Polygon.idl y agregue el código siguiente en
methods:
en la declaracióndispInterface_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
Vuelva a compilar el proyecto.
O bien
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
En el Explorador de soluciones, abra _IPolyCtlEvents_CP.h y agregue el código siguiente en la instrucción
public:
de la claseCProxy_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
En Vista de clases, haga clic en el botón derecho en la clase
CPolyCtl
y haga clic en Propiedades en el menú contextual.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.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
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