![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
Вопрос знатокам. Возможно ли создать точку восстановления программы написанной на Delphi.
Т.е. записать в файл полное состояние программы с целью при повторном запуске приложения продолжить работу так, как будто вы не выгружались. В своём Sapr автоматизированного раскроя я сохраняю в бинаный файл те классы, которые отвечают за раскладку деталей на листе раскроя. Но есть ньюансы при чтении данных из этого бинарного файла после загрузки приложения. Раскрой воспроизводится и можно продолжить дальнейшую раскладку деталей с возможностью изменения положения ранее разложенных деталей. Но нет возможности делать откат назад и возврат, хотя он работает при самом проектировании. Возможно ли сохранить состояние программы каким то другим способом. Исходные коды Sapr мои . |
|
#2
|
|||
|
|||
|
Ну так сохраняй в бинарник историю тоже.
Теоретически, можно сохранить весь дамп памяти приложения. Вот только потом будут проблемы с восстановлением, бо как физ адреса съедут. Т.е. в твоем случае заморачиваться смысла нет, просто пиши в бинарник историю, если это действительно нужно при "восстановлении". |
|
#3
|
|||
|
|||
|
Цитата:
Торопился и не совсем правильно выразился. "я сохраняю в бинаный файл те классы, которые отвечают за раскладку деталей " имею ввиду конечно не сами классы, а записи, ссылки на которые сохраняю в этих классах ( классы TList). Код:
type
PNewElement=^TNewElement;
TNewElement=record
NumberFigures:integer; // порядковый номер фигуры раскроя 1,2,3...
Begin_Figures:integer; // начальный индекс фигуры в списке List
End_Figures:integer; // конечный индекс фигуры в списке List
Nach_Point:TPointM;
End_Point:TPointM;
Angle_Rotate :double;
MRect:TMainRect;
STR_Coment:string[80];
case Element :TMElement of
elLine :(Pln,Plk:TPointM);
elCircle :(Pn,Pk,Pc:TPointM;Direct:TPrisnak);
elBKL :(BKL:integer);
elBIKL :(BIKL:integer);
elKORLeft :(KORLeft:integer);
elKORRight :(KORRight:integer);
elKORKK :(KORKK :integer);
elHP :(HP:boolean);
elKP :(KP:integer);
elBX :(BX:integer);
elBBX :(BBX:integer);
elHPP :(HPP:integer); // 1001,1002
elKPP :(KPP:integer);
elBPP :(BPP,BPPN:integer;BPPAngle:real);
elSpeed :(Speed :boolean);
elNul :(NUL:boolean);
elABC :(ABC:boolean);
elPrisnak :(Prisn:TPrisnak);
elName :(Name:string[80]);
elComent :(Comment:boolean);
end;
PChetchik=^TChetchik_;
TChetchik_=record
NumberFigures:integer; // порядковый номер детали в StringList - 1,4,2,2,3,3,5.
end;
...
var
FiguresElem:PNewElement;
FigureList_Elem_:TList; // список который заполняется адресами элементов детали
Chetchik:PChetchik;
FLE_Chetchik:TList;
...
procedure TFormSapr.SaveFigure_NEW; // ïèñàòü
var
i,j:integer;
f:file;
filename: string;
FigureIndex_:integer;
begin
if FigureList_Elem_.Count<>0 then // ñàìè ôèãóðû
begin
FigureIndex:=FigureList_Elem_.Count-1;
filename:=ExtractFilePath(ParamStr(0))+'RaskFigMem\FigureList_Elem.figN';
system.assign(f,filename);
system.rewrite(f,1);
system.blockWrite(f,FigureIndex,sizeof(FigureIndex));
for i:=0 to FigureList_Elem_.Count-1 do
begin
FiguresElem:=FigureList_Elem_.Items[i];
system.blockWrite(f,FiguresElem^,SizeOf(FiguresElem^));
end;
system.blockWrite(f,FiguresElem^.Nach_Point.X,SizeOf(FiguresElem^.Nach_Point.X));
system.blockWrite(f,FiguresElem^.Nach_Point.Y,SizeOf(FiguresElem^.Nach_Point.Y));
system.blockWrite(f,FiguresElem^.End_Point.X,SizeOf(FiguresElem^.End_Point.X));
system.blockWrite(f,FiguresElem^.End_Point.Y,SizeOf(FiguresElem^.End_Point.Y));
system.blockWrite(f,FiguresElem^.MRect.MinX,SizeOf(FiguresElem^.MRect.MinX));
system.blockWrite(f,FiguresElem^.MRect.MaxX,SizeOf(FiguresElem^.MRect.MaxX));
system.blockWrite(f,FiguresElem^.MRect.MinY,SizeOf(FiguresElem^.MRect.MinY));
system.blockWrite(f,FiguresElem^.MRect.MaxY,SizeOf(FiguresElem^.MRect.MaxY));
system.close(f);
end; // if FigureList_Elem_.Count<>0 then
if FLE_Chetchik.Count<>0 then // ïîðÿäêîâûé íîìåð ôèãóðû ðàñêðîÿ 1,4,2,2,3,3,5... èç StringGrid1
begin
FigureIndex_:=FLE_Chetchik.Count-1;
filename:=ExtractFilePath(ParamStr(0))+'RaskFigMem\FLE_Chetchik.figN';
system.assign(f,filename);
system.rewrite(f,1);
system.blockWrite(f,FigureIndex_,sizeof(FigureIndex_));
for i:=0 to FLE_Chetchik.Count-1 do
begin
Chetchik:=FLE_Chetchik.Items[i];
system.blockWrite(f,Chetchik^,SizeOf(Chetchik^));
end;
system.close(f);
end;
end;
procedure TFormSapr.LoadRaskroj_NEW; // ÷èòàòü
var
i,j,nomread:integer;
f:file;
S,S1:string;
k:integer;
fileName:string;
FigureIndex_:integer;
begin
if FigureList_Elem_.Count=0 then
begin
filename:=ChangeFileExt(ExtractFilePath(ParamStr(0))+'RaskFigMem\FigureList_Elem.figN','.figN');
if not FileExists(filename) then
Exit;
LMDLabel7.Caption:='ÑÈÑÒÅÌÀ SAPR ×ÏÓ. ÐÀÑÊÐÎÉ : '+ExtractShortPathName(filename);
system.assign(f,Filename);
system.Reset(f,1);
system.blockRead(f,FigureIndex,sizeof(FigureIndex),nomread);
for i:=0 to FigureIndex do // èçì
begin
new(FiguresElem);
system.blockRead(f,FiguresElem^,SizeOf(FiguresElem^),nomread);
if (i=FigureIndex) then
Index_Figure:=FiguresElem.NumberFigures;
FigureList_Elem_.Add(FiguresElem);
end;
Nach_Point_X := FiguresElem^.Nach_Point.X;
Nach_Point_Y := FiguresElem^.Nach_Point.Y;
End_Point_X := FiguresElem^.End_Point.X;
End_Point_Y := FiguresElem^.End_Point.Y;
MRect_MinX := FiguresElem^.MRect.MinX;
MRect_MaxX := FiguresElem^.MRect.MaxX;
MRect_MinY := FiguresElem^.MRect.MinY;
MRect_MaxY := FiguresElem^.MRect.MaxY;
Inc(Index_Figure);
system.close(f);
end;
if FLE_Chetchik.Count=0 then
begin
filename:=ChangeFileExt(ExtractFilePath(ParamStr(0))+'RaskFigMem\FLE_Chetchik.figN','.figN');
if not FileExists(filename) then
Exit;
system.assign(f,Filename);
system.Reset(f,1);
system.blockRead(f,FigureIndex_,sizeof(FigureIndex_),nomread);
for i:=0 to FigureIndex_ do
begin
new(Chetchik);
system.blockRead(f,Chetchik^,SizeOf(Chetchik^),nomread);
FigureList_Elem_.Add(Chetchik);
end;
system.close(f);
end;
if FormSapr.Panel_Visual_Raskroj1<>nil then
Panel_Visual_Raskroj1.WMPaint(Msg1)
else
Panel_Visual_Raskroj2.WMPaint(Msg1);
end;Код:
Nach_Point_X := FiguresElem^.Nach_Point.X; Nach_Point_Y := FiguresElem^.Nach_Point.Y; End_Point_X := FiguresElem^.End_Point.X; End_Point_Y := FiguresElem^.End_Point.Y; MRect_MinX := FiguresElem^.MRect.MinX; MRect_MaxX := FiguresElem^.MRect.MaxX; MRect_MinY := FiguresElem^.MRect.MinY; MRect_MaxY := FiguresElem^.MRect.MaxY; Код:
if (Index_Figure>1) and (i=1) then
begin
{Line} new(FiguresElem);
FiguresElem^.Element:=elLine;
if Flag_Vosstanovlen then
begin
FiguresElem^.Pln.X:=End_Point_X;
FiguresElem^.Pln.Y:=End_Point_Y;
FiguresElem^.Plk.X:=MRect_MinX;
FiguresElem^.Plk.Y:=MRect_MaxY+5;
Flag_Vosstanovlen:=false;
end
else
begin
FiguresElem^.Pln:=PNewElement(FigureList_Elem_.Items[BeginFig-1]).End_Point;
FiguresElem^.Plk.X:=PNewElement(FigureList_Elem_.Items[BeginFig-1]).MRect.MinX;
FiguresElem^.Plk.Y:=PNewElement(FigureList_Elem_.Items[BeginFig-1]).MRect.MaxY+5;
end;
// FiguresElem^.Pln:=PNewElement(FigureList_Elem_.Items[BeginFig-1]).End_Point;
// FiguresElem^.Plk.X:=PNewElement(FigureList_Elem_.Items[BeginFig-1]).MRect.MinX;
// FiguresElem^.Plk.Y:=PNewElement(FigureList_Elem_.Items[BeginFig-1]).MRect.MaxY+5;
FiguresElem^.Begin_Figures:=BeginFig;
FiguresElem^.End_Figures:=BeginFig+FigureIndex+1;
FiguresElem^.NumberFigures:=Index_Figure;
Nach_Point_:=FiguresElem^.Plk;
Xmin_:=FiguresElem^.Pln.X;
Xmax_:=FiguresElem^.Pln.Y;
Ymin_:=FiguresElem^.Pln.X;
Ymax_:=FiguresElem^.Pln.Y;
FiguresElem^.MRect.MinX:=Xmin_;
FiguresElem^.MRect.MaxX:=Xmax_;
FiguresElem^.MRect.MinY:=Ymin_;
FiguresElem^.MRect.MaxY:=Ymax_;
FigureList_Elem_.Add(FiguresElem);
endПотому что приходится стирать всё и читать второй раз, тогда всё работает нормально.[/code] Последний раз редактировалось lmikle, 26.09.2022 в 04:23. |
|
#4
|
|||
|
|||
|
Значит что-то не пишешь или не читаешь. Кстати, что такое TPointM? Указатель на структуру? Если да, то вот тут и есть ошибка, бо, как видимо, там сохраняется адрес, а не содержимое полей. Кстати, там вообще можно тогда на Access Violation налететь только так.
Вообще, это у тебя кошмар какой-то. Нет что бы сделать нормальную иерархию классов. В каждом классе есть метод его записи и чтения (например, в поток, так лучше, чем использовать нетипизированный файл). И, соответсвенно, просто вызывается соотв. метод. Посмотри, я вот тут: https://delphisources.ru/forum/showt...029#post158029 постил пример модели. Там всего 2 уровня, но идея должна быть понятна. Да, кода придется написать чуточку больше, но зато будет красиво и читабельно. Ну и вообще, поправишь модель. А то есть у меня подозрение, что у тебя там что-то лишнее есть... |
|
#5
|
|||
|
|||
|
Цитата:
Код:
PPointM=^TPointM; TPointM=record X,Y:real; Последний раз редактировалось lmikle, 27.09.2022 в 04:54. |
|
#6
|
|||
|
|||
|
Да нет, судя по описанию записи должно быть нормально.
Но, как я уже сказал, код у тебя получается очень путанный, неудобно отлаживать. Вообще, наверное лучше переписать сохранение на алгоритм "честной" сереализации. А еще лучше, как я говорил, переделай на иерархию классов. Там код будет очень простой и прозрачный, вероятность ошибки будет минимальная. Если не знаешь как - пиши, подскажу. |