Adicionando um evento (Tutorial ATL, parte 5)
Nesta etapa, você adicionará um evento ClickIn
e um ClickOut
ao controle da ATL. Você disparará o evento ClickIn
se o usuário clicar no polígono e disparará ClickOut
se o usuário clicar do lado de fora. As tarefas para adicionar um evento são as seguintes:
Adicionar os métodos
ClickIn
eClickOut
Gerar a biblioteca de tipos
Implementar as interfaces do ponto de conexão
Adicionar os métodos ClickIn e ClickOut
Quando você criou o controle ATL na etapa 2, selecionou a caixa de seleção Pontos de conexão. Isso criou a interface _IPolyCtlEvents
no arquivo Polygon.idl. Observe que o nome da interface começa com um sublinhado. Essa é uma convenção para indicar que a interface é uma interface interna. Assim, os programas que permitem navegar por objetos COM podem optar por não exibir a interface para o usuário. Observe também que selecionar Pontos de conexão adicionou a seguinte linha no arquivo Polygon.idl para indicar que _IPolyCtlEvents
é a interface de origem padrão:
[default, source] dispinterface _IPolyCtlEvents;
O atributo de origem indica que o controle é a origem das notificações, portanto, ele chamará essa interface no contêiner.
Agora, adicione os métodos ClickIn
e ClickOut
à interface _IPolyCtlEvents
.
Adicionar os métodos ClickIn e ClickOut
Em Gerenciador de Soluções, abra Polygon.idl e adicione o seguinte código em
methods:
na declaraçãodispInterface_IPolyCtlEvents
da 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);
Os métodos ClickIn
e ClickOut
tomam as coordenadas x e y do ponto clicado como parâmetros.
Gerar a biblioteca de tipos
Gere a biblioteca de tipos neste momento, pois o projeto a usará para obter as informações necessárias para construir uma interface de ponto de conexão e uma interface de contêiner do ponto de conexão para o controle.
Gerar a biblioteca de tipos
Recompile o projeto.
-ou-
Clique com o botão direito do mouse no arquivo Polygon.idl no Gerenciador de Soluções e clique em Compilar no menu de atalho.
Isso criará o arquivo Polygon.tlb, que é sua biblioteca de tipos. O arquivo Polygon.tlb não está visível no Gerenciador de Soluções, pois é um arquivo binário e não pode ser exibido ou editado diretamente.
Implementar as interfaces do ponto de conexão
Implemente uma interface de ponto de conexão e uma interface de contêiner do ponto de conexão para seu controle. No COM, os eventos são implementados por meio do mecanismo de pontos de conexão. Para receber eventos de um objeto COM, um contêiner estabelece uma conexão de consultoria com o ponto de conexão que o objeto COM implementa. Como um objeto COM pode ter vários pontos de conexão, o objeto COM também implementa uma interface de contêiner do ponto de conexão. Por meio dessa interface, o contêiner pode determinar quais pontos de conexão têm suporte.
A interface que implementa um ponto de conexão é chamada IConnectionPoint
, e a interface que implementa um contêiner de ponto de conexão é chamada IConnectionPointContainer
.
Para ajudar a implementar IConnectionPoint
, você usará o Assistente para Implementar Ponto de Conexão. Esse assistente gera a interface IConnectionPoint
lendo sua biblioteca de tipos e implementando uma função para cada evento que pode ser acionado.
Implementar os pontos de conexão
Em Gerenciador de Soluções, abra _IPolyCtlEvents_CP.h e adicione o seguinte código na instrução
public:
na classeCProxy_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; }
Você verá que esse arquivo tem uma classe chamada CProxy_IPolyCtlEvents
que deriva de IConnectionPointImpl
. _IPolyCtlEvents_CP.h agora define os dois métodos Fire_ClickIn
e Fire_ClickOut
, que tomam os dois parâmetros de coordenada. Você chama esses métodos quando deseja disparar um evento do seu controle.
Ao criar o controle com a opção Pontos de conexão selecionada, o arquivo _IPolyCtlEvents_CP.h foi gerado para você. Ele também adicionou CProxy_PolyEvents
e IConnectionPointContainerImpl
à lista de várias heranças do controle e expôs IConnectionPointContainer
para você adicionando entradas apropriadas ao mapa COM.
Você terminou de implementar o código para dar suporte a eventos. Agora, adicione algum código para disparar os eventos no momento apropriado. Lembre-se de que você vai disparar um evento ClickIn
ou ClickOut
quando o usuário clicar no botão esquerdo do mouse no controle. Para descobrir quando o usuário clica no botão, adicione um manipulador para a mensagem WM_LBUTTONDOWN
.
Adicionar um manipulador para a mensagem WM_LBUTTONDOWN
No Modo de Exibição de Classe, clique com o botão direito do mouse em
CPolyCtl
e clique em Propriedades no menu de atalho.Na janela Propriedades, clique no ícone Mensagens e clique em
WM_LBUTTONDOWN
na lista à esquerda.Na lista suspensa que é exibida, clique em <Adicionar> OnLButtonDown. A declaração do manipulador
OnLButtonDown
será adicionada ao PolyCtl.h e a implementação do manipulador ao PolyCtl.cpp.
Em seguida, modifique o manipulador.
Modificar o método OnLButtonDown
Altere o código que compreende o método
OnLButtonDown
em PolyCtl.cpp (excluindo qualquer código colocado pelo assistente) para que ele tenha esta aparência: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; }
Esse código usa os pontos calculados na função OnDraw
para criar uma região que detecta cliques do mouse do usuário com a chamada para PtInRegion
.
O parâmetro uMsg é a ID da mensagem do Windows que está sendo tratada. Isso permite que você tenha uma função que manipula um intervalo de mensagens. Os parâmetros wParam e lParam são os valores padrão para a mensagem que está sendo tratada. O parâmetro bHandled permite que você especifique se a função lidou com a mensagem ou não. Por padrão, o valor é definido como TRUE para indicar que a função lidou com a mensagem, mas você pode defini-la como FALSE. Isso fará com que a ATL continue procurando outra função de manipulador de mensagens para a qual enviar a mensagem.
Compilação e teste do controle
Agora experimente seus eventos. Crie o controle e inicie o Contêiner de Teste de Controle ActiveX novamente. Desta vez, exiba a janela do log de eventos. Para rotear eventos para a janela de saída, clique em Registrar em log no menu Opções e selecione Registrar na janela de saída. Insira o controle e tente clicar na janela. Observe que ClickIn
será acionado se você clicar no polígono preenchido e ClickOut
será acionado quando clicar fora dele.
Em seguida, você adicionará uma página de propriedades.
Voltar para a Etapa 4 | Na Etapa 6