Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.10;
Скачать: CL | DM;

Вниз

TTreeNode.Data - как правильно использовать?   Найти похожие ветки 

 
П7   (2004-09-20 10:00) [0]

Мастера, подскажите пожалуйста сабж.
Вот кусок кода:

type
 TMyRec = record
   field1 : integer;
   field2 : integer;
 end;

var
 Node : TTreeNode;
 MyRec : TMyRec;
begin
 Node := treList.Items.Add( nil, "Text" ); //treList : TTreeView
 // Заполняю MyRec
 MyRec.field1 := 77;
 Node.Data := @MyRec;
end;

Далее пытаюсь получить данные так:

var
 MyRec2 : TMyRec;
begin
 MyRec2 := TMyRec( treList.Selected.Data^ );
end;

В итоге иногда получаю нормальное значение, а иногда какую-то белиберду. Вероятно нужно как-то выделять память, хотя вроде бы присваивается указатель на переменную. Как быть?


 
Alx2 ©   (2004-09-20 10:04) [1]

У тебя заносится в Data указатель на переменную в стэке.
Естественно, никакой гарантии сохранности нет.
Объявление MyRec : TMyRec надо сделать глобальным.

А вообще гораздо чаще выделяют память.


 
KSergey ©   (2004-09-20 10:05) [2]

Надо выделить память (а не просто переменную, которая умирает после выхрда из ф-ции, где объявлена)
Записать указатель в Data
Где надо - использовать
После - не забыть всю память освободить.


 
Гаврила ©   (2004-09-20 10:06) [3]

type
PMyRec = ^TMyRec;
TMyRec = record
  field1 : integer;
  field2 : integer;
end;

var
Node : TTreeNode;
MyRec : PMyRec;
begin
Node := treList.Items.Add( nil, "Text" ); //treList : TTreeView
// Заполняю MyRec
New(MyRec);
MyRec.field1 := 77;
Node.Data := MyRec;
end;

И не забыть освободить потом память под запись (dispose)


 
П7   (2004-09-20 10:11) [4]

Эээ... Код условен. Запись объявляется глобально, как и переменная...
Вообще-то у меня есть класс...

 PP7TypeItem = ^P7TypeItem;
 P7TypeItem = record
   Typ : integer;
   // и т.д.
 end;

 P7TypeList = class
   Items : array of P7TypeItem;
   Count : Cardinal;

   function Add( item : P7TypeItem ) : PP7TypeItem;
   procedure Clear();
 end;

Есть глобальная переменная:

var
 TypeList : P7TypeList;

И если совсем точно, то делаю я так:

var
 ti : P7TypeItem;
 Node : TTreeNode;
begin
 Node := treList.Items.Add( nil, "Text" ); //treList : TTreeView
 ti.Typ := 0;
 // и т.д.
 Node.Data := QstTypeList.Add( ti );
end;

ВотЪ... После этого данные могут теряться, а могут и нет...


 
Erik1 ©   (2004-09-20 10:12) [5]

LOL
А ты знаеш, что такое область видимости переменых? MyRec уничтожается сразу после выполнения твоей процедуры! Делай так:
PMyRec = TMyRec^;
........
Procedute SetValue(Value: Integer);
var
Node : TTreeNode;
MyRec : PMyRec;
begin
New(MyRec);
MyRec.field1 := Value;
Node := treList.Items.Add( nil, "Text" );
Node.Data := MyRec;
....
Только незубудь при освобождении сделать Dispose(PMyRec(Node.Data));
Кроме того есть метод Items.AddObject и Help+example на TTreeNode.Data


 
П7   (2004-09-20 10:19) [6]


> Erik1 ©   (20.09.04 10:12) [5]

Сам ты ЛОЛ. Внимательнее ветку нужно читать. Код в первом посте достаточно условен... К тому же как ты мог заметить там нет ни одного слова, вроде function и procedure. Считай что это глобальные begin..end. Вот.

> Гаврила ©   (20.09.04 10:06) [3]

Спасибо, вроде как помогло, хотя ещё тестить нужно будет подольше...


 
Гаврила ©   (2004-09-20 10:45) [7]

