Координатные преобразованияВ начале предыдущей главы уже были описаны функции
GdipRotateWorldTransform и GdipTranslateWorldTransform, при
помощи которых можно выполнять координатные преобразования, а именно:
переносить точку начала координат в произвольное место растра и поворачивать
координатные оси на заданный угол. Создайте в проекте форму с именем DemoTimer.
Установите её размеры равными 300 (ширина) на 250 (высота) пикселей.
Разместите на форме управляющий элемент Timer, установите его
свойство Enabled в «ложь», а свойству Interval присвойте
значение 1000, чтобы таймер срабатывал один раз в секунду.
Установите начальные значения свойств
nativeGraphics, nativePen и nativeBrush равными нулю.
DECLARE Long GdipCreateFromHWND IN Gdiplus.dll Long, Long @ DECLARE Long GdipGraphicsClear IN Gdiplus.dll Long, Long DECLARE Long GdipTranslateWorldTransform IN Gdiplus.dll Long, Single, Single, Long DECLARE Long GdipRotateWorldTransform IN Gdiplus.dll Long, Single, Long DECLARE Long GdipDrawLineI IN Gdiplus.dll Long, Long, Long, Long, Long, Long DECLARE Long GdipFillEllipseI IN Gdiplus.dll Long, Long, Long, Long, Long, Long DECLARE Long GdipCreatePen1 IN Gdiplus.dll Long, Single, Long, Long @ DECLARE Long GdipSetPenColor IN Gdiplus.dll Long, Long DECLARE Long GdipSetPenWidth IN Gdiplus.dll Long, Single DECLARE Long GdipCreateSolidFill IN Gdiplus.dll Long, Long @ DECLARE Long GdipDeleteGraphics IN Gdiplus.dll Long DECLARE Long GdipDeletePen IN Gdiplus.dll Long DECLARE Long GdipDeleteBrush IN Gdiplus.dll Long DECLARE Long GdipDrawClosedCurveI IN Gdiplus.dll Long, Long, String, Long DECLARE Long GdipSetSolidFillColor IN Gdiplus.dll Long, Long DECLARE Long GdipSetSmoothingMode IN Gdiplus.dll Long, Long DECLARE Long GetLocalTime IN WIN32API String @ * Заполнение структур, описывающих массивы размеров часовой и минутной стрелок thisform.cPointsHour = BINTOC(0, "4RS") + BINTOC(-90, "4RS") + BINTOC(-10, "4RS") + ; BINTOC(10, "4RS") + BINTOC(10, "4RS") + BINTOC(10, "4RS") thisform.cPointsMinute = BINTOC(0, "4RS") + BINTOC(-115, "4RS") + BINTOC(-10, "4RS") + ; BINTOC(5, "4RS") + BINTOC(10, "4RS") + BINTOC(5, "4RS") Последняя объявленная функция, GetLocalTime, подробно
рассмотрена в главе 19 «Windows API». Она необходима для получения значений
часов, минут и секунд. Событие Destroy возникает перед уничтожением формы. В методе, обрабатывающем это событие, необходимо удалить все созданные объекты GDIPlus.
= GdipDeleteGraphics(this.nativeGraphics) = GdipDeletePen(this.nativePen) = GdipDeleteBrush(this.nativeBrush) Где лучше всего создавать связанный с формой объект Graphics? Вероятно, в методе, обрабатывающем событие Paint. Событие Paint происходит, когда форма уже выведена на экран. Одновременно с созданием объекта Graphics так же создадим перо и кисть. В этом же методе при помощи функции GdipTranslateWorldTransform перенесём оси координат в центр формы.
LOCAL lnGraphics, lnPen, lnBrush lnGraphics = 0 IF GdipCreateFromHWND(this.HWnd, @lnGraphics) = 0 this.nativeGraphics = lnGraphics = GdipSetSmoothingMode(lnGraphics, 4) lnPen = 0 IF GdipCreatePen1(0, 1, 0, @lnPen) = 0 this.nativePen = lnPen lnBrush = 0 IF GdipCreateSolidFill(0xFF00FF00, @lnBrush) = 0 this.nativeBrush = lnBrush = GdipTranslateWorldTransform(lnGraphics, this.width/2, this.height/2, 0) this.Timer1.Timer() this.Timer1.Enabled = .t. ENDIF ENDIF ENDIF В методе функцией GdipCreateFromHWND создаётся
объект Graphics, связанный с окном формы. Так как мы создали обычную
немодальную форму без полос прокрутки, то нам не требуется определять
«истинный» hWnd верхнего окна. Теперь самое главное: при помощи функции
GdipTranslateWorldTransform центр осей координат переносится в центр
окна формы. Надеюсь, вы обратили внимание на то, что в методе Init
координаты точек стрелок заданы отрицательными числами; сделано это как раз
с учётом того, что центр оси координат будет смещён, и поэтому стрелки будут
находиться внутри окна формы. Откройте для редактирования метод Timer управляющего элемента Timer1 и введите в него код из листинга 23.27.
LOCAL i, lnHour, lnMinute, lnSecond, lcSystemTime * Всё стираем и заливаем форму однотонным цветом = GdipGraphicsClear(thisform.nativeGraphics, 0xFFEEFFEE) STORE 0 TO lnHour, lnMinute, lnSecond * Формируем структуру SystemTime и вызываем функцию GetLocalTime * для получения текущего значения часов, минут и секунд lcSystemTime = REPLICATE(CHR(0),16) = GetLocalTime(@lcSystemTime) lnHour = CTOBIN(SUBSTR(lcSystemTime,9,2),'2RS') lnMinute = CTOBIN(SUBSTR(lcSystemTime,11,2),'2RS') lnSecond = CTOBIN(SUBSTR(lcSystemTime,13,2),'2RS') * Корректируем значение часов IF lnHour > 12 lnHour = lnHour – 12 ENDIF lnHour = INT(5 * lnHour + lnMinute / 12) * Цикл на 60 итераций FOR i = 0 TO 59 * Рисуем минутные отметки шкалы циферблата = GdipSetPenWidth(thisform.nativePen, 4) = GdipSetPenColor(thisform.nativePen, 0xFF00AA00) = GdipDrawLineI(thisform.nativeGraphics, thisform.nativePen, 117, 0, 120, 0) IF MOD(i, 5) = 0 * Рисуем часовые отметки циферблата = GdipSetPenWidth(thisform.nativePen, 3) = GdipSetPenColor(thisform.nativePen, 0xFF0000AA) = GdipDrawLineI(thisform.nativeGraphics, thisform.nativePen, 110, 0, 125, 0) ENDIF IF lnHour = i && Рисуем часовую стрелку = GdipSetPenWidth(thisform.nativePen, 2) = GdipSetPenColor(thisform.nativePen, 0xFF0000AA) = GdipDrawClosedCurveI(thisform.nativeGraphics, thisform.nativePen, ; thisform.cPointsHour, 3) ENDIF IF lnMinute = i && Рисуем минутную стрелку = GdipSetPenWidth(thisform.nativePen, 2) = GdipSetPenColor(thisform.nativePen, 0xFF0000AA) = GdipDrawClosedCurveI(thisform.nativeGraphics, ; thisform.nativePen, thisform.cPointsMinute, 3) ENDIF IF lnSecond = i && Рисуем секундную стрелку = GdipSetPenWidth(thisform.nativePen, 2) = GdipSetPenColor(thisform.nativePen, 0xFFAA6600) = GdipDrawLineI(thisform.nativeGraphics, thisform.nativePen, 0, -125, 0, 30) ENDIF * Поворачиваем оси координат на 6 градусов (360 / 60 = 6) = GdipRotateWorldTransform(thisform.nativeGraphics, 6, 0) ENDFOR * Рисуем часовую ось = GdipFillEllipseI(thisform.nativeGraphics, thisform.nativeBrush, -6, -6, 12, 12) Сохраните форму и запустите её на выполнение. Вы должны увидеть нечто подобное показанному на рис.23.6. Часы должны «ходить». Рис. 23.6. Форма DemoTimer в работе Обратите внимание на то, для всех графических примитивов указаны одни и те же координаты, но выводятся эти примитивы в разных позициях в результате поворота координатных осей функцией GdipRotateWorldTransform.
|