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 funzione

  • Aggiunta 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

  1. 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
    
  2. 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)
    
  3. Dopo aver calcolato i punti poligoni, questi verranno archiviati in una matrice di tipo POINT, quindi aggiungere la matrice dopo l'istruzione short 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

  1. 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

  1. Aggiungere la dichiarazione di CalcPoints alla IPolyCtl sezione pubblica della CPolyCtl 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);
    
  2. 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

  1. 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 nuovamente 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

  1. 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 riga TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT ); con TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );e TRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) ); con TRACE( "Source Text: %s\n", bstrSourceLineText );.
    Per gli errori che interessano HMONITOR, aprire StdAfx.h nel TCProps progetto e sostituire:

    #ifndef WINVER
    #define WINVER 0x0400
    #endif
    

    con

    #ifndef WINVER
    #define WINVER 0x0500
    #define _WIN32_WINNT 0x0500
    #endif
    
  2. Nel contenitore di test scegliere Inserisci nuovo controllo dal menu Modifica.

  3. Individuare il controllo, che verrà chiamato PolyCtl classe 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

  1. In Contenitore di test fare clic su Richiama metodi dal menu Controllo .

    Viene visualizzata la finestra di dialogo Richiama metodo .

  2. Selezionare la versione PropPut della proprietà Sides dall'elenco a discesa Nome metodo.

  3. 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

  1. Aggiornare PolyCtl.cpp aggiungendo la chiamata al FireViewChangeput_Sides metodo . Al termine, il put_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