|
Antwort |
Registriert seit: 19. Apr 2005 18 Beiträge |
#1
Hallo,
seit einiger Zeit benutze ich Delphi und beschäftige mich zur Zeit mit dem VirtualStringTree. Im Internet habe ich ein interresantes Beispiel gefunden, das mit dem ClientDataSet arbeitet. Ich würde gern eine Accessdatenbankverbindung über AdoConnection und BetterADODataSet herstellen. Das Problem liegt in der Methode FindKey, die nicht unterstützt wird. Mit Seek habe ich leider keinen Erfolg gehabt. Ich poste mal den Sourcecode.
Code:
Hier die entscheidende Procedure
unit VTDBExample;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, VirtualTrees, StdCtrls, ExtCtrls, Provider, DB, DBClient, Menus, ImgList, Grids, DBGrids, ADODB, BetterADODataSet; type TBasicNode = class protected FCaption : shortstring; FID : longint; FImageIndex : longint; FHasChanged : boolean; public constructor Create( const sCaption : shortstring; const iID, iIndex: longint); property Caption : shortstring read FCaption write FCaption; property ID : longint read FID write FID; property ImageIndex : longint read FImageIndex write FImageIndex; property HasChanged : boolean read FHasChanged write FHasChanged; end; TBasicNodeAdd = class(TBasicNode) protected FJobTitle : shortstring; FAdd1 : shortstring; FAdd2 : shortstring; FAdd3 : shortstring; public property Add1 : shortstring read FAdd1 write FAdd1; property Add2 : shortstring read FAdd2 write FAdd2; property Add3 : shortstring read FAdd3 write FAdd3; property JobTitle : shortstring read FJobTitle write FJobTitle; end; PTreeData = ^TTreeData; TTreeData = record FObject : TBasicNode; end; type TfrmVTDBExample = class(TForm) Label1: TLabel; cds: TClientDataSet; Panel1: TPanel; VT: TVirtualStringTree; imgMaster: TImageList; cds3: TBetterADODataSet; ADOConnection1: TADOConnection; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var Text: WideString); procedure VTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure VTInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); procedure FormActivate(Sender: TObject); procedure VTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); procedure VTCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); procedure VTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); procedure VTInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal); private procedure LoadCDS; end; implementation {$R *.DFM} constructor TBasicNode.Create( const sCaption : shortstring; const iID, iIndex: longint); begin inherited Create; FCaption := sCaption; FID := iID; FImageIndex := iIndex; end; const FLDN_CustNo = 0; FLDN_Company = 1; FLDN_Addr1 = 2; FLDN_Addr2 = 3; FLDN_City = 4; FLDN_State = 5; FLDN_Zip = 6; FLDN_Country = 7; FLDN_Phone = 8; FLDN_FAX = 9; FLDN_TaxRate = 10; FLDN_Contact = 11; FLDN_LastInvoiceDate = 12; procedure TfrmVTDBExample.FormActivate(Sender: TObject); var r : TRect; begin SystemParametersInfo(SPI_GETWORKAREA, 0, @r, 0); Height := r.Bottom-Top; Width := r.Right-Left; Application.ProcessMessages; LoadCDS; end; procedure TfrmVTDBExample.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; procedure TfrmVTDBExample.LoadCDS; var Node : PVirtualNode; begin with cds do begin VT.BeginUpdate; try FileName := 'customer.cds'; Active := True; IndexFieldNames := 'CustNo'; while not eof do begin Node := VT.AddChild(nil); VT.ValidateNode( Node, False ); Next; end; finally VT.EndUpdate; end; end; end; procedure TfrmVTDBExample.VTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin NodeDataSize := SizeOf(TTreeData); end; procedure TfrmVTDBExample.VTInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); var Data : PTreeData; iImage : integer; begin Data := Sender.GetNodeData(Node); iImage := -1; if Sender.GetNodeLevel( Node ) = 0 then begin iImage := 3; if (Node.Index < 10) then begin iImage := 31; InitialStates := InitialStates + [ivsHasChildren]; end; end; Data.FObject := TBasicNodeAdd.Create( cds.Fields[FLDN_Company].AsString, cds.Fields[FLDN_CustNo].AsInteger, iImage ); end; procedure TfrmVTDBExample.VTInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal); begin ChildCount := 1; end; procedure TfrmVTDBExample.VTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var Data: PTreeData; begin Data := Sender.GetNodeData(Node); Data.FObject.Free; Finalize( Data^ ); end;
Code:
procedure TfrmVTDBExample.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var Text: WideString); var Data : PTreeData; FObject : TBasicNodeAdd; iLevel : integer; begin Text := ''; Data := Sender.GetNodeData(Node); if Assigned(Data) and (Data.FObject <> nil) then with Data.FObject do begin iLevel := Sender.GetNodeLevel( Node ); case Column of 0: begin case TextType of ttNormal: begin if iLevel = 0 then begin Text:=Caption end else begin if cds.FindKey([ID]) then with cds do Text := Trim( Fields[ FLDN_Addr1 ].AsString + ' ' + Fields[ FLDN_Addr2 ].AsString + ' ' + Fields[ FLDN_City ].AsString + ' ' + Fields[ FLDN_State ].AsString + ' ' + Fields[ FLDN_Zip ].AsString + ' ' + Fields[ FLDN_Country ].AsString ); end; end; ttStatic: begin Text := ''; end; end; end; 1: begin FObject := TBasicNodeAdd( Data.FObject ); case TextType of ttNormal: begin if (iLevel = 0)and cds.FindKey([ID]) then with cds do Text := Fields[ FLDN_Contact ].AsString; end; end; end; 2: begin if TextType = ttNormal then Text := ' '; end; end; end; end;
Code:
procedure TfrmVTDBExample.VTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind;
Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); var Data : PTreeData; iLevel: integer; begin ImageIndex := -1; Data := Sender.GetNodeData(Node); iLevel:= Sender.GetNodeLevel( Node ); if (Column = 2 ) then begin if ( Kind in [ ikNormal, ikSelected ] ) and (iLevel=0) then ImageIndex := 20 end else if Assigned(Data) and (Data.FObject <> nil) and (Column = 0) then ImageIndex := Data.FObject.ImageIndex; end; procedure TfrmVTDBExample.VTCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); var Data1 : PTreeData; Data2 : PTreeData; begin Data1 := Sender.GetNodeData(Node1); Data2 := Sender.GetNodeData(Node2); case Column of 0: Result := CompareText( Data1.FObject.Caption, Data2.FObject.Caption ) end; end; end. |
Zitat |
Registriert seit: 24. Mär 2004 Ort: bei Hannover 2.416 Beiträge Delphi XE5 Professional |
#2
du hast die vcl und den vst nicht verstanden...
FormActivate wird immer dann aufgerufen wenn die anwendung bzw. das formular den focus erhält. (dunkelblauber form titel bei w2k) dort den tree zu initialisieren ist nicht das klügste. jedesmal wenn wieder in die anwendung geswitcht wird (z.b. mit alt-tab), wird der tree initialisiert. (es sei den du hast das gewollt, dann nehme ich das mit dervcl zurueck) besser im onCreate zum tree: dieser gekommt gesagt wie gross die daten sind. (nodedatasize) normal nimmt man dort record weil diese haben eine feste groesse. in meinen projekte nehme ich objekte -> nodedatasize ist dann die groesse des pointer auf das objekt jetzt gibt es mehrere möglichkeiten den tree zu füllen. a) du laeuft durch eine schleife so oft wie datensätze da sind und kopierst diese in ein passendes record oder in ein objekt und fügst diese dann mit addchild+daten hinzu. deine load routine (loadcds) ist also irgendwie am ziel vorbei b) man baut die struktur zusammen und lässt dann die knoten per initnode füllen. nur knoten die angezeigt werden werden dann auch initialisiert (geladen aus der datenbank). methode b) hat einen grossen geschwindigkeitsvorteil. wenn du rootnodecount angibst wird gleich der noetige speicherplatz (für die records) belegt. geladen werden nur die die angezeigt werden. egal welche methode du verwendest - du brauchst nur firecursors (readonly, forwardonly) langsames cursorspringen mit locate, filter usw braucht man nicht. im gettext gibt man eigendlich dann nun noch den record bzw obj aus (welches sich dann im speicher befindet). langsame datenbankoperation führt man dort eigendlich nicht aus. gruss |
Zitat |
Registriert seit: 19. Apr 2005 18 Beiträge |
#3
Hallo generic,
zunächst mal Danke, dass du dich mit meinem Problem auseinandersetzt. Es stimmt, dass ich den VST noch nicht richtig verstanden habe, deshalb versuche ich dieses Beispielprogramm zu analysieren und auf andere Datenbanken umzusetzen. Der Code stammt nicht von mir, sondern gehört zu der Anwendung VTBasic/Database Example 1, die ich unter folgender Adresse heruntergeladen habe: Extensive Basic Demo Mein Problem liegt in der Methode FindKey, die ich mit ADO nicht benutzen kann. Gruß u. |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |