Программирование в delphi реализация undo redo в графическом редакторе? Пример кода достаточно 5 изменений.

программирование Delphi делфи

Нашел в интернете вот это но как это реализовать не пойму.
(Нестандартный способ решения задачи применён и к алгоритму отмены и повтора действий пользователя. Создан специальный класс TBmpMemory, который хранит изображения в памяти. После каждого действия, будь то рисование прямоугольника или увеличение контрастности, изображение сохраняется в отдельной ячейке (Cell) динамического массива, длина которого равна числу возможных отмен + 1. Данный массив представляет собой двусвязный список. Тип каждой ячейки определён следующим образом:
PBitmapCell = ^TBitmapCell;
TBitmapCell = record
NextCell: PBitmapCell; // указатель на следующую ячейку
PrevCell: PBitmapCell; // указатель на предыдущую ячейку
Bitmap: TBitmap;
end;
Таким образом, каждый элемент списка имеет указатель на предыдущий и на следующий элемент. Указатель PrevCell первой ячейки указывает на последнюю, а указатель NextCell последней ячейки указывает на первую ячейку. Получается замкнутое кольцо без входа и выхода. Это сделано по той причине, что после отмены действия, для восстановления требуется то изображение, которое было отменено. Например: пользователь нарисовал круг, а затем линию. В первой ячейке записано изображение, которое было до рисования круга, во второй - после рисования круга, а в третьей - после рисования линии. После отмены последнего действия указатель перемещается на предыдущую ячейку (ячейка с кругом, но без линии):
procedure TBmpMemory.Undo(Bitmap: TBitmap);
begin
if CanUndo then begin
Dec(FNumUndo); //уменьшаем число возможных отмен
Bitmap.Assign(FActiveCell^.Bitmap); //передаём изображение с активной ячейки
FActiveCell := FActiveCell^.PrevCell;//переносим указатель на предыдущую ячейку
end;
end;
Если же пользователь передумал и решил вернуть нарисованное, то он может вызвать повтор последнего отменённого действия (если после отмены ничего не было сделано):
procedure TBmpMemory.Redo(Bitmap: TBitmap);
begin
if CanRedo then begin
Inc(FNumUndo); //увеличиваем число возможных отмен
FActiveCell := FActiveCell^.NextCell; //переносим указатель на следующую ячейку
Bitmap.Assign(FActiveCell^.NextCell^.Bitmap); //передаём изображение
//со следующей после активной ячейки, т. к. активная ячейка та,
//которая должна быть отменена
end;
end;)
Ответы:
В рамках ООП undo\redo логичнее реализовать так:
Делается базовый абстрактный класс (интерфейс) действие (TAction например) у него есть два абстрактных метода, выполнить (do()) и отменить (cancel()). От него наследуются все классы действий которые может совершить пользователь. Например нарисовать точку (в конструктор передаются координаты, цвет и размер точки), нарисовать круг (соответственно координаты центра, цвет, радиус и толщина) ну и тд. Когда пользователь, что то делает, то создаётся соответствующий объект выполняется у него do и он помещается в очередь. в методе do объект должен сохранять информацию необходимую для cancel (ну скажем для рисования точки надо запоминать кусок картинки под точкой). В программе есть очередь (двусвязный список) команд пользователя которая содержит указатели базового класса которые ссылаются на объекты действия. И текущее положение, undo вызывает cancel и смещает текущщее положение назад, redo соответственно наоборот смещает вперёд и вызывает do.
Как-то так.


12 лет назад

RPI.su - самая большая русскоязычная база вопросов и ответов. Наш проект был реализован как продолжение популярного сервиса otvety.google.ru, который был закрыт и удален 30 апреля 2015 года. Мы решили воскресить полезный сервис Ответы Гугл, чтобы любой человек смог публично узнать ответ на свой вопрос у интернет сообщества.

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

Чтобы связаться с нами по любому вопросу О САЙТЕ (реклама, сотрудничество, отзыв о сервисе), пишите на почту [email protected]. Только все общие вопросы размещайте на сайте, на них ответ по почте не предоставляется.