Изменение кода отрисовки (учебник ATL, часть 4)
По умолчанию код рисования элемента управления отображает квадрат и текст PolyCtl. На этом шаге вы измените код, чтобы отобразить что-то более интересное. К этим задачам относятся следующие задачи:
Изменение файла заголовка
OnDraw
Изменение функцииДобавление метода для вычисления точек многоугольника
Инициализация цвета заливки
Изменение файла заголовка
Начните с добавления поддержки математических функций sin
и cos
, которые будут использоваться для вычисления точек многоугольника, и путем создания массива для хранения позиций.
Изменение файла заголовка
Добавьте строку
#include <math.h>
в верхнюю часть PolyCtl.h. Верхняя часть файла должна выглядеть следующим образом:#include <math.h> #include "resource.h" // main symbols
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)
После вычисления точек многоугольника они будут храниться в массиве типа
POINT
, поэтому добавьте массив после инструкцииshort m_nSides;
определения в PolyCtl.h:POINT m_arrPoint[100];
Изменение метода OnDraw
Теперь необходимо изменить OnDraw
метод в PolyCtl.h. Добавленный код создает новое перо и кисть, с помощью которого нарисовывается многоугольник, а затем вызывает Ellipse
Polygon
функции API Win32 для выполнения фактического рисования.
Изменение функции OnDraw
Замените существующий
OnDraw
метод в PolyCtl.h следующим кодом: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
Добавьте объявление
CalcPoints
в общедоступныйIPolyCtl
разделCPolyCtl
класса в PolyCtl.h:void CalcPoints(const RECT& rc);
Последняя часть общедоступного
CPolyCtl
раздела класса будет выглядеть следующим образом:void FinalRelease() { } public: void CalcPoints(const RECT& rc);
Добавьте эту реализацию
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
с цветом по умолчанию.
Инициализация цвета заливки
Используйте зеленый цвет в качестве цвета по умолчанию, добавив эту строку в
CPolyCtl
конструктор в PolyCtl.h:m_clrFillColor = RGB(0, 0xFF, 0);
Конструктор теперь выглядит следующим образом:
CPolyCtl()
{
m_nSides = 3;
m_clrFillColor = RGB(0, 0xFF, 0);
}
Сборка и тестирование элемента управления
Перестройте элемент управления. Убедитесь, что файл PolyCtl.htm закрыт, если он по-прежнему открыт, а затем нажмите кнопку "Создать многоугольник " в меню "Сборка ". Вы можете снова просмотреть элемент управления на странице PolyCtl.htm, но на этот раз используйте контейнер тестов activeX.
Использование контейнера тестов activeX
Создайте и запустите контейнер тестов activeX. Пример TSTCON: контейнер тестов activeX можно найти на сайте GitHub.
Примечание.
Для ошибок, связанных
ATL::CW2AEX
с скриптом Cpp, замените строкуTRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT );
TRACE( "XActiveScriptSite::GetItemInfo( %s )\n", pszNameT.m_psz );
строкой и строкойTRACE( "Source Text: %s\n", bstrSourceLineText );
TRACE( "Source Text: %s\n", COLE2CT( bstrSourceLineText ) );
.
Для ошибок, связанных сHMONITOR
этим, откройте StdAfx.h вTCProps
проекте и замените:#ifndef WINVER #define WINVER 0x0400 #endif
на
#ifndef WINVER #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #endif
В меню "Изменить" в меню "Тестовый контейнер" нажмите кнопку "Вставить новый элемент управления".
Найдите элемент управления, который будет вызываться
PolyCtl class
, и нажмите кнопку "ОК". В круге появится зеленый треугольник.
Попробуйте изменить количество сторон, выполнив следующую процедуру. Чтобы изменить свойства в двойном интерфейсе из тестового контейнера, используйте методы Invoke.
Изменение свойства элемента управления из контейнера тестирования
В тестовом контейнере щелкните "Вызвать методы " в меню "Элемент управления ".
Откроется диалоговое окно "Метод invoke".
Выберите версию свойства "Стороны" в раскрывающемся списке "Имя метода".
Введите
5
поле "Значение параметра", нажмите кнопку "Задать значение" и нажмите кнопку "Вызвать".
Обратите внимание, что элемент управления не изменяется. Хотя количество сторон было изменено внутренне, задав m_nSides
переменную, это не привело к повторной настройке элемента управления. Если переключиться на другое приложение, а затем вернуться к тестовой контейнере, вы увидите, что элемент управления переопределен и имеет правильное количество сторон.
Чтобы устранить эту проблему, добавьте вызов FireViewChange
функции, определенный в IViewObjectExImpl
, после установки количества сторон. Если элемент управления выполняется в собственном окне, FireViewChange
вызовет метод напрямую InvalidateRect
. Если элемент управления работает без окна, InvalidateRect
метод будет вызываться в интерфейсе сайта контейнера. Это заставляет элемент управления перезапугать себя.
Добавление вызова в FireViewChange
Обновите PolyCtl.cpp, добавив вызов
FireViewChange
к методуput_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
См. также
Руководство
Тестирование свойств и событий с использованием тестового контейнера