Rect — Функция Delphi


Rect — Функция Delphi

GDI расшифровывается как Graphics Device Interface, и представляет собой интерфейс, который Windows использует для рисования 2D графики. Также это самый медленный способ отображения графики из существующих, однако самый простой для понимания основ. Итак, для начала, поговорим об основных понятиях и терминах в GDI.

Начнём с того, что GDI обычно не используют для создания крутых графических эффектов, для этого есть DirectX, OpenGL, или любые графические библиотеки (такие как: DelphiX, FastLib, DIBUltra, Graphics32. ). Однако, для создание простых эффектов с минимальными усилиями GDI вполне сгодится.

С GDI тесно связана ещё одна аббревиатура — DC («Device Context» — контекст устройства). Это то, на чём мы рисуем, и в Delphi контекст устройства представлен как TCanvas. Идея контекста устройства заключается в том, что это универсальное устройство вывода, поэтому можно использовать одинаковые функции как для экрана, так и для принтера.

Все графические функции в Delphi являются надстройками над стандартными GDI функциями Windows. Позже мы поговорим об этих функциях.

А теперь самое время приступить к рассмотрению того, как устроен GDI. Ниже, в таблице, представлены некоторые важные классы:

ИМЯ ОПИСАНИЕ
Pen Используется для рисования простых линий. Обычно применяется для функции LineTo или при рисовании рамки для определённой фигуры (например для функции Rectangle).
Brush Кисть используется для заполнения области определённым цветом. Применяется в функциях Rectangle, FillRect или FloodFill.
Font Используется для задания шрифта, которым будет нарисован текст. Можно указать имя шрифта, размер и т.д.
Region Позволяет задать регион (замкнутое пространство). Регионом может быть круг, квадрат или произвольная фигура. Позволяет так же делать дырки в фигурах.

Однако, пора переходить от слов к делу, а именно, начать рисовать линии и фигуры.

Сперва необходимо чётко уяснить, что координата (0,0) это верхний левый угол экрана. То есть значения по оси y увеличиваются вниз экрана. Соответственно, координата (0, 50) означает, что мы просто отступили на 50 пикселей от верха экрана.

Самое главное, что надо знать при рисовании линий и фигур, это различие между пером (Pen) и кистью (Brush). Всё очень просто: перо (Pen) используется при рисовании линий или рамок, а кисть (Brush) для заполнения фигуры.

Ниже приведены две функции, которые используются для рисования линий и обе принадлежат TCanvas:

ИМЯ ОПИСАНИЕ ПРИМЕР
MoveTo Перемещает точку начала рисования линии в указанные координаты x и y Canvas.MoveTo(50, 100);
LineTo Рисует линию начиная с текущей позиции (см. MoveTo) до указанных координат x и y. Canvas.LineTo(50, 100);

Эффект перемещения точки начала рисования линии так же достигается при помощи установки своства PenPos в канвасе. например, «Canvas.PenPos.x := 20;», «Canvas.PenPos.y := 50», или «Canvas.PenPos := Point(20,50);».

По умолчанию, точка начала рисования установлена в (0,0), то есть, если сразу вызвать «Canvas.LineTo(100,100);» то будет нарисована линия из точки (0,0) в точку (100, 100). Точка начала рисования автоматически переместится в (100, 100), то есть, если выполнить команду «Canvas.LineTo(200, 100);», то следующая линия будет нарисована из точки (100, 100) в (200, 100). Поэтому, если мы хотим рисовать линии несоединённые друг с другом, то придётся воспользоваться методом MoveTo.

Линия, нарисованная при помощи LineTo использует текущее перо канваса (типа TPen). Основные свойства пера, это ширина — «Canvas.Pen.W .

Взглянем на простой пример беспорядочного рисования разноцветных линий:

Процедура DrawLines вызывается из обработчика кнопки OnClick. Количество линий задаётся в константе NUM_LINES. Между прочим, функция RGB, составляет цвет каждой линии из трёх основных составляющих: красного, зелёного и синего (значения от 0 до 255) и возвращает нам цвет в виде TColor. О цветах поговорим немного позже, а вот так выглядит нарисованный пейзаж:

Теперь, когда линии нарисованы, попробуйте немножко подвигать форму. Если форму переместить за края экрана, то Вы увидите, что линии частично стёрлись. Это не глюк, и решается эта проблема очень просто. Но не сейчас ;-). Сперва посмотрим, как рисовать различные фигуры.

Для рисования фигур, в TCanvas предусмотрены следующие функции:

ИМЯ ОПИСАНИЕ ПРИМЕР
Ellipse Рисует элипс, вписанный в невидимый квадрат с координатами верхнего левого угла и правого нижнего. Если координаты х и y у углов будут совпадать, то получится круг. Canvas.Ellipse(0,0,50,50);
FillRect Заполняет прямоугольник цветом текущей кисти (brush), но никак не за пределами него. Canvas.FillRect( Bounds(0,0,100,100));
FloodFill Заполняет данную область цветом текущей кисти, до тех пор пока не будет достигнут край. Canvas.FloodFill(10, 10, clBlack, fsBorder);
Rectangle Рисует прямоугольник (или квадрат), заполненный цветом текущей кисти и обрамлённый цветом текущего пера Canvas.Rectangle( Bounds(20, 20, 50, 50));
RoundRect Тоже, что и Rectangle, но с загруглёнными углами. Canvas.RoundRect( 20, 20, 50, 50, 3, 3);

Ещё есть очень нужная функция TextOut, которая позволяет рисовать текст, используя шрифт, заданный в канвасе:

ИМЯ ОПИСАНИЕ ПРИМЕР
TextOut Рисует данную строку на канвасе начиная с координат (x,y) — фон текста заполняется текущим цветом кисти. Canvas.TextOut(10, 10, ‘Some text’);

Кстати, функция позволяет рисовать текст, не заполняя его фон. Если Вам необходимо изменить шрифт, используемый в TextOut, то необходимо изменить свойство Font канваса (это свойство имеет тип TFont) — например «Canvas.Font.Name := ‘Verdana’;», «Canvas.Font.Size := 24;» или «Canvas.Font.Color := clRed;».

Вкратце хотелось бы обратить Ваше внимание на довольно полезный класс TRect, который умеет хранить в себе значения лево, право, верха и низа (кстати, в Windows API это RECT). То ест, достаточно указать левую и верхнюю координату и ширину и высоту области, а TRect автоматически подставит в виде (лево, верх, лево + ширина, верх + высота). Ещё есть другая функция Rect(), которая делает тоже самое, но координаты в ней задаются напрямую как лево, право, верх и низ. Ну и по желанию, можно использовать API функцию SetRect.

Ниже представлен пример, который рисует случайным образом различные фигуры:

Как Вы уже успели заметить, некоторые фигурки имеют цвет рамки, отличающийся от того цвета, которым заполнена фигура. Это как раз тот момент, о котором я упоминал выше. Кистью мы заполняем объекты, а пером обрамляем. Если цвет кисти (brush) меняется случайным образом, то цвет пера(pen) остаётся постоянным. Из-за этого и получается такая картина.

Теперь давайте разберёмся, почему в самом первом примере у нас стирались линии при перемещении формы за границы экрана. А именно, нам нужно выяснить разницу между «рисованием» и «перерисовкой».

Рисование, это то, что мы делали выше. То есть, рисовали любые линии и графические фигуры. Однако, рисунок сохранялся до тех пор, пока окно(форма) не было обновлено.

Перерисовка несколько отличается от понятия «рисование». Когда окну необходимо перерисоваться, то Windows посылает определённое сообщение. Это сообщение поступает в обработчик события «OnPaint». Любой код, который поместить в обработчик OnPaint будет вызван каждый раз, когда форме необходимо обновиться.

Для примера, поместите следующий код в проект:

Если поместить на форму кнопку и вызывать DrawSomeText из обработчика кнопки OnClick, то проблема с исчезновением текста при перемещении формы останется. ОДНАКО, если вызвать DrawSomeText из обработчика формы OnPaint, то текст останется на своём месте окончательно.

Дескрипторы, или как пользоваться аналогичными API функциями

Итак, мы научились рисовать линии, различные фигуры, научились делать так, чтобы наше творение не стиралось при перемещении формы, и проделали мы всё это при помощи стандартных функций VCL (таких как Canvas.TextOut и т.д.). Однако, что делать, если Вы не хотите пользоваться графическими функциями VCL, которые всего навсего являются надстройками над аналогичными функциями из Windows API? Пожалуйста! Никто нам не запрещает пользоваться API функциями напрямую! Но постойте-ка, все они требуют какого-то HDC! Что такое HDC?

Почти всё в Windows использует «Дескриптор» (Handle). Дескриптор, это способ идентификации Вашего объекта в системе. У каждого окна есть свой дескриптор, у каждой кнопки тоже есть свой дескриптор и т.д. Именно поэтому все наши объекты имеют дескриптор в качестве свойства — например, «MyForm.Canvas.Handle».

Тип HDC это Дескриптор(Handle) Контекста Устройства (Device Context). Я уже говорил в самом начале, что TCanvas включает в себя большинство функций DC. Поэтому, мы спокойно можем подставлять свойство канваса Handle везде, где нам это потребуется.

Ради интереса можно взглянуть на таблицу, в которой представлены примеры вызовов некоторых функций из VCL и их аналогов из Windows API.

VCL WINDOWS API
Canvas.TextOut(x,y,myString); TextOut(Canvas.Handle, x, y, PChar(myString), Length(String));
Canvas.FloodFill(X, Y, Color,fsBorder); ExtFloodFill(Canvas.Handle, x, y, YourColour, FLOODFILLBORDER);
Canvas.LineTo(x,y); LineTo(Canvas.Handle, x, y);
Canvas.MoveTo(x,y); MoveToEx(Canvas.Handle, x, y, nil);

Так же можно использовать разные дескрипторы, чтобы рисовать в разных местах. Например, можно использовать «SomeBmp.Canvas.Handle» для рисования на картинке (битмапе), либо «Form1.Canvas.Handle», чтобы рисовать на форме.

В API версии функции TextOut необходимо передавать строку завершённую нулём. Это значит, что вместо того, чтобы передать строку в функцию напрямую, необходимо передать её как PChar. Так же не забывайте передавать в функцию длину строки. Для этого можно воспользоваться функцией Length.

Ну что, Вам уже захотелось поместить на форму какую-нибудь красивую картинку ?

Что такое Битмапы (Bitmaps)?

Рисование линий, это, конечно, хорошо, но рано или поздно Вам понадобится нарисовать более реалистичную картнику в своём приложении. Поэтому совершенно необходимо научиться работать с растровыми изображениями, или как их называют в среде программистов — битмапами.

Битмап, это графический объект, который содержит заголовок, необходимую информацию о картинке (такую как высота, ширина, цвета и т.д.) и, собственно, само изображение (большой массив, содержащий цвет каждой точки). В Delphi для этой цели уже предусмотрен класс TBitmap.

Битмапы можно рисовать не только на форме, но и по всему экрану. Может это и может показаться немного странным, но иногда это бывает полезно, особенно при создании скринсейвера. Однако, сначала нам необходимо разобраться с тем, как работать с битмапами. Вот небольшой пример:

Эта функция пытается загрузить и показать картинку, (с именем Filename, например ‘myBitmap.bmp’) начиная с точки (x,y).

