Alteração do código de desenho (Tutorial ATL, parte 4)
Por padrão, o código de desenho do controle exibe um quadrado e o texto PolyCtl. Nesta etapa, você alterará o código para exibir algo mais interessante. As seguintes tarefas estão envolvidas:
Modificar o arquivo de cabeçalho
Modificar a função
OnDraw
Adicionar um método para calcular os pontos de polígono
Inicializar a cor de preenchimento
Modificar o arquivo de cabeçalho
Comece adicionando suporte para as funções matemáticas sin
e cos
(que serão usadas para calcular os pontos de polígono) e criando uma matriz para armazenar posições.
Para modificar o arquivo de cabeçalho
Adicione a linha
#include <math.h>
à parte superior do PolyCtl.h. A parte superior do arquivo deve ter esta aparência:#include <math.h> #include "resource.h" // main symbols
Implemente a interface
IProvideClassInfo
para fornecer informações de método para o controle, adicionando o código a seguir ao PolyCtl.h. Na classeCPolyCtl
, substitua a linha:public CComControl<CPolyCtl>
por
public CComControl<CPolyCtl>, public IProvideClassInfo2Impl<&CLSID_PolyCtl, &DIID__IPolyCtlEvents, &LIBID_PolygonLib>
e, em
BEGIN_COM_MAP(CPolyCtl)
, adicione as linhas:COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2)
Depois que os pontos de polígono forem calculados, eles serão armazenados em uma matriz de tipo
POINT
, portanto, adicione a matriz após a instrução de definiçãoshort m_nSides;
em PolyCtl.h:POINT m_arrPoint[100];
Modificando o método OnDraw
Agora você deve modificar o método OnDraw
em PolyCtl.h. O código que você adicionará cria uma nova caneta e um pincel para desenhar seu polígono e, em seguida, chama as funções de API Ellipse
e Polygon
do Win32 para executar o desenho real.
Para modificar a função OnDraw
Substitua o método
OnDraw
existente em PolyCtl.h pelo código a seguir:HRESULT CPolyCtl::OnDraw(ATL_DRAWINFO& di) { RECT& rc = *(RECT*)di.prcBounds; HDC hdc = di.hdcDraw; COLORREF colFore; HBRUSH hOldBrush, hBrush; HPEN hOldPen, hPen; // Translate m_colFore into a COLORREF type OleTranslateColor(m_clrFillColor, NULL, &colFore); // Create and select the colors to draw the circle hPen = (HPEN)GetStockObject(BLACK_PEN); hOldPen = (HPEN)SelectObject(hdc, hPen); hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); // Create and select the brush that will be used to fill the polygon hBrush = CreateSolidBrush(colFore); SelectObject(hdc, hBrush); CalcPoints(rc); Polygon(hdc, &m_arrPoint[0], m_nSides); // Select back the old pen and brush and delete the brush we created SelectObject(hdc, hOldPen); SelectObject(hdc, hOldBrush); DeleteObject(hBrush); return S_OK; }
Adicionar um método para calcular os pontos de polígono
Adicione um método, chamado CalcPoints
, que calculará as coordenadas dos pontos que compõem o perímetro do polígono. Esses cálculos serão baseados na variável RECT que é passada para a função.
Para adicionar o método CalcPoints
Adicione a declaração do
CalcPoints
para a seção públicaIPolyCtl
da classeCPolyCtl
em PolyCtl.h:void CalcPoints(const RECT& rc);
A última parte da seção pública da classe
CPolyCtl
terá esta aparência:void FinalRelease() { } public: void CalcPoints(const RECT& rc);
Adicione essa implementação da função
CalcPoints
ao final de PolyCtl.cpp:void CPolyCtl::CalcPoints(const RECT& rc) { const double pi = 3.14159265358979; POINT ptCenter; double dblRadiusx = (rc.right - rc.left) / 2; double dblRadiusy = (rc.bottom - rc.top) / 2; double dblAngle = 3 * pi / 2; // Start at the top double dblDiff = 2 * pi / m_nSides; // Angle each side will make ptCenter.x = (rc.left + rc.right) / 2; ptCenter.y = (rc.top + rc.bottom) / 2; // Calculate the points for each side for (int i = 0; i < m_nSides; i++) { m_arrPoint[i].x = (long)(dblRadiusx * cos(dblAngle) + ptCenter.x + 0.5); m_arrPoint[i].y = (long)(dblRadiusy * sin(dblAngle) + ptCenter.y + 0.5); dblAngle += dblDiff; } }
Inicializar a cor de preenchimento
Inicialize m_clrFillColor
com uma cor padrão.
Para inicializar a cor de preenchimento
Use verde como a cor padrão adicionando esta linha ao construtor
CPolyCtl
em PolyCtl.h:m_clrFillColor = RGB(0, 0xFF, 0);
O construtor agora tem esta aparência:
CPolyCtl()
{
m_nSides = 3;
m_clrFillColor = RGB(0, 0xFF, 0);
}
Compilação e teste do controle
Recompile o controle. Verifique se o arquivo PolyCtl.htm está fechado. Em seguida, clique em Compilar Polígono no menu Compilar. Você pode exibir o controle mais uma vez na página PolyCtl.htm, mas desta vez use o Contêiner de Teste de Controle ActiveX.
Para usar o Contêiner de Teste de Controle ActiveX
Compile e inicie o Contêiner de Teste de Controle ActiveX. O exemplo TSTCON: contêiner de teste de controle ActiveX pode ser encontrado no GitHub.
Observação
Para erros envolvendo
ATL::CW2AEX
, em Script.Cpp, substitua a linhaTRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT );
porTRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );
e a linhaTRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) );
porTRACE( "Source Text: %s\n", bstrSourceLineText );
.
Para erros envolvendoHMONITOR
, abra StdAfx.h no projetoTCProps
e substitua:#ifndef WINVER #define WINVER 0x0400 #endif
por
#ifndef WINVER #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #endif
No Contêiner de Teste, no menu Editar, clique em Inserir Novo Controle.
Localize o controle, que será chamado
PolyCtl class
, e clique em OK. Você verá um triângulo verde dentro de um círculo.
Tente alterar o número de lados seguindo o próximo procedimento. Para modificar propriedades em uma interface dupla de dentro do Contêiner de Teste, use os Métodos de Invocação.
Para modificar a propriedade de controle de dentro do Contêiner de Teste
No Contêiner de Teste, clique em Invocar Métodos no menu Controle.
A caixa de diálogo Invocar Método é exibida.
Selecione a versão PropPut da propriedade Sides na caixa de listagem suspensa Nome do Método.
Digite
5
na caixa Valor do Parâmetro, clique em Definir Valor e clique em Invocar.
Observe que o controle não é alterado. Embora você tenha alterado o número de lados internamente definindo a variável m_nSides
, isso não fez o controle se repintar. Se você alternar para outro aplicativo e voltar para o Contêiner de Teste, descobrirá que o controle foi repintado e tem o número correto de lados.
Para corrigir esse problema, adicione uma chamada à função FireViewChange
, definida em IViewObjectExImpl
, depois de definir o número de lados. Se o controle estiver em execução em sua própria janela, FireViewChange
chamará o método InvalidateRect
diretamente. Se o controle estiver executando sem janelas, o método InvalidateRect
será chamado na interface do site do contêiner. Isso força o controle a se repintar.
Para adicionar uma chamada ao FireViewChange
Atualize o PolyCtl.cpp adicionando a chamada
FireViewChange
ao métodoput_Sides
. Quando você terminar, o métodoput_Sides
deve ter esta aparência:STDMETHODIMP CPolyCtl::put_Sides(short newVal) { if (2 < newVal && newVal < 101) { m_nSides = newVal; FireViewChange(); return S_OK; } else { return Error(_T("Shape must have between 3 and 100 sides")); } }
Depois de adicionar FireViewChange
, recompile e tente o controle novamente no Contêiner de Teste de Controle ActiveX. Desta vez, ao alterar o número de lados e clicar em Invoke
, você visualizará a alteração de controle imediatamente.
Na próxima etapa, você adicionará um evento.
Voltar para a Etapa 3 | Na Etapa 5
Confira também
Tutorial
Testando propriedades e eventos com contêiner de teste