다음을 통해 공유


그리기 코드 변경(ATL 자습서, 4부)

기본적으로 컨트롤의 그리기 코드는 정사각형 및 텍스트 PolyCtl을 표시합니다. 이 단계에서는 더 흥미로운 항목을 표시하도록 코드를 변경합니다. 관련된 작업은 다음과 같습니다.

  • 헤더 파일 수정

  • OnDraw 함수 수정

  • 다각형 점을 계산하는 메서드 추가

  • 채우기 색 초기화

헤더 파일 수정

먼저 수학 함수 sincos에 대한 지원을 추가하고 다각형 점을 계산하고 위치를 저장할 배열을 만들어 계산합니다.

헤더 파일을 수정하려면

  1. PolyCtl.h의 맨 위에 줄을 #include <math.h> 추가합니다. 파일의 맨 위는 다음과 같습니다.

    #include <math.h>
    #include "resource.h"       // main symbols
    
  2. IProvideClassInfo PolyCtl.h에 다음 코드를 추가하여 컨트롤에 대한 메서드 정보를 제공하는 인터페이스를 구현합니다. 클래스에서 CPolyCtl 줄 바꾸기:

    public CComControl<CPolyCtl>
    

    다음과 같이 바꿉니다.

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

    에서 BEGIN_COM_MAP(CPolyCtl)다음 줄을 추가합니다.

    COM_INTERFACE_ENTRY(IProvideClassInfo)
    COM_INTERFACE_ENTRY(IProvideClassInfo2)
    
  3. 다각형 점이 계산되면 형식 POINT배열에 저장되므로 PolyCtl.h의 정의 문 short m_nSides; 뒤 배열을 추가합니다.

    POINT m_arrPoint[100];
    

OnDraw 메서드 수정

이제 PolyCtl.h에서 메서드를 OnDraw 수정해야 합니다. 추가할 코드는 다각형을 그릴 새 펜과 브러시를 만든 다음 Win32 API 함수를 Polygon 호출 Ellipse 하여 실제 그리기를 수행합니다.

OnDraw 함수를 수정하려면

  1. PolyCtl.h의 기존 OnDraw 메서드를 다음 코드로 바꿉다.

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

다각형 점을 계산하는 메서드 추가

다각형의 경계를 구성하는 점의 좌표를 계산하는 메서드를 CalcPoints추가합니다. 이러한 계산은 함수에 전달되는 RECT 변수를 기반으로 합니다.

CalcPoints 메서드를 추가하려면

  1. PolyCtl.h에서 클래스의 CPolyCtl public 섹션에 선언 CalcPointsIPolyCtl 을 추가합니다.

    void CalcPoints(const RECT& rc);
    

    클래스의 공개 섹션 CPolyCtl 의 마지막 부분은 다음과 같습니다.

       void FinalRelease()
       {
       }
    public:
       void CalcPoints(const RECT& rc);
    
  2. 이 함수 구현을 CalcPoints 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;
       }
    }
    

채우기 색 초기화

기본 색으로 초기화 m_clrFillColor 합니다.

채우기 색을 초기화하려면

  1. PolyCtl.h의 생성자에 이 줄을 CPolyCtl 추가하여 녹색을 기본 색으로 사용합니다.

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

이제 생성자는 다음과 같이 표시됩니다.

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

컨트롤 빌드 및 테스트

컨트롤을 다시 빌드합니다. PolyCtl.htm 파일이 열려 있는 경우 닫혀 있는지 확인한 다음 빌드 메뉴에서 다각형 빌드를 클릭합니다. PolyCtl.htm 페이지에서 컨트롤을 다시 볼 수 있지만 이번에는 ActiveX 컨트롤 테스트 컨테이너를 사용합니다.

ActiveX 컨트롤 테스트 컨테이너를 사용하려면

  1. ActiveX 컨트롤 테스트 컨테이너를 빌드하고 시작합니다. TSTCON 샘플: ActiveX 컨트롤 테스트 컨테이너는 GitHub에서 찾을 수 있습니다.

    참고 항목

    Script.Cpp에서 관련된 ATL::CW2AEX오류의 경우 줄을 TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT ); TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );바꾸고 줄 바꿈 TRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) ); 을 지정 TRACE( "Source Text: %s\n", bstrSourceLineText );합니다.
    관련된 HMONITOR오류의 경우 프로젝트에서 StdAfx.h를 열고 다음을 TCProps 바꿉다.

    #ifndef WINVER
    #define WINVER 0x0400
    #endif
    

    다음과 같이 바꿉니다.

    #ifndef WINVER
    #define WINVER 0x0500
    #define _WIN32_WINNT 0x0500
    #endif
    
  2. 테스트 컨테이너편집 메뉴에서 새 컨트롤 삽입을 클릭합니다.

  3. 호출PolyCtl class될 컨트롤을 찾아 확인을 클릭합니다. 원 안에 녹색 삼각형이 표시됩니다.

다음 절차에 따라 측면 수를 변경해 봅니다. 테스트 컨테이너 내에서 이중 인터페이스의 속성을 수정하려면 Invoke 메서드를 사용합니다.

테스트 컨테이너 내에서 컨트롤의 속성을 수정하려면

  1. 테스트 컨테이너의 컨트롤 메뉴에서 메서드 호출을 클릭합니다.

    메서드 호출 대화 상자가 표시됩니다.

  2. 메서드 이름 드롭다운 목록 상자에서 Sides 속성의 PropPut 버전을 선택합니다.

  3. 매개 변수 값 상자에 입력 5 하고 값 설정을 클릭한 다음 호출을 클릭합니다.

컨트롤은 변경되지 않습니다. 변수를 설정 m_nSides 하여 내부적으로 측면 수를 변경했지만 컨트롤이 다시 그려지지는 않았습니다. 다른 애플리케이션으로 전환한 다음 테스트 컨테이너다시 전환하면 컨트롤이 다시 그려지고 올바른 수의 측면이 있음을 확인할 수 있습니다.

이 문제를 해결하려면 측면 수를 설정한 후 정의된 함수에 IViewObjectExImpl대한 호출 FireViewChange 을 추가합니다. 컨트롤이 자체 창 FireViewChange 에서 실행 중인 경우 메서드를 직접 호출합니다 InvalidateRect . 컨트롤이 창 없이 InvalidateRect 실행되는 경우 컨테이너의 사이트 인터페이스에서 메서드가 호출됩니다. 이렇게 하면 컨트롤이 다시 그려집니다.

FireViewChange에 대한 호출을 추가하려면

  1. 메서드에 호출을 추가하여 PolyCtl.cpp를 FireViewChangeput_Sides 업데이트합니다. 완료되면 메서드는 put_Sides 다음과 같이 표시됩니다.

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

추가 FireViewChange한 후 ActiveX 컨트롤 테스트 컨테이너에서 컨트롤을 다시 빌드하고 다시 시도합니다. 이번에는 측면 수를 변경하고 클릭하면 Invoke컨트롤이 즉시 변경됩니다.

다음 단계에서는 이벤트를 추가합니다.

3 | 단계에서 5단계로 돌아가기

참고 항목

자습서
테스트 컨테이너로 속성 및 이벤트 테스트