Сразу скажу, что эта функция довольно неэффективна. Она создаёт и уничтожает битмап каждый раз когда вызывается, а так же каждый раз проверяет существование файла. Лучше объявлять объект TBitmap как часть формы, создавать и загружать картинку в FormCreate, а освобождать её в FormDestroy.

Функции рисования в GDI

TCanvas имеет несколько полезных функций, которые работают с типом TGraphic. Тип TGraphic является базовым классом для графических объектов в Delphi, таких как: битмапы (TBitmap), иконки (TIcon), метафайлы (TMetafile) и JPEG-и (TJPEGImage). Все они используют одни и те же функции, которые приведены в таблице:

Все эти функции являются методами TCanvas.

ИМЯ ОПИСАНИЕ ПРИМЕР ИСПОЛЬЗОВАНИЯ
Draw Рисует TGraphic на канвасе так как он есть, не растягивая. Canvas.Draw(5,10,MyGraphic);
StrechDraw Рисует TGraphic на канвасе, подгоняя (растягивая) его под заданную область. Canvas.StretchDraw( Bounds(0,0,32,32), MyGraphic);
CopyRect Копирует часть TCanvas-а в другой, при необходимости растягивая его. Canvas.CopyRect( Bounds(0,0,32,32), MyBmp.Canvas, Bounds(0, 0, 640, 480));

TCanvas.Draw является обёрткой для API функции BitBlt:

Описанный выше способ позволяет рисовать битмап в run-time. Конечно, проще поместить на форму TImage и установить в ней картинку. Изображение будет постоянно оставаться на том месте, где Вы его поместили, но это скучно ;-). Куда интереснее сделать при помощи битмапов анимацию.

С другой стороны, поняв принципы работы с битмапами, Вам будет легче перейти к другим графическим библиотекам (например DirectX).

Rect — Функция Delphi

Работа с графикой в Delphi это не только линии и рисунки, но также и и печать текстовых документов. Поэтому в Delphi работе с графикой нужно уделить немного времени. Работа с графикой в Delphi предполагает обращение к канве — свойству Canvas компонентов. Canvas Delphi это холст, который позволяет программисту иметь доступ к каждой своей точке (пикселу), и словно художнику отображать то, что требуется. Конечно, рисовать попиксельно для работы с графикой в Delphi не приходится, система Delphi предоставляет для мощные средства работы с графикой, облегчающие задачу программиста.

В работе с графикой в Delphi в распоряжении программиста находятся канва (холст, полотно — свойство Canvas Delphi компонентов), карандаш (свойство Pen), кисть (свойство Brush) того компонента или объекта, на котором предполагается рисовать. У карандаша Pen и кисти Brush можно менять цвет (свойство Color) и стиль (свойство Style). Доступ к шрифтам предоставляет свойство канвы Font. Эти инструменты позволяют отображать как текст, так и достаточно сложные графики математического и инженерного содержания, а также рисунки. Кроме этого, работа с графикой позволяет использовать в Delphi такие ресурсы Windows как графические и видеофайлы.

Конечно, не все компоненты в Delphi имеют эти свойства. На вкладке Additional расположен специализированный компонент TImage, специально предназначенный для рисования, но также свойство Canvas имеют, например, такие компоненты как ListBox, ComboBox, StringGrid, а также и сама Форма, которая размещает наши компоненты! Кроме того, для печати документов Delphi обращается к свойству Canvas такого объекта как принтер.

Основное свойство такого объекта как Canvas Delphi — Pixels[i, j] типа TColor, то есть это двумерный массив точек (пикселов), задаваемых своим цветом. Рисование на канве происходит в момент присвоения какой-либо точке канвы заданного цвета. Каждому пикселу может быть присвоен любой доступный для Windows цвет. Например, выполнение оператора

приведёт к рисованию красной точки с координатами [100, 100]. Узнать цвет пиксела можно обратным присвоением:

Тип TColor определён как длинное целое (LongInt). Его четыре байта содержат информацию о долях синего (B), зелёного (G), и красного (R) цветов. В 16-ричной системе это выглядит так: $00BBGGRR. Доля каждого цвета может меняться от 0 до 255. Поэтому чтобы отобразить максимально красную точку, ей нужно присвоить цвет $000000FF.
Для стандартных цветов в Delphi определён набор текстовых констант. Увидеть его можно, открыв в Инспекторе Объектов свойство Color, например, той же Формы.

Следующая таблица содержит некоторые свойства и методы канвы:

Процедура TextOut(X, Y: Integer; const Text: WideString);
Производит вывод строки Text начиная с (X, Y) — левого верхнего пиксела текста.
Свойство TextWidth(var Text: String): Integer;
Содержит длину строки Text в пикселах.
Свойство TextHeight(var Text: String): Integer;
Содержит высоту строки Text в пикселах.
Процедура MoveTo(X, Y: Integer);
Производит перемещение позиции к пикселу с адресом (X, Y).
Процедура LineTo(X, Y: Integer);
Производит рисование прямой линии из точки текущей позиции к пикселу с адресом (X, Y). Адрес (X, Y) становится точкой текущей позиции.
Процедура FillRect(const Rect: TRect);
Заполняет прямоугольник Rect на холсте, используя текущую кисть. Может использоваться, в том числе, для стирания части изображения на холсте.

Напишем, используя только эти методы канвы, приложение для изображения на канве компонента Image текста, который вводится в компонент Memo:

Расположите на форме компоненты Memo, Image (находится на странице Additional), Edit, UpDown (находится на странице Win32). Свойство Associate компонента UpDown приравняйте в выпадающем списке нашему компоненту Edit. Этим компонентом мы будем изменять размер шрифта. Поскольку и Memo и Image находятся у нас на одном устройстве вывода — на нашем экране, размер пиксела у них одинаков, и поэтому размеры изображения будут равны.

Первое, что мы сделаем, это инициализацию переменных при старте программы. Необходимо определить размеры области рисования (создадим для этого глобальную переменную Rect типа TRect) и сделать цвет фона Image белым:

procedure TForm1.FormCreate(Sender: TObject);
begin
Rect.Left:=0;
Rect.Top:=0;
Rect.Right:=Image1.Width;
Rect.Bottom:=Image1.Height;
Image1.Canvas.Brush.Color:=clWhite;
end;

Затем нарисуем рамку по сторонам Image:

procedure TForm1.page;
begin
with Image1.Canvas do
begin
MoveTo(0, 0);
LineTo(Image1.Width-1, 0);
LineTo(Image1.Width-1, Image1.Height-1);
LineTo(0, Image1.Height-1);
LineTo(0, 0);
end;
end;

Попробуем, что получилось. Всё работает, но рамка пока не выводится. Поэтому добавим процедуру page в в процедуру FormCreate. Теперь красиво. Далее напишем простую процедуру стирания, очищения Image. Её нужно будет вызывать перед любым обновлением изображения, иначе предыдущее и последующее изображения будут перекрываться.

procedure TForm1.clearing;
begin
Image1.Canvas.FillRect(Rect); //Прямоугольник Rect заполняется белым цветом, изображение стирается.
end;

Теперь пришла очередь непосредственно процедуры вывода текста. Начнём выводить текст от точки (3, 3) — верхнего левого угла листа, с небольшим отступом в 3 пиксела. Каждую последующую строку будем смещать на высоту строки:

procedure TForm1.prn;
var i: Integer;
begin
with Image1.Canvas do
for i:=1 to Memo1.Lines.Count do
TextOut(3, 3+(i-1)*TextHeight(‘A’), Memo1.Lines[i-1]);
end;

Теперь всё готово для вывода текста. Делать это будем по событию OnChange:

procedure TForm1.Memo1Change(Sender: TObject);
begin
clearing;
prn;
page;
end;

Ну и напоследок процедура изменения размера шрифта:

procedure TForm1.Edit1Change(Sender: TObject);
begin
Memo1.Font.Size:=UpDown1.Position;
Image1.Canvas.Font.Size:=UpDown1.Position;
Memo1Change(Sender);
end;

Можно модифицировать эту программу для вывода текста на печать. Для работы с принтером нужно подключить модуль Printers:

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Printers;

При работе с принтером как с полотном для начала печати вызывается метод BeginDoc, затем производится вывод документа, завершается печать вызовом метода EndDoc:

Printer.BeginDoc;
with Printer.Canvas do
begin
. Печать документа .
end;
Printer.EndDoc;

Ширина и высота полотна принтера доступны через свойства Printer.PageWidth и Printer.PageHeight. Закончить печать на одной странице и начать печатать на другой можно с помощью метода Printer.NewPage.

Создание интерфейса В начало урока Потоки в Delphi

Сергей, добавлено 8.10.10, 11:26:02
У меня есть форма, на ней расположенны несколько элементов; такие как ScrollBox на которой в свою очередь так же раположенны некоторые элементы тем самым создовая Определенный документ который я хочу распечатать подскажите как мне это лучше сделать. Автор, добавлено 8.10.10, 15:48:46
Хм, распечатывайте каждый из этих элементов по очереди. Неопределенный ответ на неопределенный вопрос. Графика и печать — большая тема, в двух словах не раскроешь, я только начал. Продолжить завтра смогу, пожалуй с того как напечатать табличку. Сергей, добавлено 11.10.10, 16:04:05
Еще раз попробую сформулировать чего я хочу добится
например есть главная форма где вводятся данные человека (ФИО, и т.д.)они должны записаться в другой форме где я расположил компоненты в виде карточки ну скажем медицинской, и эти саммые данные мне нужно вывести в печать. как мне лучше это сделать? Автор, добавлено 11.10.10, 16:29:30
Можно наверное так, как это сделано в программе выше. Сначала выведите все данные в Memo, пусть даже он будет невидимым, а при разработке и видимым для наглядности, а затем перенесите это на принтер, как показано выше. Только вместо Image1.Canvas напишите Printer.Canvas и размеры области печати тоже нужно модифицировать. veronica, добавлено 17.12.10, 21:43:38
как сделать чтобы вместо цвета формы была картинка, помогите пожалуйста Автор, добавлено 18.12.10, 09:20:06
Нужно воспользоваться методом холста Формы

Илон Маск рекомендует:  Пример использования свойств ссылок. Java Script

Он принимает параметры

Rect — прямоугольник с размерами рисунка
var Rect: TRect;

Graphic — один из классов изображений, например TBitmap
var Foto: TBitmap;

Соответственно, в обработчике OnCreate Формы создаём прямоугольник с размерами Формы:

Rect.Left:=0;
Rect.Top:=0;
Rect.Right:=Width;
Rect.Bottom:=Height;

и объект Bitmap:

Bitmap имеет метод загрузки изображений:

Выводить рисунок нужно не в момент создания Формы, а с небольшой задержкой, я ввёл её с помощью таймера, имеющего задержку 10 мс. Вот и всё. Получилось:

var
Form1: TForm1;
Rect: TRect;
Foto: TBitmap;

