Modifica del codice del disegno (Esercitazione di ATL, parte 4)
Per impostazione predefinita, il codice di disegno del controllo visualizza un quadrato e il testo PolyCtl. In questo passaggio si modificherà il codice per visualizzare qualcosa di più interessante. Sono coinvolte le attività seguenti:
Modifica del file di intestazione
Modifica della
OnDraw
funzioneAggiunta di un metodo per calcolare i punti poligono
Inizializzazione del colore di riempimento
Modifica del file di intestazione
Per iniziare, aggiungere il supporto per le funzioni sin
matematiche e cos
, che verrà usato per calcolare i punti poligoni e creando una matrice per archiviare le posizioni.
Per modificare il file di intestazione
Aggiungere la riga
#include <math.h>
all'inizio di PolyCtl.h. La parte superiore del file dovrebbe essere simile alla seguente:#include <math.h> #include "resource.h" // main symbols
Implementare l'interfaccia
IProvideClassInfo
per fornire informazioni sul metodo per il controllo aggiungendo il codice seguente a PolyCtl.h.CPolyCtl
Nella classe sostituire riga:public CComControl<CPolyCtl>
con
public CComControl<CPolyCtl>, public IProvideClassInfo2Impl<&CLSID_PolyCtl, &DIID__IPolyCtlEvents, &LIBID_PolygonLib>
e in
BEGIN_COM_MAP(CPolyCtl)
aggiungere le righe:COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2)
Dopo aver calcolato i punti poligoni, questi verranno archiviati in una matrice di tipo
POINT
, quindi aggiungere la matrice dopo l'istruzioneshort m_nSides;
di definizione in PolyCtl.h:POINT m_arrPoint[100];
Modifica del metodo OnDraw
È ora necessario modificare il OnDraw
metodo in PolyCtl.h. Il codice che aggiungerai crea una nuova penna e un pennello con cui disegnare il poligono e quindi chiama le Ellipse
funzioni API e Polygon
Win32 per eseguire il disegno effettivo.
Per modificare la funzione OnDraw
Sostituire il metodo esistente
OnDraw
in PolyCtl.h con il codice seguente: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; }
Aggiunta di un metodo per calcolare i punti poligono
Aggiungere un metodo, denominato CalcPoints
, che calcolerà le coordinate dei punti che costituiscono il perimetro del poligono. Questi calcoli saranno basati sulla variabile RECT passata alla funzione.
Per aggiungere il metodo CalcPoints
Aggiungere la dichiarazione di
CalcPoints
allaIPolyCtl
sezione pubblica dellaCPolyCtl
classe in PolyCtl.h:void CalcPoints(const RECT& rc);
L'ultima parte della sezione pubblica della
CPolyCtl
classe sarà simile alla seguente:void FinalRelease() { } public: void CalcPoints(const RECT& rc);
Aggiungere questa implementazione della
CalcPoints
funzione alla fine di 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; } }
Inizializzazione del colore di riempimento
Inizializzare m_clrFillColor
con un colore predefinito.
Per inizializzare il colore di riempimento
Usare il verde come colore predefinito aggiungendo questa riga al
CPolyCtl
costruttore in PolyCtl.h:m_clrFillColor = RGB(0, 0xFF, 0);
Il costruttore è ora simile al seguente:
CPolyCtl()
{
m_nSides = 3;
m_clrFillColor = RGB(0, 0xFF, 0);
}
Compilazione e test del controllo
Ricompilare il controllo. Assicurarsi che il file PolyCtl.htm sia chiuso se è ancora aperto e quindi fare clic su Compila poligono dal menu Compila . È possibile visualizzare di nuovo il controllo dalla pagina PolyCtl.htm, ma questa volta usare il contenitore di test del controllo ActiveX.
Per usare il contenitore di test del controllo ActiveX
Compilare e avviare il contenitore di test del controllo ActiveX. L'esempio TSTCON: Contenitore di test del controllo ActiveX è disponibile in GitHub.
Nota
Per gli errori che interessano
ATL::CW2AEX
, in Script.Cpp sostituire rigaTRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT );
conTRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );
eTRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) );
conTRACE( "Source Text: %s\n", bstrSourceLineText );
.
Per gli errori che interessanoHMONITOR
, aprire StdAfx.h nelTCProps
progetto e sostituire:#ifndef WINVER #define WINVER 0x0400 #endif
con
#ifndef WINVER #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #endif
Nel contenitore di test scegliere Inserisci nuovo controllo dal menu Modifica.
Individuare il controllo, che verrà chiamato
PolyCtl class
e fare clic su OK. Verrà visualizzato un triangolo verde all'interno di un cerchio.
Provare a modificare il numero di lati seguendo la procedura successiva. Per modificare le proprietà in un'interfaccia doppia dall'interno del contenitore di test, usare i metodi Invoke.
Per modificare la proprietà di un controllo dall'interno del contenitore di test
In Contenitore di test fare clic su Richiama metodi dal menu Controllo .
Viene visualizzata la finestra di dialogo Richiama metodo .
Selezionare la versione PropPut della proprietà Sides dall'elenco a discesa Nome metodo.
Digitare
5
nella casella Valore parametro, fare clic su Imposta valore e fare clic su Richiama.
Si noti che il controllo non cambia. Anche se il numero di lati è stato modificato internamente impostando la m_nSides
variabile, il controllo non è stato aggiornato. Se si passa a un'altra applicazione e quindi si torna al contenitore di test, si scoprirà che il controllo è stato ridisegnato e ha il numero corretto di lati.
Per risolvere il problema, aggiungere una chiamata alla FireViewChange
funzione, definita in IViewObjectExImpl
, dopo aver impostato il numero di lati. Se il controllo è in esecuzione nella propria finestra, FireViewChange
chiamerà direttamente il InvalidateRect
metodo . Se il controllo è in esecuzione senza finestra, il InvalidateRect
metodo verrà chiamato nell'interfaccia del sito del contenitore. In questo modo il controllo viene ridipingeto.
Per aggiungere una chiamata a FireViewChange
Aggiornare PolyCtl.cpp aggiungendo la chiamata al
FireViewChange
put_Sides
metodo . Al termine, ilput_Sides
metodo dovrebbe essere simile al seguente: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")); } }
Dopo aver aggiunto FireViewChange
, ricompilare e ritentare il controllo nel contenitore di test del controllo ActiveX. Questa volta, quando si modifica il numero di lati e si fa clic su Invoke
, verrà visualizzata immediatamente la modifica del controllo.
Nel passaggio successivo si aggiungerà un evento.
Tornare al passaggio 3 | al passaggio 5
Vedi anche
Esercitazione
Test di proprietà ed eventi con Test Container