Когда пользователь нажимает кнопку мыши, программа проверяет, есть ли незавершенная кривая. Если таких кривых нет, начинается создание новой кривой. До тех пор. пока пользователь не отпустит кнопку мыши, рисуется резиновая прямая. Эта прямая становится заготовкой для новой незавершенной кривой.
Если в момент нажатия кнопки мыши незавершенная кривая уже существует, координаты мыши сравниваются с координатами опорных и концевых точек и, если они оказываются достаточно близки к одной из них, дальнейшее перемещение мыши (при удерживании кнопки) приводит к перемещению соответствующей точки и перерисовке кривой в новом положении. Изменение типа линии и/или способа построения отражается на незавершенной кривой — она немедленно перерисовывается в соответствии с новыми параметрами.
При нажатии кнопки Завершить незавершенная кривая рисуется уже не на самой форме, а на растре, содержащем фон. После этого кривая перестает существовать как кривая и становится набором пикселов на фоновой картинке, а программа вновь переходит в режим, когда нажатие кнопки мыши интерпретируется как создание новой кривой.
Реализацию интерактивной кривой в данном случае иллюстрирует листинг 1.61.
const
// чтобы перемещать точку кривой, пользователь должен попасть мышью
// в некоторую ее окрестность. Константа RectSize задает размер этой
// окрестности
RectSize = 3;
type
// Тип TDragPoint показывает, какую точку перемещает пользователь:
// ptNone — пользователь пытается тянуть несуществующую точку
// ptFirst — пользователь перемещает вторую точку "резиновой" прямой
// ptBegin — пользователь перемещает начало кривой
// ptInter1, ptInter2 — пользователь перемещает промежуточные точки
// ptEnd — пользователь перемещает конец кривой
TDragPoint = (dpNone, dpFirst, dpBegin, dpInter1, dpInter2, dpEnd);
TCurveForm = class(TForm)
BtnEnd: TButton;
RGroupType: TRadioGrour;
RGroupDrawMethod: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure FomMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormPaint(Sender: TObject);
procedure BtnEndClick(Sender: TObject);
procedure RGroupTypeClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
// Если FNewLine = True, незавершённых кривых нет, и при нажатии на
// кнопку мыши начинает рисоваться новая кривая.
// Если FNewLine = False, есть незавершенная кривая, и нажатия мыши
// интерпретируются как попытки ее редактирования
FNewLine: Boolean;
// Поле FDragPoint указывает, какую точку перемещает пользователь
FDragPoint: TDragPoint;
// Поле FCurve хранит координаты незавершенной кривой
FCurve: TCurve;
// FBack — фоновый рисунок с завершенными кривыми
FBack: TBitmap;
// FCounter — счетчик точек, использующийся при рисовании отрезков
// с помощью LineDDA
FCounter: Integer;
// FDX, FDY — смещения относительно координаты точки кривой для
// рисования поперечной полосы
FDX, FDY: Integer;