procedure TForm1.FormCreate(Sender: TObject);
begin
Rect.Left:=0;
Rect.Top:=0;
Rect.Right:=Width;
Rect.Bottom:=Height;
Foto:=TBitmap.Create;
Foto.LoadFromFile(‘Адрес_Рисунка’);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled:=False;
Form1.Canvas.StretchDraw(Rect, Foto);
end; Антон, добавлено 31.01.11, 21:00:34
А где же обещанная печать таблички? Автор, добавлено 31.01.11, 21:14:34
Антон! Спасибо что напомнил! Антон, добавлено 1.02.11, 18:58:41
Незачто))) А как понимать фразу «. Печать документа . » В кодеPrinter.BeginDoc;
with Printer.Canvas do
begin
. Печать документа .
end;
Printer.EndDoc; Автор, добавлено 1.02.11, 19:56:42
Это значит, что я не буду же за вас документы печатать! Методы я показал, как линеечки поводить, должно быть понятно, как буковки печатать тоже. Вот и таблицу уже самим можно делать. В общем, пробовать надо. Тогда станет, например, и самому понятно, что нужно сначала буковки в табличке печатать, а потом уже ячейки рисовать, иначе в некоторых местах линеечки будут затёрты! Но, конечно, в скорости про печать таблиц сделаю. Новичок , добавлено 27.03.11, 21:46:45
Извините, а как поставить нужную иконку после создания в ярлык? Автор, добавлено 27.03.11, 21:59:29
Также извините, вопрос не понял. Ярлык программы? Тогда так:

Application.Icon.LoadFromFile(‘имя файла с иконкой’);

