Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Разное
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 23.09.2022, 21:55
basilcat basilcat вне форума
Прохожий
 
Регистрация: 27.04.2017
Сообщения: 16
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Создание точки восстановления программы написанной на Delphi

Вопрос знатокам. Возможно ли создать точку восстановления программы написанной на Delphi.
Т.е. записать в файл полное состояние программы с целью при повторном запуске приложения продолжить работу так, как будто вы не выгружались.
В своём Sapr автоматизированного раскроя я сохраняю в бинаный файл те классы, которые отвечают за раскладку деталей на листе раскроя. Но есть ньюансы при чтении данных из этого бинарного файла после загрузки приложения. Раскрой воспроизводится и можно продолжить дальнейшую раскладку деталей с возможностью изменения положения ранее разложенных деталей. Но нет возможности делать откат назад и возврат, хотя он работает при самом проектировании. Возможно ли сохранить состояние программы каким то другим способом. Исходные коды Sapr мои .
Ответить с цитированием
  #2  
Старый 23.09.2022, 23:03
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,087
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну так сохраняй в бинарник историю тоже.

Теоретически, можно сохранить весь дамп памяти приложения. Вот только потом будут проблемы с восстановлением, бо как физ адреса съедут. Т.е. в твоем случае заморачиваться смысла нет, просто пиши в бинарник историю, если это действительно нужно при "восстановлении".
Ответить с цитированием
  #3  
Старый 24.09.2022, 11:55
basilcat basilcat вне форума
Прохожий
 
Регистрация: 27.04.2017
Сообщения: 16
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Ну так сохраняй в бинарник историю тоже.

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

Торопился и не совсем правильно выразился.
"я сохраняю в бинаный файл те классы, которые отвечают за раскладку деталей " имею ввиду конечно не сами классы, а записи, ссылки на которые сохраняю в этих классах ( классы TList).

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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;
В чём состоит проблема. Читается всё правильно, но в FigureList_Elem_ в последнем элементе впоследствии, когда начинаю выводить следующую деталь значения в FiguresElem^ ответственные за привязку следующей детали к предыдущей обнуляются, хотя при прочтении были верные. Пришлось пойти на хитрость и сразу после прочтения файла записать теряемые значения в
Код:
1
2
3
4
5
6
7
8
9
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;
И потом в том месте где они нужны заменять все FiguresElem^.End_Point.X и т.д. на End_Point_X и т.д.:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
           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  
Старый 26.09.2022, 04:30
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,087
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Значит что-то не пишешь или не читаешь. Кстати, что такое TPointM? Указатель на структуру? Если да, то вот тут и есть ошибка, бо, как видимо, там сохраняется адрес, а не содержимое полей. Кстати, там вообще можно тогда на Access Violation налететь только так.

Вообще, это у тебя кошмар какой-то.
Нет что бы сделать нормальную иерархию классов. В каждом классе есть метод его записи и чтения (например, в поток, так лучше, чем использовать нетипизированный файл). И, соответсвенно, просто вызывается соотв. метод.
Посмотри, я вот тут:
https://delphisources.ru/forum/showt...029#post158029
постил пример модели. Там всего 2 уровня, но идея должна быть понятна. Да, кода придется написать чуточку больше, но зато будет красиво и читабельно.
Ну и вообще, поправишь модель. А то есть у меня подозрение, что у тебя там что-то лишнее есть...
Ответить с цитированием
  #5  
Старый 27.09.2022, 04:38
basilcat basilcat вне форума
Прохожий
 
Регистрация: 27.04.2017
Сообщения: 16
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Значит что-то не пишешь или не читаешь. Кстати, что такое TPointM? Указатель на структуру? Если да, то вот тут и есть ошибка, бо, как видимо, там сохраняется адрес, а не содержимое полей. Кстати, там вообще можно тогда на Access Violation налететь только так.

Вообще, это у тебя кошмар какой-то.
Нет что бы сделать нормальную иерархию классов. В каждом классе есть метод его записи и чтения (например, в поток, так лучше, чем использовать нетипизированный файл). И, соответсвенно, просто вызывается соотв. метод.
Посмотри, я вот тут:
https://delphisources.ru/forum/showt...029#post158029
постил пример модели. Там всего 2 уровня, но идея должна быть понятна. Да, кода придется написать чуточку больше, но зато будет красиво и читабельно.
Ну и вообще, поправишь модель. А то есть у меня подозрение, что у тебя там что-то лишнее есть...

Код:
1
2
3
PPointM=^TPointM;
    TPointM=record
        X,Y:real;
Спасибо за ответ. Посмотрю обязательно.

Последний раз редактировалось lmikle, 27.09.2022 в 04:54.
Ответить с цитированием
  #6  
Старый 27.09.2022, 04:57
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,087
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Да нет, судя по описанию записи должно быть нормально.
Но, как я уже сказал, код у тебя получается очень путанный, неудобно отлаживать. Вообще, наверное лучше переписать сохранение на алгоритм "честной" сереализации. А еще лучше, как я говорил, переделай на иерархию классов. Там код будет очень простой и прозрачный, вероятность ошибки будет минимальная.
Если не знаешь как - пиши, подскажу.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 19:16.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025