Autor Beitrag
LittleBen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 19:41 
Hallo,
habe mal wieder ein kleines Problemchen. Es geht um das erzeugen, aber viel wichtiger, um das löschen von Pages auf einem Pager. Dazu verwende ich Komponenten der TMS-Bibliothek(TAdvOfficePage bzw. TAdvOfficePager).
Eine Page zu erzeugen ist kein Problem, doch eine zu löschen schon...

Der Vorgang:
Ich habe eine Procedure die RefreshTab heißt. Diese löscht zuerst alle Tabs(auser den Ersten), und erzeugt dann wieder so viele Tabs, wie die StringList Items hat. Doch wenn ich mich gerade in einem Tab(nicht im Ersten) aufhalte und dann diese Procedure aufrufe, dann tritt ein Fehler(meist Zugriffsverletzung) auf. Doch das komische ist, dass dieser Fehler nur manchmal auftritt, auch wenn ich immer das selbe mache.
Wenn ich mich im ersten Tab aufhalte funktioniert alles.

Schaut es euch einfach mal an:
ausblenden volle Höhe Delphi-Quelltext
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:
procedure TF_Essen.RefreshTab;
var aPage: TAdvOfficePage;
    aButton: TButton;
    i: integer;
    sl: TStringlist;
begin
 sl:= TStringlist.Create;
            
 //Alle Tabs, auser den Ersten, löschen
 for i:= oReg1.AdvPageCount-1 downto 1 do //oReg1 = TAdvOfficePager 
 begin
  oReg1.AdvPages[i].free; //Hier steckt der Fehler
 end;
                        
 //StringList füllen
 sl.Add('TEST'+inttostr(1));
 sl.Add('TEST'+inttostr(2));
 sl.Add('TEST'+inttostr(3));
 sl.Add('TEST'+inttostr(4));
 sl.Add('TEST'+inttostr(5));
             
 //Nun die Pages erstellen 
 for i:= 0 to sl.count-1 do
 begin
  aPage:= TAdvOfficePage.Create(self);
  aPage.AdvOfficePager:= oReg1;
  aPage.Caption:= sl.Strings[i];
  aPage.Name:= 'Page'+inttostr(i+2);
  aPage.Tag:= i+2;
              
  aButton:= TButton.Create(Self);
  aButton.Parent:= oReg1.AdvPages[oReg1.AdvPageCount-1];
  aButton.Caption:= 'Refresh '+IntToStr(i+1);
  aButton.Name:= 'b_refresh'+IntToStr(i+2); 
  aButton.SetBounds(100,12+i*(aButton.Height+4),aButton.Width,aButton.Height);
  aButton.Tag:=i+2;
  aButton.OnClick:= b_refresh1Click; //RefreshTab aufrufen
 end;
                       
 sl.Free;
end;

Habe mich dann ein bisschen schöau gemacht und den Tipp gelesen, dass man mit die Pages mit Postmessage freigeben soll.
Also habe ich das getan. Hat sich dadurch auch deutlich verbessert!!
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
const
  PM_FREEPAGE = CM_Base+1;
...
         
procedure TF_Essen.RefreshTab;
var ...
begin
...
 for i:= oReg1.AdvPageCount-1 downto 1 do //oReg1 = TAdvOfficePager 
 begin
  PostMessage(Handle,PM_FREEPAGE,i,0);
  Application.ProcessMessages;
 end;
...
end;

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TF_Essen.PMFREEPAGE(var Message: TMessage);
begin
 oReg1.AdvPages[Message.WParam].Free;
end;


Nun kommen nur abwechselnd irgendwelche Exceptions, etc...
Doch ich mach immer genau das Selbe:
Wechseln zu Page3-->Button drücken-->Wechseln zu Page3-->Button drücken-->Wechseln zu Page3-->Button drücken-->...
Und irgendwann kommt dann mal ein Fehler!
Warum?

Ich hoffe, dass ich mein Problem gut genug geschildert habe, sodass ihr mir auch helfen könnt :)

Freu mich schon auf eure Ideen!

Danke&Grüße
Benny
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 22.04.11 20:40 
Ich kenne die Komponente eigentlich nicht, habe sie aber einmal kurz installiert. Da fällt mir sofort RemoveAdvPage beim Pager ins Auge. Hast du das einmal damit versucht statt die Seite einfach freizugeben?

Bei mir funktioniert das damit problemlos, ohne irgendwelche Messages oder irgendetwas Besonderes. :nixweiss:
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 21:44 
Also wenn ich es so mache:
ausblenden Delphi-Quelltext
1:
2:
 for i:= 2 to oReg1.AdvPageCount do
  oReg1.RemoveAdvPage(TAdvOfficePage(FindComponent('Page'+inttostr(i))));

und dann wieder meine Pages erstelle, kommt sofort der Fehler, dass Page2 schon vorhanden ist.
Ich denke dass RemoveAdvPage die Page nicht wirklich Destroyed.

Grüße
Benny
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 22.04.11 21:47 
Na gut, das hatte ich jetzt natürlich nicht getestet. Und wie sieht es mit einer Kombination aus beidem aus? Erst entfernen, dann freigeben? :zwinker:
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 21:52 
Das funktioniert dann, wenn ich mich im ersten Tab aufhalte.
Wenn nicht, dass gibt es wieder, aber nur Manchmal, eine Zugriffsverletzung...

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
 for i:= oReg1.AdvPageCount-1 downto 1 do
 begin
  oReg1.RemoveAdvPage(TAdvOfficePage(FindComponent('Page'+inttostr(i+1))));
  TAdvOfficePage(FindComponent('Page'+inttostr(i+1))).Free;
 end;


Als ich nach dem Problem gegooglet hatte, bin ich ja auf den Tipp mit Postmessage gekommen.
Hier die Erklärung dafür:
Zitat:
PostMessage wird hier verwendet, weil PostMessage ans Ende der Botschafts-
warteschlange gestellt wird und deshalb erst abgearbeitet wird wenn alle
anderen Botschaft, wie z.B. die Click Botschaft an den Button abgearbeitet
wurde


EDIT: Zurzeit kommen auch Fehlermeldungen wie "Priviligierte Anweisung" oder "Abstrakter Fehler"
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 22.04.11 22:25 
Ja, wenn du auch die Seite freigeben willst, auf der der Button ist, so dass der mit freigegeben wird... :shock:

Dann musst du das eben alles kombinieren, Message schicken, dort Seiten entfernen und freigeben.
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 22:27 
Wie meinen?

Edit: Also meinst du, dass ich den Button auch(manuell) freigeben muss?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 22.04.11 22:48 
Ok, ich habe es ausprobiert. Und dabei dann ClearAdvPages gesehen. So klappt es bei mir absolut problemlos:
ausblenden volle Höhe Delphi-Quelltext
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:
const
  WM_TEST = WM_USER + 3290;

type
  TForm746 = class(TForm)
    TestPager: TAdvOfficePager;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure RecreatePagesClick(Sender: TObject);
  protected
    procedure WmTest(var Msg: TMessage); message WM_TEST;
  public
    { Public-Deklarationen }
  end;

var
  Form746: TForm746;

implementation

{$R *.dfm}

procedure TForm746.RecreatePagesClick(Sender: TObject);
begin
  PostMessage(Handle, WM_TEST, 00);
end;

procedure TForm746.FormCreate(Sender: TObject);
begin
  RecreatePagesClick(Sender);
end;

procedure TForm746.WmTest(var Msg: TMessage);
var
  i: Integer;
  NewPage: TAdvOfficePage;
  NewButton: TButton;
begin
  TestPager.ClearAdvPages;

  for i := 0 to Random(10) + 1 do
  begin
    NewPage := TAdvOfficePage.Create(Self);
    NewPage.AdvOfficePager := TestPager;
    NewPage.Caption := 'Page ' + IntToStr(i);
    NewPage.Name := 'Page' + IntToStr(i);

    NewButton := TButton.Create(Self);
    NewButton.Parent := NewPage;
    NewButton.Caption := 'Refresh ' + inttostr(i + 1);
    NewButton.Name := 'b_refresh' + inttostr(i + 2);
    NewButton.SetBounds(10012 + i * (NewButton.Height + 4), NewButton.Width, NewButton.Height);
    NewButton.Tag := i + 2;
    NewButton.OnClick := RecreatePagesClick;
  end;
end;
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 22:56 
Vielen,vielen Dank!
Vorallem dass du dir die Mühe gemacht hast!

Doch ich musste erschreckend feststellen, dass ich diese Funktion nicht habe :(
Könntest du sie vielleicht posten?

Vielen Danke!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 22.04.11 23:07 
Ich habe nur die Trial, also keine Quelltexte. ;-)

Aber dann eben ohne diese Funktion, so funktioniert es ebenfalls problemlos:
ausblenden volle Höhe Delphi-Quelltext
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:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AdvOfficePager, StdCtrls, Generics.Collections;

const
  WM_TEST = WM_USER + 3290;