Или сразу через меню Delphi: Project — Options. и в появившемся окне на вкладке Application есть кнопка для загрузки иконки приложения. Дмитрий, добавлено 7.04.11, 15:52:06
подскажите пожалуйста как перемещать один image по другому? Автор, добавлено 7.04.11, 16:24:11
Дмитрий, что значит перемещать? Двигать по Форме? А каков ваш вариант? В общем, не понял вопрос. Дмитрий, добавлено 24.04.11, 14:36:57
Немного размыто , но смысл понятен Вячеслав, добавлено 17.05.11, 12:30:37
Как перевести пиксели в миллиметры? Вячеслав, добавлено 17.05.11, 12:33:01
Как згенерировать процедуру «procedure TForm1.page;» — после нажатия Ctr+Shift+C выдайотса ошыбка. Автор, добавлено 17.05.11, 14:22:36
А вручную написать влом? Я так делаю иногда. Насчёт пикселей. Есть метод экрана (объекта Screen) PixelsPerInch — переводит пиксели в дюймы. А далее дюймы в мм: 1 дюйм равен 25.4 мм. Андрей, добавлено 5.08.11, 13:39:11
Здравствуйте. Как загрузить экселевский файл (или т.п.) в виде рисунка? В какой компонент не важно, просто основная цель загрузить док и наложить сверху еще несколько картинок с переменным положением (задаваемым вручную). Автор, добавлено 5.08.11, 14:49:22
Как вы это представляете? Дело в том, что экселевский файл это не рисунок, даже если и содержит рисунок. Что, нужно их экселевского файла средствами delphi выделить рисунок? Не проще ли сделать это ручками, достать рисунок, сохранить у себя и использовать? Автор, добавлено 5.08.11, 14:53:07
Можно ещё открыть программу Excel в рамках формы delphi, и попробовать наложить сверху другие рисунки. Здесь посмотрите: cyberforum.ru/delphi-beginners/thread274393-page2.html Данил, добавлено 6.09.11, 14:40:55
Можете показать что в итоге получается, плз! Автор, добавлено 6.09.11, 15:45:54
Это вы об чём? Данил, добавлено 6.09.11, 20:02:50
Я о програмке, ради которой создавалась эта страничка. Просто я написал все что выше изложено и никакого результата.Компилятор срабатывает без ошибок. Возможно я что то недопонимаю — я в delphi новичок. Автор, добавлено 7.09.11, 04:26:04
Теперь понял. Хорошо, в течение дня выложу архив с рабочим проектом. Автор, добавлено 7.09.11, 12:14:31
Данил, кстати, ваша проблема, видимо, в том, что вы просто все процедуры скопировали в проект, но не сопоставили с обработчиками событий компонентов. То есть у вас компоненты не привязаны к этим процедурам. Посмотрите, какие обработчики компонентов используются, щёлкните по ним в Инспекторе Объектов — появятся процедуры, которые могут им соответствовать. Тогда всё и заработает. Данил, добавлено 12.09.11, 07:02:39
Спасибо, помогло. нубчик, добавлено 12.09.11, 20:37:51
не работает у меня (( ошибки на page;clearing;prn;Memo1Change и прочее они же не заданы никак Автор, добавлено 12.09.11, 22:15:00
Да, подождите пару дней, я переделал пример, чтобы сразу всё было правильно.
А впрочем, прежде чем изучать графику, научитесь создавать процедуры, тогда поймёте как их задавать, чтобы они заработали. А пока просто добавьте в описание класса Формы, там где

type
TForm1 = class(TForm)

следующие строки вслед за procedure FormCreate(Sender: TObject);

procedure page;
procedure clearing;
procedure prn;
procedure Memo1Change(Sender: TObject);
procedure Edit1Change(Sender: TObject);
Данил, добавлено 13.09.11, 14:11:51
Доброго времени суток, Автор!
Если не сложно — подскажите пожалуйста. Пишу программку для печати пропусков. Возникла проблема с выводом на печать.
Разрешение принтера больше чем разрешение экрана. Я масштабировал изображение, но оно получилось очень нечетким. Как с этим бороться? Автор, добавлено 13.09.11, 16:01:20
Чтобы ответить, мне нужно »поковыряться», но принтера нет. Так что эту тему я плохо знаю, извините. Я, добавлено 13.10.11, 22:12:16
А как обозначить что принтер будет печатать? Автор, добавлено 13.10.11, 22:24:57
Что такое «обозначить»? Сделать сообщение, что сейчас начнётся печать? Или задать текст, который будет напечатан? Короче, не понял фразы. Я, добавлено 13.10.11, 22:29:22
Всмысле, какой компонент? Автор, добавлено 13.10.11, 22:32:59
Растолкуйте значение первой фразы, пожалуйста — что вы хотите уточнить. Автор, добавлено 13.10.11, 22:34:39
Принтер будет печатать то, что будет расположено между BeginDoc и EndDoc. Это обычное рисование методами канвы. Андрей, добавлено 7.11.11, 12:59:22
А как передать рисунок с одной формы на другую в Image Автор, добавлено 7.11.11, 13:13:38
Нет ничего проще.

Image1.Picture:=Form1.Image1.Picture; Олег, добавлено 14.02.12, 17:16:38
Здравствуйте автор. Прочел ваши рекомендации по поводу графики. Но решить свою проблему никак не могу, вот: вывести график функции, образованной сложением двух синусоид. Период одной в 5 раз больше периода другой. Из математики понимаю, что график будет в в виде синусоиды, только не плавные перегибы, а частотные на всем определении функции. Так же понимаю, что график будет лежать на канве и отсюда длина оси х и будет длина формы. Помогите разобрать эту задачу.

вот сумел сделать синусоиду, но без периода, вот код — работает!

procedure TForm1.FormPaint(Sender: TObject);
var
X,Y: real; // координаты функции
PX,PY: longint; // координаты пикселей
begin
Color:=clWhite;
Canvas.MoveTo(0,ClientHeight div 2);
for PX:=0 to ClientWidth do
begin
соответствующий пикселю с координатой РХ>
X := PX*4*Pi/ClientWidth;
Y := 2*Sin(X);
соответствующая координате Y>
PY := trunc(ClientHeight — (Y+1)*ClientHeight/2);
<Проводится линия на графике>
Canvas.LineTo(PX,PY);
end;
end;
Автор, добавлено 15.02.12, 00:05:18
С утра посмотрю. Автор, добавлено 15.02.12, 10:46:31
Всё написал, затем Касперский заблокировал работу и всё удалил. Вирус, видите ли, обнаружил! Повторяю:

Я бы проще делал. Сначала провёл бы координатную линию по оси Х: и засечки, соответствующие периоду в 2*Pi:

Canvas.MoveTo(0, Height div 2);
Canvas.LineTo(Width, Height div 2);
PX:=0;
Period:=2*Pi;
Yo:=Trunc(Height/2);
while PX
Затем строил бы график функции Y:=sin(X)+sin(X/5):

Canvas.MoveTo(0, Height div 2);
for PX:=0 to Width do
begin
Y := sin(Px)+sin(Px/5);
Py :=Yo-trunc(Y);
Canvas.LineTo(Px, Py);
end;

Но получается не график, а мазня — всё слишком мелко. Вводим масштаб, по Х в 20 раз, а по Y во все 100. И вот что получается:

procedure TForm1.FormPaint(Sender: TObject);
var X, Y: Real;
Period: Real;
Mx, My, Px, Py, Yo: Integer;
begin
Mx:=20; My:=100;
Canvas.MoveTo(0, Height div 2);
Canvas.LineTo(Width, Height div 2);
Canvas.MoveTo(0, Height div 2);
Period:=2*Pi*Mx;
Yo:=Trunc(Height/2);
for Px:=0 to Width do
begin
Y := sin(Px/Mx)+sin(Px/5/Mx);
Py :=Yo-trunc(Y*My);
Canvas.LineTo(Px, Py);
end;
X:=0;
Canvas.Pen.W >Canvas.Pen.Color:=clRed;
while X
Единственно, засечки перенёс вниз процедуры, выкрасил в красный цвет, и сделал потолще. кирилл , добавлено 28.02.12, 17:40:03
Добрый вечер,не могу доделать работу подскажите: необходимо чтобы окружность маленького радиуса двигалась по линиям семилучевой звезды. вот наработки мои:
procedure TForm3.a(Sender: TObject; var Key: Char);
begin
cc:=key; edit1.Text:=key;
end; //отвечает за управление процессом

procedure TForm3.s(Sender: TObject);
var x,y,r,j,i:word; B:array[1..360] of integer;G:array[1..360] of integer;
a:real;
begin
R:=200;
for i:=0 to 360 do
begin
if i mod 45=0 then
a:=(i*pi)/180 ;
x:=250+round(R*cos(a));
y:=250+round(R*sin(a));
b[i]:=x; g[i]:=y;
end;
canvas.MoveTo(b[45],g[45]);
canvas.LineTo(b[180],g[180]);
canvas.LineTo(b[315],g[315]);
canvas.LineTo(b[90],g[90]);
canvas.LineTo(b[225],g[225]);
canvas.lineto(b[360],g[360]);
canvas.LineTo(b[135],g[135]);
canvas.LineTo(b[270],g[270]);
canvas.LineTo(b[45],g[45]); //начертил семиугольник.
begin
form3.Color:=clnavy;
form3.KeyPreview:=true;
canvas.Pen.W >repeat
Application.processMessages;
canvas.Pen.Color:=clyellow;
canvas.ellipse(x,y,x+12,y+12);
sleep(5);
canvas.Pen.color:=clNavy;
Canvas.Ellipse(x,y,x+12,y+12) ; //пустил эллипс с одинаковыми радиусами по линиям. но вот это и не получается.
until cc=’q’; // клавиша q отвечает за конец операции иначе не остановить.

end;
end;
end. Автор, добавлено 28.02.12, 19:52:52
Через часок доберусь домой, посмотрю. Автор, добавлено 29.02.12, 06:59:28
Вот начертили вы семиугольник. Затем закрасили Форму синим. Каждый пиксел стал синим. И семиугольник что? — пропал. Форму красить сразу нужно, а затем семиугольник рисовать.

Далее. Рисуем эллипс.

canvas.Pen.W >repeat
Application.processMessages;
canvas.Pen.Color:=clyellow;
canvas.ellipse(x,y,x+12,y+12);
sleep(5);
canvas.Pen.color:=clNavy;
Canvas.Ellipse(x,y,x+12,y+12) ;
until cc=’q’;

a:=0; — зачем, где это используется?

Как будет движение осуществляться? Координаты же не меняются.

А как вы собираетесь вычислять каждый пиксел вашей звезды, чтобы эллипс по ней шёл? Это не констатация ошибки, просто интересно.

И красивее когда центр окружности движется по линии, а у вас угол квадрата, куда она вписана. Правильнее так:

А остановка движения. Через ввод символа в Edit. Естественнее ввести переменную

var Move: Boolean=False;

repeat
вычисления
until Move=False;

Ну и менять переменную нажатием кнопки:

Move:=not Move; кирилл, добавлено 29.02.12, 19:11:44
да,вначале красим форму синим, чертим семиугольник тоже синим, чтоб на форме его не было видно, потом запускаем окружность по заданной нам траектории семиугольника, остановка движения производится вводом символа q в эдит. Вот так.
но существует проблема, тот код который я написал не работает, он даже не чертит семиугольник. Нужно запускать цикл, точнее семь циклов для траектории, но я не знаю как это сделать. Автор, добавлено 1.03.12, 09:17:19
Да. Ваша фигура, естественно, не семилучевая, а восьмилучевая звезда. Для правильного её рисования нужно сместить begin на 1 строку вниз:

for i:=0 to 360 do
if (i mod 45) = 0 then
begin
a:=(i*pi)/180 ;
x:=250+round(R*cos(a));
y:=250+round(R*sin(a));
b[i]:=x; g[i]:=y;
end;
Автор, добавлено 1.03.12, 09:29:46
А дальше и в самом деле нужно 8 циклов, где окружность будет двигаться из угла в угол. Автор, добавлено 1.03.12, 16:11:26
И ещё. Я путём высоконаучных экспериментов выЯснил, что запустить эллипс в той же процедуре не получается. Введите таймер, и последним оператором в процедуре активируйте его. По каждому срабатыванию стирайте старый эллипс, меняйте координаты, рисуйте новый. кирилл, добавлено 10.04.12, 20:59:26
Создать массив из 8-ми объектов изображающих движение двух треугольников в пределах формы по случайным траекториям. пропорции и скорость движения выбираются на вкус. В программе предусмотреть алгоритм перехода от одного объекта к другому. т.е. создать радиогруппу из 8 радиокнопок и на каждую кнопку повесить различные по масштабу треугольники с различной скоростью движения. помогите не могу сообразить Автор, добавлено 10.04.12, 21:16:51
Мне всё понятно, за исключением объектов. Что это за объект, изображающий движение двух треугольников? Изобразить это можно например на компоненте Image. Ну, массив из 8 Image. При выборе радиокнопки один из Image видим, остальные нет. Может, так? кирилл, добавлено 11.04.12, 14:12:24
я если честно,тоже не все понимаю скорей всего это
type
poligon=object и ProcedureShow; ProcedureHide; Глеб, добавлено 14.04.12, 21:44:57
Добрый день!

Помогите мне в такой проблеме. Мне надо чтобы при запуске моей программы не было рамок формы! Я сам не знаю как это делать программно или в настройках есть такая опция. Дельфи 7 лайт Автор, добавлено 14.04.12, 21:58:01
Свойство Формы BorderStyle, значение bsNone. Я про это в первом же уроке написал. Можно и программно, по событию OnCreate, или сразу в Инспекторе Объектов. Глеб, добавлено 15.04.12, 14:58:11
Только вот есть одно дополнение) если ставить bsNone — то фору нельзя двигать по рабочему столу, а мне это нужно Автор, добавлено 15.04.12, 15:27:00
Нужно сделать функционал, который будет вычислять при нажатии левой клавиши мышки её координаты на Форме, и при последующем движении мышки поддерживать эти координаты постоянными:

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Xo:=X; Yo:=Y;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var dx, dy: Integer;
begin
dx:=X-Xo; dy:=Y-Yo;
if (ssLeft in Shift) then
begin
Left:=Left+dx;
Top:=Top+dy;
end;
end;

Xo и Yo — глобальные переменные. Олеся, добавлено 17.04.12, 19:09:00
Подскажите,пожалуйста,как работать с относительньіми координатами?чтоб изменяя размер формьі,размер рисунка тоже менялся.заранее спасибо! Автор, добавлено 17.04.12, 23:38:20
Canvas имеет такой метод как StretchDraw, который выводит рисунок в любой заранее определенный прямоугольник. Более развернуто, с примером, смогу ответить завтра к вечеру. Антон, добавлено 18.04.12, 17:14:11
Здравствуйте. Скажите пожалуйста, какими способами можно задавать цвета рисования в делфи.
Мне для решения задачи необходимо, что бы при повышении значения переменной x цвет точки на экране менялся по градиенту от зеленого к красному.
Спасибо. Антон, добавлено 18.04.12, 17:59:22
И еще, скажите каким образом нужно в делфи рисовать круг. Понятно, что при помощи функции ellipse, но у меня компилятор ругается на нее, выдавая следующую ошибку There is no overloaded version of ‘Ellipse’ that can be called with these arguments.
Что и где нужно ввести, что бы он понял меня? Автор, добавлено 18.04.12, 20:13:03
Что касается Ellipse, то что-то вы неправильно задали. Вот попробуйте просто:

Form1.Canvas.Ellipse(100, 100, 200, 200);

И всё нарисуется.Напишите ваш вариант, вместе посмотрим что не так.

А насчёт цвета, как выше написано, это целая величина, в 16-ричном виде $00BBGGRR. Самый красный цвет: $000000FF, самый зелёный: $0000FF00. Вот и делайте сумму двух переменных: green и red, где green будет постепенно уменьшаться от $0000FF00 до $00000000, а red постепенно увеличиваться от $00000000 до $000000FF. Для этого от green отнимайте $00000100, а к red прибавляйте $00000001. Но помните, что делать это можно не более $FF раз, то есть от 0 до 255. Вот как-то так:

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
red, green: Integer;
Color: TColor;
begin
Canvas.MoveTo(100, 100);
red:=$00000000;
green:=$0000FF00;
Color:=green;
with Canvas do
for i:=0 to 255 do
begin
red:=red+$00000001;
green:=green-$00000100;
Color:=red+green;
Pen.Color:=Color;
LineTo(200, 100+i);
MoveTo(100, 100+i+1);
end;
end;

Вначале цвет совсем зелёный, а в конце совсем красный. Поэтому можно выбрать диапазон изменения где-то посредине. Но здесь я не истина в последней инстанции, всё это только что придумал. Может, есть и более лучший вариант. Антон, добавлено 18.04.12, 20:23:25
Разобрался с проблемой по рисованию окружности.
Ну как разобрался. На ее месте тут же встала другая. Компилятор требует, что бы циферки в скобочках после ellipse были константами. Но меня это не устраивает, нужен тип хотя бы integer, а то и вовсе real. Как этого добиться?
Автор, добавлено 18.04.12, 20:28:18
Ну почему константами:

procedure TForm1.Button1Click(Sender: TObject);
var x1, y1, x2, y2: Integer;
begin
X1:=100; y1:=100;
X2:=200; y2:=200;
canvas.Ellipse(x1, y1, x2, y2);
end;

А вот насчёт Real вы загнули. Это же координаты в пикселах. Где вы видели нецелый пиксел? А если вы вычисляете некую формулу, то нужно округлять функцией Round. Антон, добавлено 18.04.12, 20:32:12
У меня на вот такую запись Image1.Canvas.Ellipse(x-6,y-6, x+6,y+6);
выдается вот такая ошибка Constant expression expected
Может я не понимаю, что она означает? Автор, добавлено 18.04.12, 20:43:01
Взял вашу строчку скопировал — ничего не выдаётся, рисуется кружочек. Антон, добавлено 18.04.12, 20:44:40
Если нужно, то вот полный текст программы

Read(F, x,y,radon);
case radon of
1..10: Image1.Canvas.Brush.Color:=clGreen;
11..20: Image1.Canvas.Brush.Color:=clYellow;
21..30: Image1.Canvas.Brush.Color:=clRed;
Image1.Canvas.Ellipse(x-6,y-6, x+6,y+6);
end;

end. Автор, добавлено 18.04.12, 21:00:27
Оператор case неправильно использовали. Перенесите

Image1.Canvas.Ellipse(x-6,y-6, x+6, y+6);

за end; Антон, добавлено 18.04.12, 21:06:14
Огромное спасибо, вы даже не подозреваете, насколько вы помогли (не только мне). Антон, добавлено 18.04.12, 21:09:21
Но оказывается мои мучения не закончились. Теперь проблема в чтении файла. У меня данные представлены в виде трех столбцов в файле txt по сути — просто 3 числа в строке. Когда программа считывает данные, как она это делает? (имеется в виду все три числа сразу или по одному?) Автор, добавлено 18.04.12, 21:20:02
Текстовый файл читается построчно. Лично я не заморачиваюсь и читаю текстовые файлы компонентами типа Memo, или создаю для этого StringList. Антон, добавлено 18.04.12, 22:05:34
Переделал с условием перевода строк в числа, и разбиения строки на три числа (пишутся через пробелы), но опять ругается на несовместимость типов.
while (not EOF(F)) do
begin
Read(F, s);
p:=pos(‘ ‘, s);
x:=StrToInt(copy(s, 1, p-1));
s:=delete(s, 1, p);
p:=pos(‘ ‘, s);
y:=StrToInt(copy(s, 1, p-1));
s:=delete(s, 1, p);
radon:=StrToInt(s);
case radon of
1..10: Image1.Canvas.Brush.Color:=clGreen;
11..20: Image1.Canvas.Brush.Color:=clYellow;
21..30: Image1.Canvas.Brush.Color:=clRed;
end;
Image1.Canvas.Ellipse(x-6,y-6, x+6,y+6);
end; Автор, добавлено 18.04.12, 22:14:51
Мне интересно, а то что вы прочитали в строку S, это и правда три числа, вы проверяли? Выведите в какой-нибудь компонент, я использую Form1.Caption для проверки что там такое. Антон, добавлено 18.04.12, 22:22:05
Пробовал только что. Я просто удалил все разбиение строки, добавил Memo и попытался записать строку туда. Программа зависла. Я специально вставил вместо Reset (оно было выше и в скопированный кусок не вошло) Rewrite. Но файл не перезаписался. То есть программа не дошла и до него. Тем не менее, текст который был на тот момент в Memo исчез. Что это за бред я не знаю. В файле лежат три строки по три числа. Ниже код. Антон, добавлено 18.04.12, 22:22:31
s:=delete(s, 1, pos(‘ ‘, s));
p:=pos(‘ ‘, s);
y:=StrToInt(copy(s, 1, pos(‘ ‘,s)-1));
s:=delete(s, 1, pos(‘ ‘, s));
radon:=StrToInt(s);
Антон, добавлено 18.04.12, 22:30:24
В этом коде программа ругается на несоответствие типов в процедурах delete
(Incompatible types: ‘String’ and ‘procedure, untyped pointer or untyped parameter’) Автор, добавлено 18.04.12, 22:39:16
ТщательнЕЕ надо. delete это не функция а процедура. Присвоение нужно убрать. И вообще, вместо чтения файла построчно, считайте файл в Memo целиком и читайте строки оттуда. Что-то меня смущают эти операции. Вроде как текстовый файл читается не Read а Readln. Аноним, добавлено 18.04.12, 22:52:29
Нннда, заработался видать. Преогромное вам спасибо, программа прекрасно работает. Еслибы не вы. в общем было бы очень плохо. Чуть позже я адаптирую эту программу под нужные условия и в дальнейшем она будет указывать на опасность возникновения оползня в том или ином районе. Аноним, добавлено 21.04.12, 16:03:44
Скажите, а как можно сохранить в памяти программы изображение нарисованное на Image?
Просто у меня при изменении размеров формы изменяются размери Image, соответствено рамку по краям и белый фон приходится прорисовывать заново, а значит изображение стирается. Я пробовал так
Picture:=Image1.Picture;
clearing;
page;
Image1.Picture:=Picture;
Но изображение не появляется.
И еще один ворпос: почему у меня при изменении размеров формы Image может увеличиваться только до определеного предела? В какой-то момент размеры формы продолжаюи изменяться, а размеры Image — нет, при этом исчезает граница (прорисована процедурой page) с той стороны, с которой происходило увеличение. Автор, добавлено 21.04.12, 16:30:09
А как изображение вообще в Image появляется? А если ещё раз так же как и в первый?
А насчёт размеров — напишите как вы изменяете размер, посмотрим. Аноним, добавлено 21.04.12, 16:47:43
Изображение считывается по некоторым данным из указанного мной файла. Считывание происходит по событию нажатия кнопки. Если сослаться на это нажатие, то считывание произойдет даже в том случае, если у меня Image чистая, тоесть при изменении размеров формы картинка появится в любом случае.
А вот код изменения размеров Image:
procedure TForm1.FormResize(Sender: TObject);
var picture : TPicture;
begin
Image1.Height := Form1.Height-130;
Image1.W >Image1.Left := 24;
Image1.Top := 16;
Picture:=Image1.Picture;
clearing;
page;
Image1.Picture:=Picture;
end; Автор, добавлено 21.04.12, 17:12:18
Понятно насчёт размеров. Вы бы не размер Image фиксировали, а расстояние до нижнего и правого краёв Формы. По событию OnCreate Формы вычисляли бы и потом изменяли бы ширину и высоту чтобы эти значения оставались постоянными. Тогда правый и нижний края Image не будут вылезать за правый и нижний края Формы. Аноним, добавлено 21.04.12, 17:19:11
Так они у меня и так не вылезают за края. У меня наоборот при определенном увеличении размеров формы Image перестает увеличиваться. Я собственно именно так и делаю, как вы предложили, за тем исключением, что расстояния до правого и нижнего краев у меня вычесленны не в коде программы, а заренее. Аноним, добавлено 21.04.12, 17:20:09
Если все равно не понятно, то скажите, куда можно выложить скрины программы. Автор, добавлено 21.04.12, 17:34:18
Понятно. Вернее непонятно. Но меня размер компонента меняется как угодно. Попробуйте в другом, тестовом проекте сделать процедуру изменения размеров, посмотрите в чём разница. Аноним, добавлено 21.04.12, 18:01:07
Пробовал и в других своих программах делать процедуру изменения размеров — то же самое. Что интересно: размер Image не превышает тех размеров, которые имел первоначально. И что самое главное: попытка увеличить его на форме (на этапе задания размеров) ни к чему не приводит. Аноним, добавлено 21.04.12, 18:12:56
Сделал как надо (правда через одно место, увеличив размеры Image еще на этапе редактированияя, затем развернул форму и свернул ее снова).
Тут возможны два варианта: либо глючность Delphi, либо ошибка в процедуре прорисовки рамки и белого фона (эту процедуру, кстати я безжалостно содрал из урока выше).
procedure TForm1.clearing;
begin
Rect.Left:=0;
Rect.Top:=0;
Rect.Right:=Image1.Width;
Rect.Bottom:=Image1.Height;
Image1.Canvas.Brush.Color:=clWhite;
Image1.Canvas.FillRect(Rect);
end;
Вот мне интересно: не из-за того ли проблема, что переменные Rect.Right Rect.Bottom
не меняются при повторном вызове процедуры? Автор, добавлено 21.04.12, 18:38:34
А! Да. И имидж у вас меняет размеры, только этого не видно. Ведь он не имеет собственных границ, и мы видим только то что нарисовано. Если размер имиджа меньше размера рисунка, то и будет обрыв. Так что меняйте Rect. Аноним, добавлено 21.04.12, 18:49:28
А вот нифига, похоже это глюки Делфи. Других объяснений я не вижу. Да, Image действительно меняет размеры, но вот прямоугольник хоть убейте не хочет прорисовываться больше чем начальные размеры Image.
Скажите, а вот эти две переменные: Image1.Width Image1.Height, они точно изменяются? Аноним, добавлено 21.04.12, 18:50:06
Хотя по идее должны, я же присваиваю им новые значения в зависимости от размеров формы. Автор, добавлено 21.04.12, 19:20:17
А вот выведите куда-нибудь значения размеров и посмотрите. А вообще Canvas имеют и другие компоненты, StringGrid например. Оставить одну ячейку и рисовать в ней, там Rect уже определён.
Глеб, добавлено 28.04.12, 18:40:22
Добрый день

Илон Маск рекомендует:  Iis справочник по перенаправлению

А можно в дельфи сделать форму не квадраную, а скажем с закругленными краями? Допусти чтобы при запуске программы отображалась форма в виде круга Автор, добавлено 28.04.12, 21:47:27
Да, это возможно. Но описывать создание регионов у меня желания нет. Хотите, погуглите сами: «создание регионов delphi». Глеб, добавлено 29.04.12, 13:26:00
procedure TForm1.FormShow(Sender: TObject);
var
frm: HRGN;
begin
frm := CreateRoundRectRgn(0, 0, form1.Width,form1.Height , 100 ,100);
SetWindowRgn(form1.Handle, frm, FALSE);
end;
end.

Вот пример прямоугольника с закругленными углами.
Автору спасибо за «ключ» поиска Олег, добавлено 10.05.12, 18:32:43
здравствуйте,помогите в такой проблеме необходимо создать движение квадратика по сложной хаотичной траектории и создать 5 радиокнопок изменяющие габариты ,цвет квадратика и скорость передвижения. вот движение по сложной траектории квадратика ,а как сделать радиокнопки и задать им св-ва я не знаю,помогите:
var
i , n , x,y,h,w: word;
a,b:real;
r,q,z:byte;
begin Randomize ; h:=form1.height; w:=form1.width;
button1.top:=h; form1.color:=clblack;
x:=300; y:=250;
form1.keypreview:=true; canvas.pen.w >repeat h:=random(200)+20; a:=random*8-4; b:=random*8-4;
r:=random(50)+40 ; g:=random(150);z:=random(256);
for i:=1 to n do begin application.processmessages;
x:=round(x+a*sin(i/20)+a/2); if (x>w)or(x h) or (b Автор, добавлено 11.05.12, 06:54:34
Пять радиокнопок это пять вариантов. Каждый вариант описывает свой набор свойств квадратика. Вот как выбрать вариант по нажатию радиокнопки. Каждой радиокнопке присваиваем свойство Tag от 1 до 5. Создаём ОДИН обработчик события OnClick для всех:

var Tag: Integer;
begin
Tag:=(Sender as TRadioButton).Tag;
case Tag of
1: atribut1;
2: atribut2;
3: atribut3;
4: atribut4;
5: atribut5;
end;
end;

atributN — процедуры, придающие квадратику тот или иной вид. Такой вариант более «культурен», чем просто

if Tag=1 then
begin
<Первый набор атрибутов>
end;
if Tag=2 then
begin
<Второй набор атрибутов>
end; и так далее, Впрочем, неважно, вам решать. олег , добавлено 11.05.12, 16:58:56
хм,а вы не могли бы показать мне хотя бы на одном примере как делать ,а я дальше по аналогии.буду благодарен Автор, добавлено 11.05.12, 17:40:42
Хорошо, но только завтра, согласны? Май! олег, добавлено 11.05.12, 17:54:34
ах..завтра сдавать..хорошо спасибо. Автор, добавлено 11.05.12, 18:22:14
Да чего показать-то. Как присвоить нескольким компонентам один обработчик? Как создать процедуры? Как присвоить квадратику соответствующие процедуры? Просто не вижу что может быть неясно. олег, добавлено 11.05.12, 18:53:02
неясно с чего начинать программу и чем заканчивать. и так же как присвоить квадратику процедуру. Автор, добавлено 11.05.12, 19:21:17
Утром после 9. Иосиф, добавлено 31.05.12, 20:26:55
ВСЕМ ПРИВЕТ, ПОМОГИТЕ ПОЖАЛУЙСТА ВСЕ ОБЛАЗИЛ НЕМОГУ НАЙТИ, КАК СДЕЛАТЬ, ЧТОБЫ КАРТИНКА НА ФОРМЕ АВТОМАТИЧЕСКИ ПОДСТРАИВАЛАСЬ, НА ВЕСЬ ЭКРАН МОНИТОРА, С ЛЮБЫМ РАЗШИРЕНИЕМ, А ТО НА МОЕМ 1024Х768 ОНА НА ВЕСЬ ЭКРАН, А НА ДРУГОМ НЕ НА ВЕСЬ ЭКРАН, СПАСИБО ВСЕМ КТО ПОМОЖЕТ Автор, добавлено 31.05.12, 22:51:19
Есть такой объект Screen, или Application.Screen, у него есть размеры экрана. Ну и рисуйте методом StretchDraw. Автор, добавлено 31.05.12, 22:57:14
А вы что к стати, рисуете по экрану? Если всё же по Форме, то вместо размеров экрана — размеры Формы. Илья, добавлено 9.10.12, 21:33:24
как осуществить перерисовку? рисую на форме Автор, добавлено 9.10.12, 21:45:35
Уточните, непонятно. Илья, добавлено 9.10.12, 22:00:26
что непонятно? при закрытие изображения другими окнами изображение исчезает, как от этого избавиться Автор, добавлено 9.10.12, 22:15:01
Получается, что после исчезновения изображения вследствие перекрытия его другими окнами, нужно прорисовать его ещё раз. Как? Так же как и первый раз. Анализируйте перекрытие, и выводите изображение. Илья, добавлено 9.10.12, 22:35:02
а в коде можно? я только начал разбираться вообще то с этой канвой, а вы мне уже «анализируйте перекрытие». поподробнее пжл Автор, добавлено 10.10.12, 06:59:29
Я не знаю как работает ваше приложение, каким образом перекрывается нарисованное изображение. Вы в программе должны увидеть, что произошло перекрытие, и тогда нарисовать его ещё раз. Ну или не рисуйте по Форме. Поставьте компонент Image, и всё. Автор, добавлено 10.10.12, 07:04:03
Или поставьте таймер, и рисуйте по его срабатыванию, например раз в секунду. Хотя это плохой совет, но будет работать. Юлия, добавлено 5.04.13, 22:23:54
Бльшое спасибо, очень пригодилось Шамурат туркменистан, добавлено 2.05.13, 14:33:31
Спасибо Михаил, добавлено 29.08.13, 22:16:59
Пока мало, что понимаю в DELPHI. Есть вопрос по работе с графикой. Как заставить мышь передвигая её по форме с координатной сеткой,рисовать линию вслед за этим считывать значения по какой-нибудь координатной оси. Спасибо. Автор, добавлено 30.08.13, 10:59:59
Пришлось чуток повозиться. Вот что получилось по рисованию линии (при нажатой левой кнопке мыши). На форме должен быть компонент Timer (в начальный момент выключенный) со значением Interval как можно меньше, я взял 10:

var
Form1: TForm1;
Xo, Yo, X1, Y1: Integer;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Image1.Canvas.MoveTo(Xo, Yo);
Image1.Canvas.LineTo(X1, Y1);
Xo:=X1;
Yo:=Y1;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Timer1.Enabled=False then
begin
Xo:=X;
Yo:=Y;
Timer1.Enabled:=True;
end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Timer1.Enabled:=False;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if X<>Xo then X1:=X;
if Y<>Yo then Y1:=Y;
end;
Михаил, добавлено 30.08.13, 18:57:28
Спасибо за оперативность буду пробовать Сергей, добавлено 10.12.13, 23:37:22
Здравствуйте, у меня на форме находится анкета в виде панели с эдитами, проблема в том, чтобы распечатать эту панель. Автор, добавлено 11.12.13, 05:32:40
У Формы есть метод Print, он распечатывает Форму со всем её содержимым. У компонента Panel такого метода нет. И если Форма не устраивает, то придётся рисовать всё содержимое панели на принтере. Аноним, добавлено 12.12.13, 01:58:15
Printer.BeginDoc;
Panel1.PaintTo(Printer.Handle, 10, 10);
Printer.EndDoc;
Как отмасштабировать? Автор, добавлено 12.12.13, 09:10:09
Метод PaintTo отрисовывает компонент как он есть, без масштабирования. Он не предназначен для собственно рисования, а только для перерисовки компонента в случае каких-либо изменений. Я в предыдущем ответе имел в виду не отрисовать панель, а нарисовать вручную её содержимое, методами MoveTo, LineTo.

Но можно попробовать сначала отмасштабировать панель методом ScaleBy — увеличить её размер на Форме, затем напечатать её на принтере, затем опять уменьшить панель. Как программа себя поведёт при этом, не могу сказать — принтера нет, попробовать не могу. Возможно, во время печати Форма исказится. Можно попробовать сделать панель невидимой, или перенести на другую Форму, невидимую или свёрнутую. Сергей, добавлено 13.12.13, 00:30:54
нашел как масштабировать:
Panel1.SetBounds(Panel1.Left, Panel1.Top, Printer.PageWidth, Printer.PageHeight);
теперь другая проблема, как отмасштабировать все компоненты на ней? Сергей, добавлено 13.12.13, 00:52:07
ну и через ScaleBy получилось:
Panel1.ScaleBy(100, 16);
только не все компоненты корректно отобразились; а можно это все вывести на предварительный просмотр в Fast Report? Автор, добавлено 13.12.13, 04:38:33
Можно, наверное. Но я с ФастРепортом дела не имел. Сергей, добавлено 14.12.13, 01:17:45
И на том большое спасибо) Майлз, добавлено 26.12.13, 18:36:38
Позвольте задать вопрос: а возможно ли получить цвет пикселя из стороннего изображения не отрисовывая его при этом? Автор, добавлено 26.12.13, 19:41:55
Пиксель это элемент канвы. Нужно создать битовую карту TBitMap — она имеет свойство Canvas, загрузить туда изображение, и исследовать пиксели. Майлз, добавлено 27.12.13, 09:21:39
Спасибо, разобрался! Филлип, добавлено 20.02.14, 23:41:26
Аноним, добавлено 21.04.12, 18:49:28
А вот нифига, похоже это глюки Делфи. Других объяснений я не вижу. Да, Image действительно меняет размеры, но вот прямоугольник хоть убейте не хочет прорисовываться больше чем начальные размеры Image.
Скажите, а вот эти две переменные: Image1.Width Image1.Height, они точно изменяются?
Аноним, добавлено 21.04.12, 18:50:06
Хотя по идее должны, я же присваиваю им новые значения в зависимости от размеров формы.
Автор, добавлено 21.04.12, 19:20:17
А вот выведите куда-нибудь значения размеров и посмотрите. А вообще Canvas имеют и другие компоненты, StringGrid например. Оставить одну ячейку и рисовать в ней, там Rect уже определён.
———————————
Вывел значения размеров — они меняются. Как быть? Филлип, добавлено 21.02.14, 00:09:02
О! Сам нашёл ответ:
При изменении размеров TImage размер его Canvas не меняется (Delphi)

Иногда возникает ситуация, когда необходимо в ходе выполнения программы изменить размеры компонента TImage, а потом на его холсте что-то нарисовать. Но все новые рисунки на холсте TImage ограничены старыми габаритами. Как это решить?

Необходимо вместе с размерами TImage изменить размеры его Bitmap.

Image1.Height := 80;
Image1.W >Image1.Picture.Bitmap.Height := 80;
Image1.Picture.Bitmap.W >
RelatedCommand line calculator on Rails — dentaku
In «Программирование»Как изменить стандартный crHandPoint на системный (Delphi)
In «Программирование»Кто вызвал PopupMenu? (Delphi)
In «Программирование»

Об авторе alvisx
Good muzhik.
Все записи автора alvisx »
:)