Кстати, переменные эти должны быть именно локальными


 
Iconka ©   (2004-09-20 11:15) [8]

Псмотри в сторону TreeView.OnCreateNodeClass.
Создай потомок TTreeNode c нужными тебе дополнительными полями.


 
П7   (2004-09-22 09:38) [9]


> Iconka ©   (20.09.04 11:15) [8]

Вы можете поподробнее рассказать об TreeView.OnCreateNodeClass?


 
Miralex ©   (2004-09-22 10:10) [10]


> TTreeNode.Data - как правильно использовать?


В примерах уи тя в Delphi олжен валяться TreeDirDemo.
Там хорошо видно как можно использовать TTreeNode.Data!

Код:
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 ComCtrls, StdCtrls, FileCtrl, ImgList, Menus;

Type
 PDirFile = ^TDirFile;
 TDirFile = Record
   Path: String;
   Name: String;
   Time: Integer;
   Size: Integer;
   Attr: Integer;
   End;

type
 TForm1 = class(TForm)
   TreeView1: TTreeView;
   StatusBar1: TStatusBar;
   ImageList1: TImageList;
   PopupMenu1: TPopupMenu;
   Replace1: TMenuItem;
   Find1: TMenuItem;
   N2: TMenuItem;
   PasteSpecial1: TMenuItem;
   Paste1: TMenuItem;
   Copy1: TMenuItem;
   Cut1: TMenuItem;
   N3: TMenuItem;
   Repeatcommand1: TMenuItem;
   Undo1: TMenuItem;
   procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
   procedure FormCreate(Sender: TObject);
   procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode;
     var AllowExpansion: Boolean);
   procedure TreeView1Collapsed(Sender: TObject; Node: TTreeNode);
   procedure TreeView1Deletion(Sender: TObject; Node: TTreeNode);
   procedure TreeView1CustomDrawItem(Sender: TCustomTreeView;
     Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
 private
   Procedure AddNode(Const SR: TSearchRec; Const Path: String; Const Node: TTreeNode);
   Procedure AddRootNode(Const SR: TSearchRec; Const Path: String; Const RootName: String; Const Node: TTreeNode);
   Procedure ViewStatusBar(DF: TDirFile);
   Procedure GetDiskList(Var Value: String);

 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
Var
 DF: TDirFile;
begin
 If TreeView1.Visible And Assigned(TreeView1.Selected) Then Begin
   DF := TDirFile(TreeView1.Selected.Data^);
   ViewStatusBar(DF);
   End
end;

procedure TForm1.ViewStatusBar(DF: TDirFile);
begin
 StatusBar1.Panels[0].Text := Format("%s", [DF.Name]);
 StatusBar1.Panels[1].Text := Format("%d", [DF.Size]);
end;

procedure TForm1.FormCreate(Sender: TObject);
Var
 SR: TSearchRec;
 Disks: String;
 A: Shortint;
begin
//Form1.PopupMenu1.Items[1].Visible := false;

 With SR Do Begin
   Size := 0;
   Attr := faDirectory;
   End;
 GetDiskList(Disks); // Список существующих дисков
 //For A := 1 To Length(Disks) Do Begin
   SR.Name := "C:\Program Files\";
   AddRootNode(SR, "", "rootdir", Nil);
   SR.Name := "D:\Program Files\Borland\Delphi7\";
   AddRootNode(SR, "", "borlanddir", Nil);
   //End;
end;

procedure TForm1.AddRootNode(Const SR: TSearchRec; Const Path: String; Const RootName: String; Const Node: TTreeNode);
Var
 CNode: TTreeNode;
 P: PDirFile;
begin
 With SR Do If (Name = ".") Or (Name = "..") Then Exit;
 New(P);
 P^.Path := Path;
 P^.Name := SR.Name;
 P^.Time := SR.Time;
 P^.Size := SR.Size;
 P^.Attr := SR.Attr;
 CNode := TreeView1.Items.AddChildObject(Node, rootname, P);
 If (P^.Attr And faDirectory) <> 0 Then Begin
   CNode.HasChildren := True;
   CNode.ImageIndex := 2;
   CNode.SelectedIndex := 2;
   End
 else CNode.ImageIndex := 1;
end;

procedure TForm1.AddNode(Const SR: TSearchRec; Const Path: String; Const Node: TTreeNode);
Var
 CNode: TTreeNode;
 P: PDirFile;
begin
 With SR Do If (Name = ".") Or (Name = "..") Then Exit;
 New(P);
 P^.Path := Path;
 P^.Name := SR.Name;
 P^.Time := SR.Time;
 P^.Size := SR.Size;
 P^.Attr := SR.Attr;
 CNode := TreeView1.Items.AddChildObject(Node, P^.Name, P);
 If (P^.Attr And faDirectory) <> 0 Then Begin
   CNode.HasChildren := True;
   CNode.ImageIndex := 2;
   CNode.SelectedIndex := 2;
   End
 else CNode.ImageIndex := 1;
end;

procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
 var AllowExpansion: Boolean);
