![]() |
Delphi-Version: XE2
Ein Object in TObjectList<T> löschen mit Ereignis
Hallo zusammen,
ich habe folgende Klassen erstellt :
Delphi-Quellcode:
Das funktioniert auch alles soweit ganz gut, bis auf den Teil mit FOnDelete. Warum bekomme ich jedesmal bei der Zeile
type
TModifyActionList = (lnNone, lnAdded, lnChange, lnDelete); TDegree = class private FOnChange : TNotifyEvent; FOnDelete : TNotifyEvent; FModifyAction : TModifyActionList; FID : Integer; FDegree : string; procedure SetID(const Value: Integer); procedure SetDegree(const Value: string); public property ID : Integer read FID write SetID; property Degree : string read FDegree write SetDegree; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write FOnChange; property OnDelete : TNotifyEvent read FOnDelete write FOnDelete; end; TCustomObjectList<T: class> = class(TObjectList<T>) private FOnChange : TNotifyEvent; FOnDelete : TNotifyEvent; FModifyAction : TModifyActionList; FNewRecord : Boolean; procedure DeleteRecord(Klasse: T); protected function getItem(Index: Integer): T; virtual; procedure setItem(Index: Integer; Objekt: T); virtual; procedure Notify(const Item: T; Action: TCollectionNotification); override; public function Add(Objekt: T): Integer; virtual; function NewRecord(Objekt: T): Integer; virtual; function Remove(Objekt: T): Integer; virtual; function IndexOf(Objekt: T): Integer; virtual; procedure Insert(Index: Integer; Objekt: T); virtual; property Items[index: Integer]: T read getItem write setItem; default; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write FOnChange; property OnDelete : TNotifyEvent read FOnDelete write FOnDelete; end; {...} { TDegree } procedure TDegree.SetDegree(const Value: string); begin FDegree := Value; if (Assigned(FOnChange)) and (FModifyAction = lnChange) then FOnChange(Self); end; procedure TDegree.SetID(const Value: Integer); begin FID := Value; if (Assigned(FOnChange)) and (FModifyAction = lnChange) then FOnChange(Self); end; { TCustomObjectList<T> } function TCustomObjectList<T>.Add(Objekt: T): Integer; begin FNewRecord := False; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.DeleteRecord(Klasse: T); begin // To do something end; function TCustomObjectList<T>.getItem(Index: Integer): T; begin Result := T(inherited Items[Index]); end; function TCustomObjectList<T>.IndexOf(Objekt: T): Integer; begin Result := inherited IndexOf(Objekt); end; procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T); begin inherited Insert(Index, Objekt); end; function TCustomObjectList<T>.NewRecord(Objekt: T): Integer; begin FNewRecord := True; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Notify(const Item: T; Action: TCollectionNotification); begin if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then begin FNewRecord := False; FOnChange(Self); end; if Action = cnRemoved then begin FOnDelete(Item); end; inherited Notify(Item, Action); end; function TCustomObjectList<T>.Remove(Objekt: T): Integer; begin Result := inherited Remove(Objekt); end; procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T); begin inherited Items[Index] := Objekt; end;
Delphi-Quellcode:
eine AccessViolation ? Wie kann ich das beheben und was habe ich falsch gemacht ?
FOnDelete(Item);
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Prüf doch mal mit
Delphi-Quellcode:
ab, ob da was zugewiesen ist ;)
if Assigned( FOnDelete ) then
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Habe ich das aus der OH für Assigned richtig verstanden, wenn ich folgende Zeilen Code chreibe :
Delphi-Quellcode:
Dann gibt mir
Degree := TDegree.Create;
Degree.OnChange := TableEntryChange; Degree.OnDelete := TableEntryDelete; Degree.ID := FieldByName('ID').AsInteger; Degree.Degree := FieldByName('Degree').AsString; DegreeList.Add(Degree);
Delphi-Quellcode:
innerhalb der Klasse zurück, ob die Zeile
Assigned(FOnDelete)
Delphi-Quellcode:
ausgeführt wurde oder nicht ? Wenn ja, dann ist es leider nicht der Fall.
Degree.OnDelete := TableEntryDelete;
Delphi-Quellcode:
gibt immer False zurück. Warum ?
Assigned(FOnDelete)
Der obere Code-Iteil wird in einer Schleife mehrmals wiederholt. |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Eigentlich sollte Assigned nach der Methodenzuweisung true zurückliefern. Bau doch mal temporär einen Setter ein, setz dort einen Haltepunkt und schau, ob der angesprungen wird. Ich sehe in dem Code keinen Grund, wieso das nicht so sein sollte.
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Bei den Klassen geht er in den Setter und weißt auch den richtigen Wert zu. Kann es vielleicht daran liegen, dass erst der Delete-Befehl ausgeführt wird und er dann ins Notify springt von TCustomObjectList<T: class> ?
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Ich habe es gerade nicht im Kopf, aber möglicherweise ist das Item zwischen dem Delete und dem Notify bereits freigegeben, das würde die AV erklären.
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe es jetzt mal getestet. Wenn ich bei der Zeile
Delphi-Quellcode:
einen Breakpoint setze, steht der Count von der ObjectList um einen reduziert. Das heißt für mich, dass erst das Objekt gelöscht wird und dann Notify ausgeführt wird. Um das Ergebnis noch zu verifizieren, habe ich die Procedure Delete mit in meine abgeleitet Klasse übernommen. Es ist wirklich so, das erst die Delete Procedure ausgeführt wird und dann das Notify. Ich habe jetzt mal zusätzlich in der Delete-Procedure eine Abfrage auf Assigned(FOnDelete) gemacht. Auch hier wird ein False ausgegeben, wie kann das sein ?
if Action = cnRemoved then
Meine TCustomObjectList<T: class> sieht jetzt so aus :
Delphi-Quellcode:
Bei
TCustomObjectList<T: class> = class(TObjectList<T>)
private FOnChange : TNotifyEvent; FOnDelete : TNotifyEvent; FModifyAction : TModifyActionList; FNewRecord : Boolean; procedure SetOnDelete(const Value: TNotifyEvent); procedure SetOnChange(const Value: TNotifyEvent); protected function getItem(Index: Integer): T; virtual; procedure setItem(Index: Integer; Objekt: T); virtual; procedure Notify(const Item: T; Action: TCollectionNotification); override; public function Add(Objekt: T): Integer; virtual; procedure Delete(Index: Integer); virtual; function NewRecord(Objekt: T): Integer; virtual; function Remove(Objekt: T): Integer; virtual; function IndexOf(Objekt: T): Integer; virtual; procedure Insert(Index: Integer; Objekt: T); virtual; property Items[index: Integer]: T read getItem write setItem; default; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write SetOnChange; property OnDelete : TNotifyEvent read FOnDelete write SetOnDelete; end; {...} { TCustomObjectList<T> } function TCustomObjectList<T>.Add(Objekt: T): Integer; begin FNewRecord := False; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Delete(Index: Integer); begin if Assigned(FOnDelete) then FOnDelete(Self); inherited Delete(Index); end; function TCustomObjectList<T>.getItem(Index: Integer): T; begin Result := T(inherited Items[Index]); end; function TCustomObjectList<T>.IndexOf(Objekt: T): Integer; begin Result := inherited IndexOf(Objekt); end; procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T); begin inherited Insert(Index, Objekt); end; function TCustomObjectList<T>.NewRecord(Objekt: T): Integer; begin FNewRecord := True; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Notify(const Item: T; Action: TCollectionNotification); begin if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then begin FNewRecord := False; FOnChange(Self); end; inherited Notify(Item, Action); end; function TCustomObjectList<T>.Remove(Objekt: T): Integer; begin Result := inherited Remove(Objekt); end; procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T); begin inherited Items[Index] := Objekt; end; procedure TCustomObjectList<T>.SetOnChange(const Value: TNotifyEvent); begin FOnChange := Value; end; procedure TCustomObjectList<T>.SetOnDelete(const Value: TNotifyEvent); begin FOnDelete := Value; end;
Delphi-Quellcode:
steht der Count von TCustomObjectList<TDegree> noch auf der vollen Anzahl Objekte. Entweder verstehe ich hier etwas nicht oder es läuft irgendwas schief.
if Assigned(FOnDelete) then
Edit: Im Anhang meine DegreeList, nach dem Befüllen mit Daten. So wie ich das sehe, ist doch alles korrekt oder ? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Was sagt denn der debugger, wenn du dir kurz vor dem aufruf den Wert dieser Variable anzeigen läßt? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Debugger Exception Notification --------------------------- Project Project14.exe raised exception class $C0000005 with message 'access violation at 0x00000000: read of address 0x00000000'. --------------------------- Break Continue Help --------------------------- Zitat:
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Delphi-Quellcode:
1) aber vemutlich wirklich ein "nil".
if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then // hier hast'e geprüft
begin FNewRecord := False; FOnChange(Self); end; if Action = cnRemoved then // hier nicht begin FOnDelete(Item); // hier haltepunkt hin und schauen was in FOnDelete steht, *1 end; Jedenfalls sieht die Exception danach aus, da dort zur Adresse 0 (nil) gesprungen wurde und weil dort kein ausführbarer Code steht, knallt es. (aber natürlich kann es auch noch innerhalb einer verlinkten Methode knallen, aber da sollte der Debugger ebenfalls hilfreich sein) Der schon genannte Trick mit dem Setter würde zmindestens zeigen, ob, wann und wo dieses Property verändert wird. |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Im Beitrag 7, siehst Du im Anhang, wie der Setter von FOnDelete arbeitet. Ebenfalls im gleichen Beitrag hatte ich geschrieben, dass ein Assigned(FOnDelete) immer False ergibt.
Ich habe noch ein bisschen weiter getestet. Wenn ich die TCustomObjectList<T: class> für die Klasse TDegree folgendermaßen erstelle :
Delphi-Quellcode:
Funktioneren beide Quelltexte aus den Beiträgen 1 und 7 und die Funktion für FOnDelete wird ausgeführt. Lasse ich diese Zeile
DegreeList := TCustomObjectList<TDegree>.Create;
DegreeList.OnDelete := TableEntryDelete;
Delphi-Quellcode:
weg, dann wird FOnDelete nichtmehr ausgeführt oder es wird die Access Violation angezeigt, wenn die Abfrage auf Assigned(FOnDelete) fehlt. Deshalb gehe ich davon aus, das das FOnDelete im Notify auf das FOnDelete in der TCustomObjectList<T: class> zeigt.
DegreeList.OnDelete := TableEntryDelete;
Ich stelle mir jetzt nur die Frage, warum FOnChange so funktioniert und FOnDelete nicht ? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Hat sich Dein Compiler irgendwie verschluckt?
Hast Du einen Compilerpoint (möglicher Breakpoint) in der Zeile? Hast Du mal Projekt bereinigen/bneu erzeugen versucht? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Zitat:
Zitat:
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Ich meinte den kleinen blauen Punkt vor jeder Befehlszeile (auf den man zum Setzen eines Breakpoints klickt).
Gelegentlich fehlten die bei mir schon mal, wenn der Compiler mit meinen Units nicht zurecht kam. :stupid: Es gibt noch die Projektoptionen Bereinigen, Erzeugen und ggf. Installieren (bei Packages). Vielleicht hilft davon ja etwas. |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Trotzdem steht ja immer noch meine Frage im Raum, warum FOnChange so funktioniert und FOnDelete nicht. Ist mein Sourcecode denn überhaupt richtig oder habe ich einen Fehler gemacht ? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Dein Code aus Beitrag 1
Delphi-Quellcode:
Du prüfst, ob FOnChange zugewiesen ist, aber du prüfst nicht, ob FOnDelete zugewiesen ist und wunderst dich, dass es knallt, wenn du FOnDelete nichts zuweist?
procedure TCustomObjectList<T>.Notify(const Item: T;
Action: TCollectionNotification); begin if // Wenn Assigned( FOnChange ) // dem Event was zugewiesen ist and // und ( FNewRecord ) // FNewRecord wahr ist and // und ( Action <> cnRemoved ) // die Aktion <> Entfernt ist then // dann begin FNewRecord := False; FOnChange(Self); end; if // Wenn Action = cnRemoved // die Aktion = Entfernt ist then // dann begin FOnDelete(Item); // knallt es hier, wenn FOnDelete = nil ist !!!!! end; inherited Notify(Item, Action); // hier wird die Objekt-Instanz freigegeben, wenn OwnsObjects = True end; Warum hast du das Überprüfen weggelassen? Das kann ich irgendwie überhaupt nicht nachvollziehen, und schon gar nicht die Verwunderung, dass da mal eine AV kommt. Ich würde es bei dem Code eher erwarten und mich wundern wenn keine kommt. Bzgl. der Frage, wann die Objekt-Instanz freigegeben wird: In der überschriebenen Notify-Methode von TObjectList<T>. Wenn du also die Notify-Methode überschreibst und erst am Ende das
Delphi-Quellcode:
gibst, dann ist die Objekt-Instanz noch da.
inherited
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Ich habe das Problem so verstanden, dass Rolf die Methoden definitiv zuweist:
Delphi-Quellcode:
aber OnDelete dennoch nil ist.
Degree := TDegree.Create;
Degree.OnChange := TableEntryChange; Degree.OnDelete := TableEntryDelete; In dem Fall kann eigentlich ja nur der Compiler ein Problem haben. Wenn in Deiner Klasse keine Befehlszeilenpunkte stehen (und Deine Klasse benutzt Du doch!?) dann ist das bestimmt ein Problem mit dem Compiler. Hast Du Deine Unit irgendwie kopiert und IDE und Compiler greifen auf unterschiedliche Versionen zu? Ich würde mal schrittweise die relevanten Stellen durchlaufen... |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
TDegree ist ein einfaches Objekt und befindet sich nachher in der Liste, ist aber nicht die Liste selber ;) EDIT: Im Beitrag #7 da hat er ein schönes Bild angehängt, wo man auch sehr schön sehen kann, das FOnDelete den Wert nil hat, und den Items (TDegree) die Events zugewiesen wurden (<>nil) :) |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Aber evtl. hilft dir folgendes: Wenn du möchtest, dass ich das Fenster schließe, dann musst du mir das sagen und nicht Erna Rübenkohl aus Recklinghausen, auch wenn die mal ein Foto von mir gesehen hat. |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Das OnChange soll dann ausgeführt werden, wenn ein Objekt hinzugefügt oder geändert wird. Das OnDelete soll dann ausgeführt werden, wenn ein Object aus der ObjectList gelöscht wird.
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Das ist auch der Grund warum es nicht so funktioniert, wie du das erwartest. ;) |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Delphi-Quellcode:
TListe = class (TObjectList<TForm1>)
public procedure Delete(Index: Integer); overload; end; procedure TListe.Delete(Index: Integer); begin inherited Delete(Index); ShowMessage('es wurde was gelöscht'); // oder OnDelete ?? end;
Delphi-Quellcode:
Liste := TListe.Create;
Liste.Add(Form1); Liste.Delete(0); // Es wurde was gelöscht So hab Ich es jetzt verstanden... Also jetzt meldet die Liste was |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Zumal die Begrifflichkeiten streng genommen falsch sind: TDegree.OnDelete = Wenn die Instanz (TDegree) aus dem Speicher entfernt wird TCustomObjectList.OnDelete = Wenn die Instanz (TCustomObjectList) aus dem Speicher entfernt wird ... ach nee, wenn ein Item aus der Liste geworfen wird ... aber für die Liste ist es doch nur eine Änderung an sich selber ;) |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Ein OnDelete welches so gedacht ist, dass es vom Objekt selbst kommt.. quasi ein OnDestroy.. naja das könnte dann höchstens ein "OnBeforeDelete" werden...
destructor Destroy; begin OnDelete; //kram... inherited; end; Aber du willst ja ein "OnItemDelete" um der Sache mal ein eindeutigeres Wort zu geben. Oder? Edit: Die Liste soll ja deine Objekte verwalten... je nachdem wie du arbeitest brauchen dann deine Objekte garkein OnDelete AKA OnDestroy. Außer deine Objekte sind wiederum von einer Klasse die vielleicht eine Liste oder etwas mit einem sinnigen Delete hat... |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Vielleicht sollte die Ereignisbehandlung der Liste über "OnItemDelete" laufen...
EDIT: Oups, überholt ohne einzuholen... ;-) |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
So sehen jetzt meine beiden Klassen aus und funktionierten so wie Sie sollen :
Delphi-Quellcode:
So wird jetzt die ObjectList erstellt und die Liste befüllt :
TModifyActionList = (lnNone, lnChange, lnDelete);
TDegree = class private FOnChange : TNotifyEvent; FModifyAction : TModifyActionList; FID : Integer; FDegree : string; procedure SetID(const Value: Integer); procedure SetDegree(const Value: string); procedure SetOnChange(const Value: TNotifyEvent); public property ID : Integer read FID write SetID; property Degree : string read FDegree write SetDegree; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write SetOnChange; end; TCustomObjectList<T: class> = class(TObjectList<T>) private FOnChange : TNotifyEvent; FOnItemDelete : TNotifyEvent; FModifyAction : TModifyActionList; FNewRecord : Boolean; procedure SetOnItemDelete(const Value: TNotifyEvent); procedure SetOnChange(const Value: TNotifyEvent); protected function getItem(Index: Integer): T; virtual; procedure setItem(Index: Integer; Objekt: T); virtual; procedure Notify(const Item: T; Action: TCollectionNotification); override; public function Add(Objekt: T): Integer; virtual; function NewRecord(Objekt: T): Integer; virtual; function Remove(Objekt: T): Integer; virtual; function IndexOf(Objekt: T): Integer; virtual; procedure Insert(Index: Integer; Objekt: T); virtual; property Items[index: Integer]: T read getItem write setItem; default; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write SetOnChange; property OnItemDelete : TNotifyEvent read FOnItemDelete write SetOnItemDelete; end; {...} { TCustomObjectList<T> } function TCustomObjectList<T>.Add(Objekt: T): Integer; begin FNewRecord := False; Result := inherited Add(Objekt); end; function TCustomObjectList<T>.getItem(Index: Integer): T; begin Result := T(inherited Items[Index]); end; function TCustomObjectList<T>.IndexOf(Objekt: T): Integer; begin Result := inherited IndexOf(Objekt); end; procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T); begin inherited Insert(Index, Objekt); end; function TCustomObjectList<T>.NewRecord(Objekt: T): Integer; begin FNewRecord := True; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Notify(const Item: T; Action: TCollectionNotification); begin if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then begin FNewRecord := False; FOnChange(Self); end; if Action = cnRemoved then begin FOnItemDelete(Item); end; inherited Notify(Item, Action); end; function TCustomObjectList<T>.Remove(Objekt: T): Integer; begin Result := inherited Remove(Objekt); end; procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T); begin inherited Items[Index] := Objekt; end; procedure TCustomObjectList<T>.SetOnChange(const Value: TNotifyEvent); begin FOnChange := Value; end; procedure TCustomObjectList<T>.SetOnItemDelete(const Value: TNotifyEvent); begin FOnItemDelete := Value; end; { TDegree } procedure TDegree.SetDegree(const Value: string); begin FDegree := Value; if (Assigned(FOnChange)) and (FModifyAction = lnChange) then FOnChange(Self); end; procedure TDegree.SetID(const Value: Integer); begin FID := Value; if (Assigned(FOnChange)) and (FModifyAction = lnChange) then FOnChange(Self); end; procedure TDegree.SetOnChange(const Value: TNotifyEvent); begin FOnChange := Value; end;
Delphi-Quellcode:
Jetzt ist es so, wenn ein Object aus der Liste gelöscht wird, also mit
DegreeList := TCustomObjectList<TDegree>.Create;
DegreeList.OnItemDelete := TableEntryDelete; { Dieser Teil wird in einer Schleife ein paar Mal wiederholt } Degree := TDegree.Create; Degree.OnChange := TableEntryChange; Degree.ID := FieldByName('ID').AsInteger; Degree.Degree := FieldByName('Degree').AsString; DegreeList.Add(Degree);
Delphi-Quellcode:
, dann wird das OnItemDelete zusätzlich mit ausgeführt. Wird jetzt der Inhalt eines Objectes geändert mit
DegreeList.Delete(0)
Delphi-Quellcode:
so wird über die Variable ModifyAction=lnChange das OnChange-Ereignis der Klasse aufgerufen. Somit funktioniert das Konstrukt so wie ich es haben möchte.
DegreeList.Items[0].Degree := AdvEdt_12.Text;
Ich hoffe es ist jetzt ein bisschen klarer, was ich erreichen wollte. Wenn es noch Verbesserungsvorschläge gibt, dann nur her damit. Ich bin immer bereit noch etwas zu lernen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:11 Uhr. |
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