Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Frames auf PageControl oder Form ! Ich werd verrückt (https://www.delphipraxis.net/26161-frames-auf-pagecontrol-oder-form-ich-werd-verrueckt.html)

DataCool 19. Jul 2004 15:14


Frames auf PageControl oder Form ! Ich werd verrückt
 
Hi Leute,

ich habe eine Frame-Klasse, die ich je nach Einstellungen dynamisch auf eine Form oder auf eien Tab-Sheet eines PageControls setze.
Das ganze funktioniert eigentlich auch wunderbar, aber :

Zu Verwaltung der einzelnen Frames, habe ich diese in einem TList Objekt gespeichert mit diversen Zusatz-Information, so sieht meine KLasse aus die ich in der TLIst speichere :

Code:
  TChatWindowData = class
    private                        
      // Optische Darstellungselemente
      fFreeInProgress : Boolean; // SChalter, ob dieses Element sich gerade schon in der Freigabe befindet
      fFrame         : TfraChatWindow; // Der Frame selber
      fForm          : TfrmChatWindow; // Falls der Frame auf einer Form sitzt, dann ist es diese
      fTabSheet      : TTabsheetes;   // Falls der Frame auf einem Tab sitzt, dann dieser
      fMultiChat     : TfrmMultiChat; // Form auf dem sich die Tabshetts befinden
      // Daten von Chat-Partner
      fID            : Longint;
    protected
      {}
    public
      Constructor Create;
      Destructor Destroy; override;

      property FreeInProgress : Boolean  read fFreeInProgress write fFreeInProgress;
      property Frame : TfraChatWindow    read fFrame         write fFrame;
      property Form : TfrmChatWindow    read fForm          write fForm;
      property Tab  : TTabSheetes       read fTabSheet      write fTabSheet;
      property MultiChat : TfrmMultiChat read fMultiCHat write fMultiCHat;
      property ID   : Longint           read fID            write fID;

      function FrameIsOnTab : Boolean;
      function FrameIsinForm : Boolean;
   
  end;

constructor TChatWindowData.Create;
begin
  inherited;
  fFreeInProgress := false;
  fFrame   := Nil;
  fForm    := Nil;
  fTabSheet := Nil;
  fMultiChat:= Nil;
  fID      := 0;
  //fLastMsg := 0;
end;

destructor TChatWindowData.Destroy;
begin
  fForm := nil;
  fTabSheet := nil;
  fFrame := nil;
  fMultiChat := nil;
  inherited;
end;
An dieser Klasse ist ja nicht besonders dran, ich brauche sie nur zur Verwaltung der einzelnen Frames !
Jetzt habe ich das Problem, das meine TChatWindowData-Objekte in meiner T-List ja auch wieder sauber entfernt werden müssen. Jetzt ist aber die Frage wann und wo meine Einträge aus der Liste entfernen ?

Den Destructor meines Frames habe ich überschrieben, und versuche dann im Destroy des Frames in meinem T-List Objekt den entsprechenden Frame zu finden und den Eintrag zu entfernen.

Da aber das schliessen bzw. die Freigabe der Form von verschiedenen Stellen aufgerufen werden kann, beißt die Katze sich immer wieder selber in den Schwanz, damit meine ich :

Sitzt der Frame auf einer Form können folgende Varianten auftreten :
1. Main-Form wird geschlossen, d.h. in Close der Main-Form rufe ich Clear meiner Liste auf, dieses geht hin und gibt alle geöffneten Form und Ihre Frames frei, dabei wird dann aber auch wieder der Destructor des Frames aufgerufen. Der widerum auch versucht die Forms freizugeben und seinen Frame-Eintrag aus der Liste zu entfernen.

2. Eine bestimmte Form wird geschlossen, im OnClose setzte ich die OnCloseACtion auf caFree, so das der FRame auch wieder mit freigegeben wird, und dann destructor von frame ....

3. Das Close kommt aus dem Frame(Button) selber, jetzt kann ich nicht einfach meinen Frame-Eintrag mit aus der Liste entfernen, sondern muss die Form auf der der Frame sitzt ja auch mit schliessen/Freigeben, wodurch sich wieder alles überschneidet.

Ich weiß nicht, on aus meiner ERklärung mein Problem ersichtlich wird, aber das ganze ist wie ein Teufelskreis, behabe ich einen Fehler, tritt dieser Fehler wird an anderer Stelle auf und so bekomme ich immer Zugriffsverletzungen oder "Abstrakte Fehler".
Jetzt bitte nicht sagen, "debug das ganze doch mal", denn das tue ich schon seit einem Tag :wall:

Der Fehler ist mit Debuggen leider nicht zu finden, ich habe z.B. meine Procedure meines Close Buttons auf meinem Frame, es werden alle Anweisungen und DEstructoren sauber aufgerufen, gehe ich dann mit F8 ans Ende der Procedure gibt halt die oben genannten Fehlermeldungen.
Benutze ich F7 dann lade ich sporadisch in diversen überschriebenen WncProc von diversen Komponenten.
Bei plazieren der Frames auf Forms habe ich mittlerweile ne total buggy Lösung gefunden, aber nur durch Try and Error, aber bei den Tabsheets komme ich echt nicht weiter.

Mario 19. Jul 2004 16:32

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Ich würde das Problem versuchen einzugrenzen. Ersetze doch Free durch FreeAndNil. Dann kannst Du mit Assigned die Existenz Deiner Objekte prüfen und Zugriffsverletzungen bleiben aus. Dann wäre es auch möglich, an mehreren Stellen die Freigabe vorzunehmen.
Delphi-Quellcode:
if Assigned(MyObj) then FreeAndNil(MyObj);

DataCool 19. Jul 2004 17:05

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Hi,

leider hilft mir das nicht weiter, ich verwende meistens sowieso FreeAndNil !!!

Ich hab jetzt auch schonmal testweise, meine PageControl(modifizierte KOmponente) gegen ein STandard-Page-Control ausgetauscht, aber der gleiche Effekt.

ich habe ne Procedure oder einen Event(z.B. Button Click), innerhalb dieser Procedure rufe ich folgende auf :
Code:
procedure TfraChatWindow.FreeFromTab;
Var Data : TChatWindowData;
    Idx : Longint;
    RemoveTab : TTabSheet;
begin
  idx := ChatWindows.IndexOfFrame(self);
  if idx > -1 then begin
    Data := ChatWindows.Items[Idx];
    if Data <> Nil then begin
      Data.FreeInProgress := true;
      ChatWindows[idx] := Nil;
      Data.Frame.free;
      (*
      if (Data.Tab.PageIndex < (Data.Tab.PageControl.PageCount -1)) then
        Data.Tab.PageControl.ActivePageIndex := Data.Tab.PageIndex + 1
      else
        Data.Tab.PageControl.ActivePageIndex := Data.Tab.PageIndex -1;
      *)
      DAta.Tab.TabVisible := false; // egal, ob diese ZEile aktiviert ist oder nicht
      RemoveTab := Data.Tab;
      FreeAndNil(RemoveTab);
      FreeAndNil(Data);
      //ChatWindows.Pack;
    end;
  end;
end;
Wenn ich am Ende der Procedure angekommen bin, und dann F7 drücke springt er zu dem letzten End meine Action.OnExecute und bei erneutem F7 gibt es meine Schutzverletzung, aber leider keinen Hinweis wo :(
Im CPU Fenster stellen nur lauter ???? Es handelt sich bei der Exception um eine EAcessViolation, aber mit ner gültigen Zeiger-Adresse nicht 00000000000000000.

mirage228 19. Jul 2004 17:12

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Hi,

vielleicht solltest du mal versuchen mit Debug-DCUs zu kompilieren (Projekt -> Optionen -> Compiler).

Dann kannst du auch mit F7 / F8 in die Borland Quelltexte reinkommen.

Vielleicht hilft dir das ja.

mfG
mirage228

DataCool 19. Jul 2004 17:25

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Hi Mirage,

habe ich gerade gemacht, dann hangelt er sich von der Action hoch bis zum TControl.WMLButtonUp
Code:
procedure TControl.DoMouseUp(var Message: TWMMouse; Button: TMouseButton);
begin
  if not (csNoStdEvents in ControlStyle) then
    with Message do MouseUp(Button, KeysToShiftState(Keys), XPos, YPos);
end;

procedure TControl.WMLButtonUp(var Message: TWMLButtonUp);
begin
  inherited;
  if csCaptureMouse in ControlStyle then MouseCapture := False;
  if csClicked in ControlState then
  begin
    Exclude(FControlState, csClicked);
    if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
  end;
  DoMouseUp(Message, mbLeft);
end;
In dem DoMouseUp, sprint er dann von der ZEile with Message do MouseUp(Button, KeysToShiftState(Keys), XPos, YPos); in die System.pas
Code:
procedure      GetDynaMethod;
{       function       GetDynaMethod(vmt: TClass; selector: Smallint) : Pointer;      }
asm
        { ->   EAX    vmt of class           }
        {       SI     dynamic method index   }
        { <-    ESI pointer to routine }
        {       ZF = 0 if found        }
        {       trashes: EAX, ECX              }

        PUSH   EDI
        XCHG   EAX,ESI
        JMP    @@haveVMT
@@outerLoop:
        MOV    ESI,[ESI]
@@haveVMT:
        MOV    EDI,[ESI].vmtDynamicTable
        TEST   EDI,EDI
        JE     @@parent
        MOVZX  ECX,word ptr [EDI]
        PUSH   ECX
        ADD    EDI,2
        REPNE  SCASW
        JE     @@found
        POP    ECX
@@parent:
        MOV    ESI,[ESI].vmtParent
        TEST   ESI,ESI
        JNE    @@outerLoop
        JMP    @@exit

@@found:
        POP    EAX
        ADD    EAX,EAX
        SUB    EAX,ECX        { this will always clear the Z-flag ! }
        MOV    ESI,[EDI+EAX*2-4]

@@exit:
        POP    EDI
end;
MOVZX ECX,word ptr [EDI] ist die Zeile wo er crashed :shock:

Robert_G 19. Jul 2004 17:27

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Im Create wird fFrame nicht erzeugt, genausowenig im Destroy freigegeben!
Zitat:

Zitat von DataCool
Es handelt sich bei der Exception um eine EAcessViolation, aber mit ner gültigen Zeiger-Adresse nicht 00000000000000000.

Könnte sich um den nicht existierenden Frame handeln. Du verpasst ihm doch mit ...
Delphi-Quellcode:
  fFrame   := Nil;
... absichtlich eine ungültige Adresse.
Eine AV @00000000000000000 gibt's IMHO nur bei Zeigern, die auf nichts zeigen (also 00000000000000000 ;) ).

shmia 19. Jul 2004 17:32

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Zitat:

Zitat von DataCool
3. Das Close kommt aus dem Frame(Button) selber, jetzt kann ich nicht einfach meinen Frame-Eintrag mit aus der Liste entfernen, sondern muss die Form auf der der Frame sitzt ja auch mit schliessen/Freigeben, wodurch sich wieder alles überschneidet.

Hier scheint mir das Problem zu liegen. Ein Control darf nicht einfach sich selber oder sein
Parent-Control oder sein Parent-Frame zerstören. (Weil die VCL noch nicht ganz fertig mit dem Control ist)
Schau dir mal meinen Artikel Controls, die sich selbst zerstören an.

DataCool 19. Jul 2004 17:32

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
hi Robert,

der Frame wird an einer anderen Stelle erzeugt, weil er ja wahlweise auf einen Tabsheet oder einer Form plaziert wird.
Genauso wird er an einer anderen Stelle freigegeben.
Die Klasse wo der Frame auf Nil gesetzt wird, wird nur als Zugriffs-Container gebraucht.

DataCool 19. Jul 2004 17:36

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Hi Shmia,

und wie schliesse ich jetzt aus einer ACtion des Frames jetzt das übergeordnete Control(Form oder Tabsheet) ?
Ich denke auch das da irgentwo der Hund begraben liegt, den bei der Form hatte ich ein ähnliches Problem, was ich dadurch gelöst habe, das ich das OnClick EReignis des Close-Buttons der Form aufgerufen habe :zwinker:
Aber wie mache ich das jetzt bei Tab ?
Erschwerend kommt hinzu, das wenn nur noch ein Tab aktiv ist, natürlich auch die Form auf der die Tabs liegen geschlossen werden soll.

shmia 19. Jul 2004 17:47

Re: Frames auf PageControl oder Form ! Ich werd verrückt
 
Zitat:

Zitat von DataCool
der Frame wird an einer anderen Stelle erzeugt, weil er ja wahlweise auf einen Tabsheet oder einer Form plaziert wird.
Genauso wird er an einer anderen Stelle freigegeben.
Die Klasse wo der Frame auf Nil gesetzt wird, wird nur als Zugriffs-Container gebraucht.

Wo der Frame erzeugt wird oder wo er zerstört wird, spielt keine Rolle.
Einscheidend ist, ob ein Control auf dem Frame (z.B. ein Button oder ein Popup-Menu) der Ausgangspunkt
für das Zerstören des Frames ist.
Wenn der Lösch-Button (oder was auch immer) beim Klicken selbst zerstört wird, dann -> Zugriffsverletzung.

PS: Hast du das Beispiel zu meinem Artikel angeschaut ?


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:37 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz