![]() |
Pointer wirrwarr. Bitte um hilfe
Hallo zusammen
Dieser Code war meine Grundlage:
Delphi-Quellcode:
Wie man erkennen kann, handelt es sich um VirtualTreeView.
type
TTreeData = record FCaption: string; FColumn1: string; end; PTreeData = ^TTreeData; ... procedure TForm1.Button2Click(Sender: TObject); var Node : PVirtualNode; Data:PTreeData; begin //Data ist nur ein Pointer auf eine Datenstruktur von TTreeData; vst.BeginUpdate; //Zuerst holen wir uns den Node Node := VST.AddChild(nil); //VST kennt bereits die grösse der Struktur und hat hier genau soviel Speicher bereit gestellt //Wir übergeben Data nun die Adresse des Speichers von VST. Data := vst.GetNodeData(node); //Nun können wir direkt in den Node Speicher hinein schreiben. Data^.FCaption := 'Test'; Data^.FColumn1 := 'Column'; vst.EndUpdate; end; Ich habe nun versucht anstelle des Records ein dynamisches array bestehend aus strings zu benutzen. Dazu habe ich folgendes versucht:
Delphi-Quellcode:
type
TsqlData = array of string; PsqlData = ^TsqlData; ... function TeVCLqueryTable.Query(Query: string):integer; var row,col:integer; node:PVirtualNode; sqlData:PsqlData; begin FMySQL.Query(Query); //SQLColCount ist 11 for col := 0 to FMySQL.SQLColCount - 1 do begin FVST.Header.Columns.Add; end; FVST.BeginUpdate; SetLength(sqlData^,FMySQL.SQLColCount); //SQLColCount ist 11 FVST.NodeDataSize := sizeof(sqlData); node := FVST.AddChild(nil); sqlData := FVST.GetNodeData(node); sqlData^[0] := 'Test'; //<-- Hier kommt eine exception Result := FMySQL.SQLRowCount; FVST.EndUpdate; end; Ich wäre froh, wenn mir hier jemand weiterhelfen könnte. Es geht um das Problem mit den Pointern. Irgendwas mache ich falsch ^^ Danke |
AW: Pointer wirrwarr. Bitte um hilfe
Deine Pointer zeigen ins Nirwana. Sieh Dir mal 'New' und 'Dispose' an...
Gruß Michael |
AW: Pointer wirrwarr. Bitte um hilfe
Zitat:
|
AW: Pointer wirrwarr. Bitte um hilfe
Zitat:
(Später dann wie gesagt mit Dispose die Arrays frei geben!) |
AW: Pointer wirrwarr. Bitte um hilfe
Oder man macht es wie im oberen Beispiel mit den Strings und packt einen Record um das Array. Dann muss man aber auch im OnFreeNode das Array wieder auf nil setzen.
Delphi-Quellcode:
type
TsqlData = record Data: array of string; end; PsqlData = ^TsqlData; procedure ...GetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin { Alle Nodes haben dieselbe DataSize! Aber nicht alle Nodes müssen zwingend dieselbe Array-Länge haben. } NodeDataSize := SizeOf(TsqlData); end; procedure ...FreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var sqlData:PsqlData; begin sqlData := Sender.GetNodeData(node); sqlData.Data := nil; end; function Query(Query: string):integer; var row,col:integer; node:PVirtualNode; sqlData:PsqlData; begin FMySQL.Query(Query); //SQLColCount ist 11 for col := 0 to FMySQL.SQLColCount - 1 do begin FVST.Header.Columns.Add; end; FVST.BeginUpdate; try node := FVST.AddChild(nil); sqlData := FVST.GetNodeData(node); SetLength(sqlData.Data,FMySQL.SQLColCount); //SQLColCount ist 11 sqlData[0] := 'Test'; finally FVST.EndUpdate; end; Result := FMySQL.SQLRowCount; end; |
AW: Pointer wirrwarr. Bitte um hilfe
Zitat:
Das hier funktioniert bei mir problemlos:
Delphi-Quellcode:
Es fehlt noch die Freigabe der dynamischen Arrays bei beenden.procedure TForm1.FormCreate(Sender: TObject); begin FVST.NodeDataSize := sizeof(PsqlData); end; procedure TForm1.Button1Click(Sender: TObject); var sqlData:PsqlData; node:PVirtualNode; begin node := FVST.AddChild(nil); sqlData := FVST.GetNodeData(node); SetLength(sqlData^, 2); sqlData^[0]:='Hallo'; sqlData^[1]:='Welt'; end; procedure TForm1.FVSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var sqlData:PsqlData; idx: Integer; begin sqlData := FVST.GetNodeData(Node); CellText := ''; if Assigned(sqlData) then begin for idx := 0 to length(sqlData^) - 1 do begin CellText := CellText + sqlData^[idx]; end; end; end; Ich wüsste auch nicht wo genau jetzt der Unterschied zwischen einem dynamischen Array und dem Record von Uwes Beispielcode sein soll. Es sind am Ende Variablen. Ich wäre echt dankbar, wenn mir jemand das erklären kann... |
AW: Pointer wirrwarr. Bitte um hilfe
Zitat:
|
AW: Pointer wirrwarr. Bitte um hilfe
Vielen Dank für eure Hilfe.
Dies habe ich nun verstanden und es hat auch geklappt! Nu habe ich gleich noch eine andere Frage zum selben Thema. Ich habe bei mir in der hauptunit ein ObjektA erstellt, welches ich im private bereich deklariert habe. Dieses erstelle ich beim öffnen der Anwendung. Während der Laufzeit, möchte ich mit diesem ObjektA arbeiten. Um mit diesem ObjektA arbeiten zu können, habe ich mir eine zweite Klasse geschrieben, welche die entsprechenden "bearbeitungs methoden" beinhaltet. Damit ich mit dieser Klasse arbeiten kann, muss ich davon ja auch ein ObjektB erstellen. Soweit so gut. Klappt auch. Nun möchte ich bei einem Button click, das ObjektB, welches mir Hilft ObjektA zu bearbeiten, erstellen -> verwenden -> und wieder freigeben. Hier gibts das Problem. Da ich bisher nicht ans freigeben gedacht habe, hab ich das erst jetzt bemerkt. Ich übergebe ObjektB folgendes beim Create:
Delphi-Quellcode:
Beim ObjectB.Free bekomme ich eine Exception.
FVST:TVirtualStringTree;
FMySQL:TmySQLe; constructor TeVCLqueryTable.Create(const VST: TVirtualStringTree; const MySQL:TmySQLe); begin FVST := VST; FMySQL := MySQL; ... Ich vermute mal, dass es dabei auch die übergebenen Objekte VST und MySQL freigegeben hat. Dann wäre mir klar, dass es nicht mehr funktioniert! Eigentlich möchte ich nur einen Pointer auf das ObjektA bzw. VST und MySQL damit ich mit diesen bereits existierenden Objekten innerhalb meines neuen Objektes arbeiten kann. Nach dem Freigeben von ObjektB sollen die Objekte VST und MySQL weiterleben. Könnte mir hier jemand weiterhelfen? Vielen Dank :) |
AW: Pointer wirrwarr. Bitte um hilfe
Hallo,
wie sieht denn der Destructor der Klasse TeVCLqueryTable (also von ObjectB) aus, den Constructor sehe ich ja. Heiko |
AW: Pointer wirrwarr. Bitte um hilfe
Bisher sieht der so aus:
Delphi-Quellcode:
Wie du an den kommentaren siehst, war ich mir nicht ganz sicher... ^^
destructor TeVCLqueryTable.Destroy;
begin //FVST := nil; //FMySQL := nil; inherited; end; |
AW: Pointer wirrwarr. Bitte um hilfe
Hallo,
das sind dann also Variablen deiner Klasse?
Delphi-Quellcode:
Wenn ja, brauchst du im Destructor gar nichts machen.
type
TeVCLqueryTable = class private FVST:TVirtualStringTree; FMySQL:TmySQLe; constructor TeVCLqueryTable.Create(const VST: TVirtualStringTree; const MySQL:TmySQLe); begin FVST := VST; FMySQL := MySQL; Gibst du das Objekt vielleicht aus Versehen 2mal frei? Heiko |
AW: Pointer wirrwarr. Bitte um hilfe
Ja, das sind variablen.
Nachfolgend das gesamte Interface
Delphi-Quellcode:
type
TsqlData = record Data: array of string; end; PsqlData = ^TsqlData; //Das war ein versuch. Wird nicht benutzt PmySQL = ^TmySQLe; Pvst = ^TVirtualStringTree; type TeVCLqueryTable = class private FVST:TVirtualStringTree; FMySQL:TmySQLe; FsearchMode:boolean; FsearchString:string; //FsqlData:array of string; procedure onGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure onFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure onBeforeCellPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect); public constructor Create(const VST:TVirtualStringTree; const MySQL:TmySQLe); destructor Destroy; override; function Query(Query:string):integer; procedure FilterNodes(const Text : string); end; implementation ... Nein, das wird nicht zweimal freigegeben. Sieht so aus:
Delphi-Quellcode:
Mit .free gibts direkt eine exception.
procedure TForm6.Button1Click(Sender: TObject);
var table:TeVCLqueryTable; begin //VirtualStringTree1 liegt als Objekt zur Designzeit auf dem Form //mysql ist eine Variable der Klasse TForm6 und wird zum Programmstart erstellt. table := TeVCLqueryTable.create(VirtualStringTree1, mysql); table.Query('SELECT * FROM rechnung'); table.Free; end; Ohne gibts keine und es funktioniert. Auch bei mehrmaligem klicken. |
AW: Pointer wirrwarr. Bitte um hilfe
Ich glaube es liegt daran:
Delphi-Quellcode:
Ich weise dem VirtualStringTree ein paar Proceduren und Funktionen zu, welche sich innerhalb des Objekts befinden.
constructor TeVCLqueryTable.Create(const VST: TVirtualStringTree; const MySQL:TmySQLe);
begin FVST := VST; FMySQL := MySQL; //Hier weise ich Funktionen und Proceduren zu, welche sich innerhalb des Objekts befinden. FVST.OnGetText := onGetText; FVST.OnFreeNode := onFreeNode; FVST.OnBeforeCellPaint := onBeforeCellPaint; FsearchMode := false; //Optische einstellungen treffen! //FVST.Header.AutoSizeIndex := 0; //, hoVisible, hoColumnResize, hoHeaderClickAutoSort FVST.Header.Options := FVST.Header.Options + [hoAutoResize]; FVST.TreeOptions.PaintOptions := [toShowRoot, toThemeAware]; //FVST.TreeOptions.AutoOptions := [toAutoChangeScale]; FVST.TreeOptions.MiscOptions := [toFullRepaintOnResize]; end; Wie dumm auch ^^ Dann ist es klar, dass es nach dem Free nicht mehr geht. Nun muss ich mir was überlegen, wie man dies am besten löst, so dass der VirtualStringTree weiterhin seine Daten anzeigt. |
AW: Pointer wirrwarr. Bitte um hilfe
Hallo,
dann darfst du die Klasse nicht freigeben, oder setzt die Events vor der Freigabe auf nil. Heiko |
AW: Pointer wirrwarr. Bitte um hilfe
Danke für deine Antwort.
Leider benötigt VirtualStringTree die Events um korrekt zu funktionieren. Da ich mehrere VSTs auf dem Formular habe, müsste ich für jedes ein eigenes privates Objekt innerhalb meiner Form erstellen. Das erscheint mir sehr unschön. Ich sollte vielleicht lieber eine Klasse machen, welche von VirtualStringTree ableitet und diese um meine Funktionen ergänzt. Idealerweise, könnte ich diese dann zur Designzeit auf das Formular ziehen. Mal sehen, ob ich ein Tutorial finde, welches mir erklärt, wie ich eine Komponente erstllen kann... By the way, wie kann man ein grosses Projekt übersichtlich halten? Soll man funktionen zu bestimmten bereichen in eigene units auslagern und diese manuell dort hin kopiere? |
AW: Pointer wirrwarr. Bitte um hilfe
Hallo,
deine einzelnen Darstellungs-Klassen für die einzelnen VSTs nennt man Renderer. Jeder VST bekomme seine eigene Renderer-Klasse und solange der VST existiert, muss die Renderer-Klasse existieren. Pro Renderer-Klasse bietet sich eine eigene Datei (Unit) an. Heiko |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:17 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