Весь код инкапсулирован в три пользовательские функции:
ShadyDiagram – построение полной диаграммы;
Diagram – построение части диаграммы (основной или тени);
DiagramPie – построение одного сегмента диаграммы.
ShadyDiagram просто вызывает два раза функцию Diagram передавая немного разные на величину iShadowDepth (глубина тени) координаты центра для диаграммы и ее тени:
void ShadyDiagram(HDC hDC, int x, int y, int r, int iShadowDepth, const float* pData, const Brush* pBrushes, unsigned int iNumOfPies)
{
Diagram(hDC, x + iShadowDepth, y + iShadowDepth, r, true, pData, pBrushes, iNumOfPies);
Diagram(hDC, x, y, r, false, pData, pBrushes, iNumOfPies);
return;
}
Функции построения одного сегмента имеет следующий прототип:
void DiagramPie(HDC hDC, int x, int y, int r, float s, float e, int fnStyle, COLORREF clrref, const char* szLabel);
В функцию передается контекст устройства, координаты центра x и y (по умолчанию ось x направлена вправо, ось y вниз, начало координат в левом верхнем углу рабочей области окна), радиус, начальный и конечный углы в радианах между которыми строится сегмент s и e, стиль кисти и ее цвет, текстовая метка для сегмента. Если szLabel равно NULL, метка не отображается (необходимо для сегментов тени).
Создание штриховой кисти осуществляется следующим образом:
hBrush = CreateHatchBrush(fnStyle, clrref);
Первым параметром функции задается стиль штриховки, вторым цвет. После создания кисть необходимо выбрать в качестве текущей кисти:
hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
Функция универсальная для кистей, перьев и т.п., поэтому требуется явное преобразование типа. Возвращает предыдущую используемую кисть. Зачем ее сохранять в переменной? Кисть, как и любой другой ресурс, следует удалить после использования.
DeleteObject(hBrush);
Существует правило, справедливое для различных областей программирования – нельзя удалять что-то используемое в данный момент. Поэтому перед удалением, следует задать другую кисть текущей, например, предыдущую. Такой же подход примеряется в функции Diagram() при смене пера.
Все последующие команды вывода используют прямоугольную декартовую систему координат, поэтому для преобразования угловых величин в прямоугольные координаты используются тригонометрические функции cos() и sin().