Функции Delphi

Стандартные функции Delphi:

Для проведения всевозможных математических вычислений и многочисленных преобразований язык программирования Delphi содержит библиотеки стандартных процедур и функций. Давайте подробнее рассмотрим стандартные функции Delphi.

Между значением и именем функции существует зависимость. Поэтому всякая функция может быть представлена как операнд некоторого выражения (к примеру, в инструкции присваивания). Для возведения числа в n-ую степень достаточно записать


откуда ln — функция, вычисляющая натуральный логарифм числа exp(x), exp — функция, вычисляющая экспоненту в степени x, x — число, n-ую степень которого надо найти, а n — степень числа x. Каждая функция обладает следующими характеристиками: тип значений, тип параметров.

Должно существовать соответствие между типом переменной (ей присваивается определенное значение функции) и типом функции. И в то же время необходимо соответствие между типом фактического параметра данной функции (фактический параметр — это параметр, который указывается при обращении к функции) и типом формального параметра. В противном случае компилятором выводится сообщение об ошибке.

Математические функции Delphi:

Библиотеки языка Delphi включаются в себя и множество математических функций:

Величину угла при использовании тригонометрических функций необходимо выражать в радианах. Чтобы преобразовать угол из градусов в радианы, используйте следующую формулу:

где a выражает угол в градусах; 3.1415926 означает число pi. На месте константы 3.1415926 с дробной частью для достижения большей точности чаще всего пользуются стандартной именованной константой pi. Тогда выражения для угла в пересчете в радианы будет выглядеть следующим образом:

