Форум: "Основная";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.052 c