Udostępnij za pośrednictwem


Zmiana kodu rysującego (ATL — Samouczek, część 4)

Domyślnie kod rysunku kontrolki wyświetla kwadrat i tekst PolyCtl. W tym kroku zmienisz kod, aby wyświetlić coś bardziej interesującego. Są zaangażowane następujące zadania:

  • Modyfikowanie pliku nagłówka

  • Modyfikowanie OnDraw funkcji

  • Dodawanie metody do obliczania punktów wielokątnych

  • Inicjowanie koloru wypełnienia

Modyfikowanie pliku nagłówka

Zacznij od dodania obsługi funkcji sin matematycznych i cos, które będą używane do obliczania punktów wielokątnych oraz przez utworzenie tablicy do przechowywania pozycji.

Aby zmodyfikować plik nagłówka

  1. Dodaj linię #include <math.h> na górze pliku PolyCtl.h. Górna część pliku powinna wyglądać następująco:

    #include <math.h>
    #include "resource.h"       // main symbols
    
  2. Zaimplementuj interfejs, IProvideClassInfo aby udostępnić informacje o metodzie dla kontrolki, dodając następujący kod do pliku PolyCtl.h. W klasie zastąp CPolyCtl wiersz:

    public CComControl<CPolyCtl>
    

    with

    public CComControl<CPolyCtl>,
    public IProvideClassInfo2Impl<&CLSID_PolyCtl, &DIID__IPolyCtlEvents, &LIBID_PolygonLib>
    

    i w pliku BEGIN_COM_MAP(CPolyCtl)dodaj wiersze:

    COM_INTERFACE_ENTRY(IProvideClassInfo)
    COM_INTERFACE_ENTRY(IProvideClassInfo2)
    
  3. Po obliczeniu punktów wielokątnych będą one przechowywane w tablicy typu POINT, więc dodaj tablicę po instrukcji short m_nSides; definicji w pliku PolyCtl.h:

    POINT m_arrPoint[100];
    

Modyfikowanie metody OnDraw

Teraz należy zmodyfikować metodę OnDraw w pliku PolyCtl.h. Dodany kod tworzy nowy pióro i szczotkę, za pomocą którego można narysować wielokąt, a następnie wywołuje Ellipse funkcje interfejsu API Win32 i Polygon w celu wykonania rzeczywistego rysunku.

Aby zmodyfikować funkcję OnDraw

  1. Zastąp istniejącą OnDraw metodę w pliku PolyCtl.h następującym kodem:

    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;
    }
    

Dodawanie metody do obliczania punktów wielokątnych

Dodaj metodę o nazwie CalcPoints, która oblicza współrzędne punktów tworzących obwód wielokąta. Te obliczenia będą oparte na zmiennej RECT przekazywanej do funkcji.

Aby dodać metodę CalcPoints

  1. Dodaj deklarację do CalcPoints publicznej IPolyCtl sekcji CPolyCtl klasy w pliku PolyCtl.h:

    void CalcPoints(const RECT& rc);
    

    Ostatnia część sekcji publicznej CPolyCtl klasy będzie wyglądać następująco:

       void FinalRelease()
       {
       }
    public:
       void CalcPoints(const RECT& rc);
    
  2. Dodaj tę implementację CalcPoints funkcji na końcu 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;
       }
    }
    

Inicjowanie koloru wypełnienia

Zainicjuj m_clrFillColor kolor domyślny.

Aby zainicjować kolor wypełnienia

  1. Użyj koloru zielonego jako domyślnego, dodając ten wiersz do konstruktora CPolyCtl w pliku PolyCtl.h:

    m_clrFillColor = RGB(0, 0xFF, 0);
    

Konstruktor wygląda teraz następująco:

CPolyCtl()
{
   m_nSides = 3;
   m_clrFillColor = RGB(0, 0xFF, 0);
}

Kompilowanie i testowanie kontrolki