Функции преобразования Delphi:

Наиболее частое использование функций преобразования связано с инструкциями, которые обеспечивают ввод/вывод какой-либо информации. Например, для вывода значения переменной c типом real в поле вывода диалогового окна (компонент Label), нужно провести преобразование числа в строку символов, которая собственно изображает данное число. Это можно достичь, применяя функцию FloatToStr, которая заменяет значение выражения (оно указано как параметр функции) его строковым представлением.

Пример.

В приведенном примере значение переменной m будете выведено в поле Label. В таблице ниже Вам будут представлены основные функции преобразования Delphi:

Применение функций Delphi:

В любом выражении функция используется как операнд. В качестве ее параметра можно выбрать переменную, константу, выражение определенного типа данных.

Примеры.

Структура функции Delphi

Как организована инструкция функции в языке Delphi? В любом языке программирования на первом этапе описания функции указывается ее заголовок. Далее за заголовком программист описывает раздел объявления констант const (если таковы имеются), затем занимается описанием раздела объявления типов type, далее следует раздел объявления переменных var и, наконец, раздел инструкций.

В приведенном примере в заголовке функции вначале указывается зарезервированное слово function, а следом идет имя функции. Далее в скобках программист перечисляет список параметров, и вслед за ним, используя символ «:», указывает тип значения функции. В конце каждого заголовка стоит символ «;». После заголовка следуют раздел констант, раздел типов, раздел переменных. Внутри раздела инструкций кроме констант и переменных, описанных соответственно в разделах const и var, может находится переменная result.

Когда инструкции функции завершат свое выполнение, значению переменной result присваивается значение функции. Таким образом, среди всех инструкций функций необходимое присутствие инструкции, которая бы присваивала переменной result окончательное значение функции. Обычно подобная инструкция есть последняя исполняемая инструкция функции. Представим пример функции FuntToKg, преобразующей фунты в килограммы.

Проверка попадания точки в прямоугольник (TPoint в TRect)

Delphi , Графика и Игры , Графика

Статья Проверка попадания точки в прямоугольник (TPoint в TRect) раздела Графика и Игры Графика может быть полезна для разработчиков на Delphi и FreePascal.

Комментарии и вопросы

Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.

DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники

Графические возможности Delphi: Дуга, прямоугольник, сектор, точка

Дуга

Вычерчивание дуги выполняет метод Arc, инструкция вызова которого вобщем виде выглядит следующим образом:

  • xl, yl, х2, у2 — параметры, определяющие эллипс (окружность), частью которого является вычерчиваемая дуга;
  • хЗ, уз — параметры, определяющие начальную точку дуги;
  • х4, у4 — параметры, определяющие конечную точку дуги.

Начальная (конечная) точка — это точка пересечения границы эллипса и прямой, проведенной из центра эллипса в точку с координатами хЗ и уз (х4, у4). Дуга вычерчивается против часовой стрелки от начальной точки к конечной <рис. 10.7).

Цвет, толщина и стиль линии, которой вычерчивается дуга, определяются значениями свойства Реп поверхности (canvas), на которую выполняется вывод.

Рис. 1О.7. Значения параметров метода Arc определяют дугу как часть эллипса (окружности)

Прямоугольник

  • Объект — имя объекта (компонента), на поверхности которого выполняется вычерчивание;
  • x1, y1 и y2, у2 — координаты левого верхнего и правого нижнего углов прямоугольника.

Метод RoundRec тоже вычерчивает прямоугольник, но со скругленными углами. Инструкция вызова метода RoundRec выглядит так:

  • x1, y1, х2, у2 — параметры, определяющие положение углов прямоугольника, в который вписывается прямоугольник со скругленными углами;
  • хЗ и уЗ — размер эллипса, одна четверть которого используется для вычерчивания скругленного угла (рис. 10.8).

Рис. 10.8. Метод RoundRec вычерчивает прямоугольник со скругленными углами

Вид линии контура (цвет, ширина и стиль) определяется значениями свойства реп, а цвет и стиль заливки области внутри прямоугольника — значениями свойства Brush поверхности (canvas), на которой прямоугольник вычерчивается.

Есть еще два метода, которые вычерчивают прямоугольник, используя в качестве инструмента только кисть (Brush). Метод FiliRect вычерчивает закрашенный прямоугольник, а метод FrameRect — только контур. У каждого из этих методов лишь один параметр — структура типа TRect. Поля структуры TRect содержат координаты прямоугольной области, они могут быть заполнены при помощи функции Rect.