type
  TForm746 = class(TForm)
    TestPager: TAdvOfficePager;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    FPageList: TObjectList<TAdvOfficePage>;
    procedure RecreatePagesClick(Sender: TObject);
  protected
    procedure WmTest(var Msg: TMessage); message WM_TEST;
  public
    { Public-Deklarationen }
  end;

var
  Form746: TForm746;

implementation

{$R *.dfm}

procedure TForm746.FormDestroy(Sender: TObject);
begin
  FPageList.Free;
end;

procedure TForm746.RecreatePagesClick(Sender: TObject);
begin
  PostMessage(Handle, WM_TEST, 00);
end;

procedure TForm746.FormCreate(Sender: TObject);
begin
  FPageList := TObjectList<TAdvOfficePage>.Create(True);
  RecreatePagesClick(Sender);
end;

procedure TForm746.WmTest(var Msg: TMessage);
var
  i: Integer;
  NewPage, CurrentPage: TAdvOfficePage;
  NewButton: TButton;
begin
  for CurrentPage in FPageList do
    TestPager.RemoveAdvPage(CurrentPage);
  FPageList.Clear;

  for i := 0 to Random(10do
  begin
    NewPage := TAdvOfficePage.Create(nil);
    NewPage.AdvOfficePager := TestPager;
    NewPage.Caption := 'Page ' + IntToStr(i);
    NewPage.Name := 'Page' + IntToStr(i);
    FPageList.Add(NewPage);

    NewButton := TButton.Create(Self);
    NewButton.Parent := NewPage;
    NewButton.Caption := 'Refresh ' + inttostr(i + 1);
    NewButton.Name := 'b_refresh' + inttostr(i + 2);
    NewButton.SetBounds(10012 + i * (NewButton.Height + 4), NewButton.Width, NewButton.Height);
    NewButton.Tag := i + 2;
    NewButton.OnClick := RecreatePagesClick;
  end;
end;
// EDIT:
Ich sehe gerade, dass du nur Delphi 5 und 7 hast? Dann musst du eine normale TObjectList nehmen und statt for..in eine normale for-Schleife. ;-)
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 23:18 
Genau, habe nur Delphi 5 und 7. Wie meinst du das mit der for-schleife? Bekomme ich irgendwie nicht hin :(

Trotzdem nochmal viiiiielen Dank :)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 22.04.11 23:33 
Naja, so halt:
ausblenden volle Höhe Delphi-Quelltext
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:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AdvOfficePager, StdCtrls, Contnrs;

const
  WM_TEST = WM_USER + 3290;

type
  TForm746 = class(TForm)
    TestPager: TAdvOfficePager;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    FPageList: TObjectList;
    procedure RecreatePagesClick(Sender: TObject);
  protected
    procedure WmTest(var Msg: TMessage); message WM_TEST;
  public
    { Public-Deklarationen }
  end;

var
  Form746: TForm746;

implementation

{$R *.dfm}

procedure TForm746.FormDestroy(Sender: TObject);
begin
  FPageList.Free;
end;

procedure TForm746.RecreatePagesClick(Sender: TObject);
begin
  PostMessage(Handle, WM_TEST, 00);
end;

procedure TForm746.FormCreate(Sender: TObject);
begin
  FPageList := TObjectList.Create(True);
  RecreatePagesClick(Sender);
end;

procedure TForm746.WmTest(var Msg: TMessage);
var
  i: Integer;
  NewPage: TAdvOfficePage;
  NewButton: TButton;
begin
  for i := 0 to FPageList.Count - 1 do
    TestPager.RemoveAdvPage(FPageList[i] as TAdvOfficePage);
  FPageList.Clear;

  for i := 0 to Random(10do
  begin
    NewPage := TAdvOfficePage.Create(nil);
    NewPage.AdvOfficePager := TestPager;
    NewPage.Caption := 'Page ' + IntToStr(i);
    NewPage.Name := 'Page' + IntToStr(i);
    FPageList.Add(NewPage);

    NewButton := TButton.Create(Self);
    NewButton.Parent := NewPage;
    NewButton.Caption := 'Refresh ' + inttostr(i + 1);
    NewButton.Name := 'b_refresh' + inttostr(i + 2);
    NewButton.SetBounds(10012 + i * (NewButton.Height + 4), NewButton.Width, NewButton.Height);
    NewButton.Tag := i + 2;
    NewButton.OnClick := RecreatePagesClick;
  end;
end;

Für diesen Beitrag haben gedankt: LittleBen
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Fr 22.04.11 23:39 
ES FUNKTIONIERT!!

Vielen Dank für alles!!!!
Bin nun so erlöst :)

Nochmals Danke und eine gute Nacht!

Grüße,
Benny