// определяющие указатели на массив, при импорте функции
// PolyPolygon в модуле Windows.dcu объявлены как
// нетипизированные параметры-переменные, поэтому
// компилятор не разрешает просто передать Pts и Cnt в
// качестве фактических параметров - он запрещает
// использовать константы там, где требуются переменные.
// Это не совсем корректно, т.к. локальная
// типизированная константа - это на самом деле не
// константа, а глобальная переменная с локальной
// областью видимости. Тем не менее компилятор имеет
// такую особенность, которую приходится учитывать.
// В данном примере функция PolyPolygon используется для
// рисования двух квадратов, один из которых целиком
// лежит внутри другого. При этом содержимое внутреннего
// квадрата остается незаполненным. Обратите внимание,
// что квадраты рисуются в разных направлениях: внешний
// по часовой стрелке, внутренний - против. Если
// установлен режим заполнения ALTERNATE, это никак не
// влияет на результат, но если установить режим WINDING,
// внутренний квадрат не будет закрашен только в том
// случае, если квадраты рисуются в противоположных
// направлениях.
PolyPolygon(Canvas.Handle, (@Pts)^, (@Cnt)^, 2);
Вся хитрость в этом коде — как передать параметры в функцию PolyPolygon
. Ее второй параметр — это указатель на массив элементов TPoint
, содержащий координаты вершин всех контуров в массиве: сначала все вершины первого контура в нужном порядке, затем — все вершины второго контура и т.д. Третий параметр — это указатель на массив, содержащий число точек в каждом контуре: первый элемент массива содержит число точек в первом контуре, второй — во втором и т.д. Общее число контуров определяется четвёртым, последним параметром функции PolyPolygon
. Число элементов во втором массиве должно быть равно значению четвертого параметра, a число элементов в первом массиве — сумме значений элементов второго массива. За выполнением этих требований должен следить сам программист, если он ошибется, функция может обратиться к памяти, лежащей за пределами массивов, и последствия будут непредсказуемыми.
В оригинале параметры-массивы функции PolyPolygon
объявлены как указатели на типы элементов массива. В модуле Windows
при импорте этой функции, как это часто бывает в подобных случаях, эти параметры стали нетипизированными параметрами-переменными. В нашем случае массивы объявлены как локальные типизированные константы. По сути, в этом случае они являются глобальными переменными с локальной областью видимости, т.е., как обычные глобальные переменные, хранятся в сегменте данных и существуют на протяжении всего времени работы программы, но компилятор разрешает использовать их только внутри той процедуры, в которой они объявлены. И, несмотря на то, что по сути такие "константы" являются переменными, компилятор их рассматривает как константы и запрещает подставлять там, где требуются параметры-переменные. Поэтому приходится "обманывать" компилятор, получая указатель на эти константы, а затем разыменовывая его. Если бы наши массивы хранились в обычных переменных, нужды прибегать к такому приему не было бы.
Нетрудно убедиться, что первые четыре элемента массива Pts
содержат координаты вершин внешнего квадрата рамки, последние четыре — внутреннего квадрата. Массив
Cnt, соответственно, содержит два элемента, оба из которых имеют значение 4. Это означает, что в нашей фигуре два замкнутых контура, и оба содержат по четыре вершины. Порядок следования вершин во внешнем квадрате — по часовой стрелке, во внутреннем — против. Это имеет значение, если выбран режим заливки WINDING
, тогда направления обхода контуров должны быть противоположными, иначе отверстие тоже окажется закрашенным. Для режима заливки ALTERNATE
направление обхода контуров не имеет значения.
Далее программа GDIDraw
демонстрирует работу функции InvertRect
, которая инвертирует цвета в заданной прямоугольной области контекста устройства. Для того чтобы это было нагляднее, мы сначала выведем на форму загруженный в OnCreate
рисунок (только на этот раз без региона отсечения) и инвертируем область, частично пересекающуюся с областью рисунка (листинг 1.37).
Листинг 1.37. Пример использования функции InvertRect
// Следующая группа команд выводит рисунок и конвертирует
Читать дальше
Конец ознакомительного отрывка
Купить книгу