Ponownie skompiluj kontrolkę. Upewnij się, że plik PolyCtl.htm jest zamknięty, jeśli jest nadal otwarty, a następnie kliknij polecenie Kompiluj wielokąt w menu Kompilacja . Kontrolkę można wyświetlić ponownie na stronie PolyCtl.htm, ale tym razem użyj kontenera testów kontrolek ActiveX.

Aby użyć kontenera testów kontrolek ActiveX

  1. Skompiluj i uruchom kontener testów kontrolek ActiveX. Przykład TSTCON: Kontener testów kontrolek ActiveX można znaleźć w witrynie GitHub.

    Uwaga

    W przypadku błędów dotyczących ATL::CW2AEXelementu w pliku Script.Cpp zastąp wiersz TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT ); ciągiem TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );, i wierszem TRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) ); TRACE( "Source Text: %s\n", bstrSourceLineText );.
    W przypadku błędów obejmujących HMONITORplik otwórz plik StdAfx.h w projekcie TCProps i zastąp:

    #ifndef WINVER
    #define WINVER 0x0400
    #endif
    

    with

    #ifndef WINVER
    #define WINVER 0x0500
    #define _WIN32_WINNT 0x0500
    #endif
    
  2. W kontenerze testowym w menu Edycja kliknij pozycję Wstaw nową kontrolkę.

  3. Znajdź kontrolkę o nazwie PolyCtl class, a następnie kliknij przycisk OK. W okręgu zobaczysz zielony trójkąt.

Spróbuj zmienić liczbę stron, wykonując następną procedurę. Aby zmodyfikować właściwości w podwójnym interfejsie z poziomu kontenera testowego, użyj metod Invoke.

Aby zmodyfikować właściwość kontrolki z poziomu kontenera testów

  1. W kontenerze testowym kliknij pozycję Wywołaj metody w menu Kontrolka.

    Zostanie wyświetlone okno dialogowe Wywołaj metodę .

  2. Wybierz właściwość PropPut właściwości Sides z listy rozwijanej Nazwa metody.

  3. Wpisz 5 wartość parametru, kliknij pozycję Ustaw wartość, a następnie kliknij przycisk Wywołaj.

Należy pamiętać, że kontrolka nie zmienia się. Mimo że liczba stron została zmieniona wewnętrznie przez ustawienie zmiennej m_nSides , nie spowodowało to przemalowania kontrolki. Jeśli przełączysz się do innej aplikacji, a następnie przełączysz się z powrotem do kontenera testowego, okaże się, że kontrolka została przemalowana i ma poprawną liczbę stron.

Aby rozwiązać ten problem, dodaj wywołanie funkcji FireViewChange zdefiniowanej w IViewObjectExImplpliku po ustawieniu liczby stron. Jeśli kontrolka jest uruchomiona we własnym oknie, FireViewChange wywoła metodę InvalidateRect bezpośrednio. Jeśli kontrolka jest uruchomiona bez okna, InvalidateRect metoda zostanie wywołana w interfejsie lokacji kontenera. Wymusza to kontrolę, aby przemalować się.

Aby dodać wywołanie funkcji FireViewChange

  1. Zaktualizuj PolyCtl.cpp, dodając wywołanie metody FireViewChange do put_Sides metody . Po zakończeniu put_Sides metoda powinna wyglądać następująco:

    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"));
       }
    }
    

Po dodaniu FireViewChangepolecenia ponownie skompiluj kontrolkę i spróbuj ponownie w kontenerze testów kontrolek ActiveX. Tym razem, gdy zmienisz liczbę stron i klikniesz Invokeprzycisk , powinna zostać natychmiast wyświetlona zmiana kontrolki.

W następnym kroku dodasz zdarzenie.

Powrót do kroku 3 | do kroku 5

Zobacz też

Samouczek
Testowanie właściwości i zdarzeń za pomocą kontenera testu