var
 DF: TDirFile;
 SR: TSearchRec;
begin
 If Node.getFirstChild <> Nil Then Exit;
 DF := TDirFile(Node.Data^);
 If (DF.Attr And faDirectory) = 0 Then Exit;
 DF.Path := DF.Path + DF.Name + "\";
 If FindFirst(DF.Path + "*", faAnyFile, SR) = 0 Then Begin
   AddNode(SR, DF.Path, Node);
   While FindNext(SR) = 0 Do
     AddNode(SR, DF.Path, Node);
   FindClose(SR);  // Освобождение ресурсов
   End;
end;

procedure TForm1.TreeView1Collapsed(Sender: TObject; Node: TTreeNode);
begin
 Node.DeleteChildren; // удаление дочерней ветки
 Node.HasChildren := True;
end;

procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
 Dispose(PDirFile(Node.Data)) // освобождение памяти для каждого из узлов
end;

procedure TForm1.GetDiskList(var Value: String);
Var
 A: Integer;
 A2: Cardinal;
Begin
 Value := "";
 A2 := GetLogicalDrives;
 For A := 2 To 31 Do
   If (A2 And (1 Shl A)) <> 0 Then
     Value := Value + Char(Ord("A")+A);
end;

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
 Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if cdsSelected in State then
 begin
 Sender.Canvas.Font.Style := Sender.Canvas.Font.Style + [fsUnderline];
 end;

end;

end.


 
Гаврила ©   (2004-09-22 10:28) [11]


> П7   (22.09.04 09:38) [9]
>
> > Iconka ©   (20.09.04 11:15) [8]
>
> Вы можете поподробнее рассказать об TreeView.OnCreateNodeClass?


type
 TMyTreeNode = class(TTreeNode)
   Fielld1, Field2: Integer;
 end;

//Событие TTreeView.OnCreateNodeClass

procedure TForm1.TreeView1CreateNodeClass(Sender: TCustomTreeView;
 var NodeClass: TTreeNodeClass);
begin
 NodeClass:=TMyTreeNode;
end;

После этого все узлы дерева на самом деле создаваться будут класса TMyTreeNode, и их можно смело типизировать под этот класс.

Действительно, этот вариант самый грамотный


 
П7   (2004-09-22 11:43) [12]


> Гаврила ©   (22.09.04 10:28) [11]

Спосибо, сейчас так и делаю, ошибок пока не обнаружил.
Вопрос закрыт.



Страницы: 1 вся ветка

Текущий архив: 2004.10.10;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.037 c
14-1095436250
Igorek
2004-09-17 19:50
2004.10.10
Проблема с сетевым принтером HP LaserJet 2300d


1-1095773917
vigo
2004-09-21 17:38
2004.10.10
Если кто работал с юлианской датой...


1-1096274224
DA
2004-09-27 12:37
2004.10.10
WebBrowser


1-1096263093
_alex_
2004-09-27 09:31
2004.10.10
Delphi And Visual c++


14-1095845753
Agent[007]
2004-09-22 13:35
2004.10.10
Паспорт