Ниже в качестве примера использования методов FillRect и FrameRect приведена процедура, которая на поверхности формы вычерчивает прямоугольник с красной заливкой и прямоугольник с зеленым контуром.

Многоугольник

Метод polygon вычерчивает многоугольник. В качестве параметра методполучает массив типа TPoint. Каждый элемент массива представляет собой запись, поля (х,у) которой содержат координаты одной вершины многоугольника. Метод Polygon вычерчивает многоугольник, последовательносоединяя прямыми линиями точки, координаты которых находятся в массиве; первую со второй, вторую с третьей, третью с четвертой и т. д. Затемсоединяются последняя и первая точки.

Цвет и стиль границы многоугольника определяются значениями свойстваРеп, а цвет и стиль заливки области, ограниченной линией границы, — значениями свойства Brush, причем область закрашивается с использованиемтекущего цвета и стиля кисти.

Ниже приведена процедура, которая, используя метод polygon, вычерчиваеттреугольник:

Сектор

Метод Pie вычерчивает сектор эллипса или круга. Инструкция вызова метода в общем виде выглядит следующим образом:

  • x1, y1, х2, у2 — параметры, определяющие эллипс (окружность), частью которого является сектор;
  • хЗ, уЗ, х4, у4 — параметры, определяющие координаты конечных точек прямых, являющихся границами сектора.
Илон Маск рекомендует:  10 самых лучших пользовательских функций javascript за все времена

Начальные точки прямых совпадают с центром эллипса (окружности). Сектор вырезается против часовой стрелки от прямой, заданной точкой с координатами (хЗ, уз), к прямой, заданной точкой с координатами (х4, у4) (рис. 10.9).

Рис. 1О.9. Значения параметров метода Pie определяют сектор как часть эллипса (окружности)

Точка

Поверхности, на которую программа может осуществлять вывод графики,соответствует объект canvas. Свойство Pixels, представляющее собой двумерный массив типа TColor, содержит информацию о цвете каждой точки графической поверхности. Используя свойство Pixels, можно задать требуемый цвет для любой точки графической поверхности, т. е. «нарисовать» точку.

Например, инструкция:

окрашивает точку поверхности формы в красный цвет.

Размерность массива Pixels определяется размером графической поверхности. Размер графической поверхности формы (рабочей области, которую также называют клиентской) задается значениями свойств clientwidth и clientHeight, а размер графической поверхности компонента image — значениями свойств width и Height. Левой верхней точке рабочей области формы соответствует элемент pixels [о, о], а правой нижней —Pixels[Clientwidth — 1,ClientHeight — 1].

Свойство Pixels можно использовать для построения графиков. График строится, как правило, на основе вычислений по формуле. Границы диапазона изменения аргумента функции являются исходными данными. Диапазон изменения значения функции может быть вычислен. На основании этих данных можно вычислить масштаб, позволяющий построить график таким образом, чтобы он занимал всю область формы, предназначенную для вывода графика.

Например, если некоторая функция f(x) может принимать значения от нуля до 1000, и для вывода ее графика используется область формы высотой в 250 пикселов, то масштаб оси у вычисляется по формуле: т = 250/1000. Таким образом, значению/(х) = 70 будет соответствовать точка с координатой Y= 233. Значение координаты вычислено по формуле

Y=h-f(x)x m = 250 — 70х(250/1000),

где h — высота области построения графика.

Обратите внимание на то, что точное значение выражения

250 — 70х(250/1000) равно 232,5.

Но т. к. индексом свойства Pixels, которое используется для вывода точки на поверхность canvas, может быть только целое значение, то число 232,5 округляется к ближайшему целому, которым является число 233.

Следующая программа, текст которой приведен в листинге 10.5, используя свойство Pixels, выводит график функции у = 2 sm(x) e^5. Для построения графика используется вся доступная область формы, причем если во время работы программы пользователь изменит размер окна, то график будет выведен заново с учетом реальных размеров окна.

Использование замыканий и функций высших порядков в Delphi

Данная статья является продолжением предыдущей публикации, которая была посвящена анонимным методам. В этот раз речь пойдет о примерах использования функций высших порядков и замыканий, показавшихся автору интересными.

Delphi не является языком функционального программирования, но тот факт, что программы на нем могут манипулировать функциями как объектами означает, что в Delphi можно использовать приемы функциональной парадигмы. Цель статьи — не подтолкнуть к использованию этого стиля, но обозначить некоторые примеры и возможности.

Конструирование функций

Функции высшего порядка (ФВП) – это функции, которые оперируют функциями, принимая одну или более функций и возвращая новую функцию.
Следующий пример показывает, как с помощью ФВП можно конструировать другие функции.

Функция Negate в примере выше, является ФВП, потому что она принимает функцию IsOdd в виде аргумента и возвращает новую функцию IsEven, которая передает свои аргументы Negate и возвращает логическое отрицание значения, возвращаемого функцией IsOdd.

Так как использование обобщенных типов не способствует ясности изложения, в последующих примерах будем по возможности их избегать.

Композиция функций

Ниже приводится пример еще одной, более универсальной функции, которая принимает две функции, F и G, и возвращает новую функцию, которая возвращает результат F(G()).

Здесь функция Compose вычисляет F(G(X, Y)). Возвращаемая функция передает все свои аргументы функции G, затем передает значение, полученное от G, функции F и возвращает результат вызова F.

Частичное применение

Этот термин описывает преобразование функции с несколькими аргументами в функцию, которая принимает меньшее количество аргументов, при этом значения для опущенных аргументов задаются заранее. Этот прием вполне адекватен своему названию: он «частично применяет» некоторые аргументы функции, возвращая функцию, принимающую остающиеся аргументы.
Функция BindLeft в примере ниже берет функцию Calc, принимающую n аргументов, связывает первые k из них с наперед заданными значениями и возвращает функцию Partial, которая может принять (n-k) аргументов (первые k аргументов будут уже применены к ней).

Здесь интересен момент, когда после вызова BindLeft локальная переменная StoredArgs не прекращает свое существование и используется далее, сохраняя в себе значения аргументов, которые потом используются при вызове Partial и передаются в Calc. Этот эффект называется замыканием. При этом каждый вызов BindLeft будет порождать новые «экземпляры» StoredArgs. Замыкания использовались и в предыдущих примерах, когда в них сохранялись аргументы ФВП.
Определить частичное применение справа можно следующим образом:

Карринг

В то время как частичное применение преобразует функцию с n параметрами в функцию с n-k параметрами, применяя k аргументов, карринг декомпозирует функцию на функции от одного аргумента. Мы не передаем никаких дополнительных аргументов в метод Curry, кроме преобразуемой функции:

  • Curry(F) возвращает функцию F1, такую что.
  • F1(A) возвращает функцию F2, такую что.
  • F2(B) возвращает функцию F3, такую что.
  • F3(С) вызывает F(A, B, C)
Мемоизация

Мемоизованная функция — это функция, которая сохраняет ранее вычисленные результаты. Другими словами, для функции создаётся таблица результатов, и, будучи вычисленным при определённых значениях параметров, результат заносится в эту таблицу. В дальнейшем результат берётся из данной таблицы. Эта техника позволяет за счёт использования дополнительной памяти ускорить работу программы. Разумеется, мемоизируемая функция должна работать без побочных эффектов и ей желательно иметь дискретную область определения.
В следующем примере демонстрируется функция Memoize высшего порядка, которая принимает функцию в виде аргумента и возвращает ее мемоизованную версию.

Функция Memoize создает объект TCache для использования в качестве кэша и присваивает его локальной переменной, благодаря чему он остается доступным (через замыкание) только для возвращаемой функции. Возвращаемая функция преобразует свой аргумент в ключ. Если значение присутствует в кэше, оно просто возвращается в качестве результата. В противном случае вызывается оригинальная функция, вычисляющая значение для заданного аргумента; полученное значение помещается в кэш и возвращается.

Программа с мемоизованной функцией, периодически вызываемой с одинаковыми аргументами, должна выполняться быстрее, чем аналогичная программа без применения мемоизации. Проверим разницу:

Генераторы

Здесь под генератором понимается ФВП, которая возвращает функцию, вызов которой приводит к получению следующего члена некоторой последовательности. В примере ниже создаются два генератора: для последовательности Фибоначчи и генератор факториалов. Предыдущие элементы генераторов запоминаются в замыкании.

Польза генераторов заключается в том, что для вычисления каждого следующего элемента не требуется вычислять всю последовательность с самого начала. Генераторы позволяют работать даже с бесконечными последовательностями, но они обеспечивают только последовательный доступ к своим элементам и не позволяют обращаться к своим элементам по индексу: чтобы получить n-e значение придется выполнить n-1 итераций.

Отложенные вычисления

Генераторы бывает удобно использовать для последовательной обработки данных — элементов списка, строк текста, лексем в лексическом анализаторе и т.д. Генераторы можно объединять в цепочки, подобно конвейеру команд в Unix. Самое интересное в этом подходе заключается в том, что он следует принципу отложенных вычислений: значения «извлекаются» из генератора (или из конвейера) по мере необходимости, а не все сразу. Эту особенность демонстрирует следующий пример, в котором исходный текст фильтруется, построчно проходя через цепочку генераторов.

Справочник по компонентам Delphi. Часть 1

Written on 15 Сентября 2006 . Posted in Delphi

ОГЛАВЛЕНИЕ

Класс TCanvas

Этот класс — сердцевина графической подсистемы Delphi. Он объединяет в себе и «холст» (контекст конкретного устройства GDI), и «рабочие инстру­менты» (перо, кисть, шрифт) и даже «подмастерьев» (набор функций по рисованию типовых геометрических фигур).

В дальнейшем для обозначения этого класса мы будем пользоваться термином «канва». Сознавая неоднозначность такого перевода, авторы тем не менее считают, что у него наилучшие шансы прижиться.

Канва не является компонентом, но она входит в качестве свойства во многие другие компоненты, которые должны уметь нарисовать себя и отобразить какую-либо информацию.

Дескриптор контекста устройства, над которьм «построена» канва, может быть востребован для различных низкоуровневых операций. Он задается свой­ством:

Для рисования канва включает в себя шрифт, перо и кисть:

Кроме того, можно рисовать и поточечно, получив доступ к каждому пикселу. Значение свойства

соответствует цвету точки с координатами (X,Y).

Канва содержит методы-надстройки над всеми основными функциями рисования GDI Windows и свойства, которые приведены ниже в таблице. При их рассмотрении имейте в виду, что все геометрические фигуры рисуются текущим пером. Те из них, которые можно закрашивать, закрашиваются с помощью текущей кисти. Кисть и перо при этом имеют текущий цвет.

procedure Arc (XI, Yl, Х2, Y2, ХЗ, Y3, Х4, Y4: Integer) ; Метод рисует сегмент эллипса. Эллипс определяется описывающим прямоуголь­ником (X1,Y1) — (X2,Y2); его размеры должны лежать в диапазоне от 2 до 32767 точек. Начальная точка сегмента лежит на пересечении эллипса и луча, проведенного из его центра через точку (X3.Y3). Конечная точка сегмента лежит на пересечении эллипса и луча, проведенного из его центра через точку (X4.Y4). Сегмент рисуется против часовой стрелки.
procedure Chord(Xl, Yl, Х2, Y2, ХЗ, Y3, Х4, Y4: Integer); Рисует хорду и заливает отсекаемую ею часть эллипса. Эллипс, начальная и конеч­ная точки определяются, как в методе Arc.
procedure EllipsefXl, Yl, Х2, Y2: Integer) ; Рисует и закрашивает эллипс, вписанный в прямоугольник (X1.Y1) — (X2.Y2).
procedure LineTo(X, Y: Integer); Проводит линию текущим пером из текущей точки в (X,Y).
procedure MoveTo(X, Y: Integer); Перемещает текущее положение пера (свойство PenPos) в точку (X,Y).
procedure BrushCopy(const Dest: TRect; Bitmap: TBitmap; const Source: TRect; Color: TColor); Производит специальное копирование. Прямоугольник Source из битовой карты Bitmap копируется в прямоугольник Dest на канве; при этом цвет Color заменяется на цвет текущей кисти (Brush.Color). С помощью этого метода можно нарисо­вать «прозрачную» картинку. Для этого нужно выбрать соответствующий фону цвет кисти и затем заменить на него фоновый или наиболее часто встреча­ющийся цвет битовой карты (см. Bitmap. TransparentColor).
procedure CopyRect(const Dest: TRect; Canvas: TCanvas; const Source: TRect) ; Производит копирование прямоугольника Source из канвы Canvas в прямоугольник Dest в области самого объекта.
procedure FillRect(const Rect: TRect) ; Производит заливку прямоугольника (текущей кистью).
procedure FrameRectfconst Rect: TRect); Производит оконтуривание прямоуголь­ника цветом текущей кисти (без заполнения).
procedure Draw(X, Y: Integer; Graphic: TGraphic) ; Осуществляет рисование графического объекта Graphic (точнее, вызов метода его рисования) в области с верхним левым углом (X,Y).
procedure StretchDraw(const Rect: TRect; Graphic: TGraphic); Осуществляет рисование объекта Graphic в заданном прямоугольнике Rect. Если размеры их не совпадают, Graphic масштабируется.
procedure DrawFocusRect(const Rect: TRect); Производит отрисовку прямоугольной рамки из точек (как на элементе, имеющем фокус ввода). Поскольку метод использует логическую операцию XOR (исключающее ИЛИ), повторный вызов для того же прямоугольника приводит изображение к начальному виду.
procedure FloodFilKX, Y: Integer; Color: TColor; FillStyle: TFillStyle); TFillStyle = (fsSurface, fsBorder) ; Производит заливку области текущей кистью. Процесс начинается с точки (X,Y). Если режим FillStyle равен fsSurface, то он продолжается до тех пор, пока есть соседние точки с цветом Color. В режиме fsBorder закрашивание, наоборот, прекращается при выходе на границу с цветом Color.
procedure Pie (XI, Yl, Х2, Y2, ХЗ, Y3, Х4, Y4: Integers- Рисует сектор эллипса, описываемого прямоугольником (X1,Y1) — (X2,Y2). Стороны сектора лежат на лучах, проходящих из центра эллипса через точки (X3.Y3) и (X4,Y4).
procedure Polygon(const Points: array of TPoint) ; Строит многоугольник, используя массив координат точек Points. При этом последняя точка соединяется с первой и внутренняя область закрашивается.
procedure Polyline(const Points: array of TPoint) ; Строит ломаную линию, используя массив координат точек Points.
procedure Rectangle(XI, Yl, Х2, Y2 : Integer) ; Рисует прямоугольник с верхним левым углом в (XI ,Y1) и нижним правым в (X2.Y2).
procedure RoundRect (XI, Yl, Х2, Y2, ХЗ, Y3: Integer); Рисует прямоугольник с закругленными углами. Координаты вершин — те же, что и в методе Rectangle. Закругления рисуются как сегменты эллипса с размерами осей по горизонтали и вертикали ХЗ и Y3.
function. TextHeight(const Text: string): Integer; Возвращает высоту строки Text в пикселах.
function TextWidth(const Text: string): Integer; Возвращает ширину строки Text в пиксе­лах.
procedure TextOut(X, Y: Integer; const Text: string); Производит вывод строки Text. Левый верхний угол помещается в точку канвы (X,Y).
procedure TextRect(Rect: TRect; X, Y: Integer; const Text: stringi ; Производит вывод текста с отсечением. Как и в TextOut, строка Text выводится с позиции (X,Y); при этом часть текста, лежащая вне пределов прямоугольника Rect, отсекается и не будет видна.
(Ro) property ClipRect: TRect; Определяет область отсечения канвы. То, что при рисовании попадает за пределы этого прямоугольника, не будет изображено. Свойство доступно только для чтения — его значение переустанавливается системой в контексте устройства канвы.
property PenPos: TPoint; Содержит текущую позицию пера канвы (изменяется посредством метода MoveTo).

сбрасывает текущие шрифт, перо и кисть, заменяя их на стандартные, заимство­ванные из Windows (BLACK.PEN, HOLLOW_BRUSH, SYSTEM.FONT).

Предусмотрено два события для пользовательской реакции на изменение канвы:

Эти события возникают при изменениях свойств и вызовах методов TCanvas, меняющих вид канвы (то есть при любом рисовании. В MoveTo, например, они не возникают). Отличие их в том, что OnChanging вызывается до начала изменений, a OnChange — после их завершения.

Идентификатор (код) растровой операции при копировании прямоугольных блоков содержится в свойстве

и определяет правило сочетания пикселов, копируемых на канву, с ее текущим содержимым. При этом можно создавать разные изобразительные эффекты. В Delphi определены следующие константы кодов: cmBlackness, cmDstInvert, cmMergeCopy, cmMergePaint, cmNotSrcCopy, cmNotSrcErase, cmPatCopy, cmPatInvert, cmPatPaint, cmSrcAnd, cmSrcCopy, cmSrcErase, cmSrcInvert, cmSrcPaint, cmWhiteness.

Все они стандартно определены в Windows, и подробное их описание можно найти в документации по GDI. Значением CopyMode по умолчанию является cmSrcCopy — копирование пикселов источника поверх существующих.

Использование графики иллюстрируют несколько примеров, имеющихся на дискете, прилагаемой к книге. Обратите внимание на пример MOVLINES — в нем показано, как создавать и использовать канву для всего экрана. Помимо графических примитивов, таких как линии и фигуры, на канве можно разместить готовые изображения. Для их описания создан класс TGraphic.

Почему такие функции, как «Точка» / «Rect» / «Bounds» (и т.д.), Объявленные как в классах, так и в единицах типов?

Я заметил, что в Delphi 7 функции, такие как Point / Rect / Bounds (и т.д.) объявляются и реализуются как в Classes , так и в системном Types .

Есть ли причина для этого? это также верно для более новых версий Delphi?

(Мое предположение заключается в том, что можно использовать блок Types , чтобы избежать необходимости Classes при необходимости)

В старых версиях эти типы и функции были объявлены в Classes . Поскольку RTL был разработан, особенно для поддержки кросс-платформенных, стало желательным, чтобы эти типы были доступны единицам, которые не включали Classes .

Для этого был введен блок Types . Блок Types не имеет зависимостей uses , поэтому его можно безопасно использовать любым другим устройством, независимо от того, насколько низкий уровень.

Основные декларации были перенесены на Types , а Classes повторно экспортировать эти типы и функции в пользу существующего кода, который импортирует из Classes . Так, например, SysUtils использует Types , но не разрешено использовать Classes . Перемещение этих типов и функций в модуль без зависимостей, такой как Types , позволяет это.

Это изменение было сделано между Delphi 5 и Delphi 6, что стало началом кросс-платформенных разработок Delphi. В этом случае это был Kylix, но реструктуризация RTL принесла пользу будущим кросс-платформенным разработкам, хотя Kylix был оставлен.

Процедуры RoundRect, DrawRoundRect, FillRoundRect

Снова здравствуйте, посетители сайта о программировании на паскале для начинающих! На этой странице мы рассмотрим построение прямоугольников со скругленными краями с помощью процедур RoundRect, DrawRoundRect и FillRoundRect, в отличие от предыдущего материала, где мы разобрали построение обычных прямоугольников без скругления.

В зависимости от того какой прямоугольник со скругленными краями вам нужен – залитый с границей, незалитый с границей или залитый без границы, – вы можете использовать соответственно процедуры RoundRect, DrawRoundRect или FillRoundRect, поскольку в разных задачах свои требования. Но обо всем по порядку, и начнем с определения первой подпрограммы.

Процедура RoundRect

procedure RoundRect(x1,y1,x2,y2,w,h: integer);

— Рисует заполненный прямоугольник со скругленными краями; (x1,y1) и (x2,y2) задают пару противоположных вершин, а w и h – ширину и высоту эллипса, используемого для скругления краев

Прямоугольник, нарисованный с помощью RoundRect , имеет границу и заливку, поэтому границе можно придать цвет и толщину, а область самого прямоугольника разукрасить в определенный цвет. Вот как это делать в программе.

Причем для простого вывода прямоугольника использовать переменные x1, y1, x2, y2, w, h не обязательно – вместо них можно вставить сами их значения в процедуру.

Процедура DrawRoundRect

procedure DrawRoundRect(x1,y1,x2,y2,w,h: integer);

— Рисует границу прямоугольника со скругленными краями; (x1,y1) и (x2,y2) задают пару противоположных вершин, а w и h – ширину и высоту эллипса, используемого для скругления краев

Эта процедура отсутствует в простом PascalABC, поэтому будем запускать среду PascalABC.Net. Обратим внимание, что DrawRoundRect рисует только границу скругленного прямоугольника, но не заливает его, поэтому использовать кисть Brush для заливки не имеет смысла, поскольку она не сработает.

Процедура FillRoundRect

procedure FillRoundRect(x1,y1,x2,y2,w,h: integer);

— Заполняет внутренность прямоугольника со скругленными краями; (x1,y1) и (x2,y2) задают пару противоположных вершин, а w и h – ширину и высоту эллипса, используемого для скругления краев

Последняя процерура FillRoundRect выводит на экран заполненный прямоугольник со скругленными краями, но без границы, поэтому в определении и сказано, что не рисует, а заполняет внутренность. В этом случае перо Pen использовать для толщины и цвета границы не имеет смысла, ведь никакой границы нет.

Вот похожие темы:

На этом пока все. А пока можете посмотреть онлайн сервис для легкой сдачи отчетности medoc online, который помогает отправлять отчеты из браузера в режиме онлайн.

Позже я добавлю сюда некоторые интересные задачи с применением скругленных прямоугольников. Если у вас есть какие-то идеи, то пишите в комментариях.

TRect.Intersect and TRect.IntersectsWith Inconsistencies

I am hoping that I am confused in some way. I am getting some inconsistent behavior with TRect.Intersect and TRect.IntersectsWith . Here is some code that demonstrates the problem.

The second exception is raised. TRect.IntersectsWith indicates that the rects intersect but when I call TRect.Intersect to get the new intersected rect then it returns an empty rect.

The code in IntersectsWith (which isn’t written very clearly) is returning true in the second case because Self.BottomRight.Y = R.TopLeft.Y (100).

The problem is that IsRectEmpty which is called by Intersect checks to see if either the top and bottom of the rect or the left and right of the rect have the same values and when that passes Intersect sets the result to an empty rect.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL