![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TTreeNode.Data - как правильно использовать? [D7, Win2k, WinXP]
П7 © (2004-09-20 10:00:00)Мастера, подскажите пожалуйста сабж.
Вот кусок кода:
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;
В итоге иногда получаю нормальное значение, а иногда какую-то белиберду. Вероятно нужно как-то выделять память, хотя вроде бы присваивается указатель на переменную. Как быть?
П7 (2004-09-22 11:43:00) [1]
> Гаврила © (22.09.04 10:28) [11]
Спосибо, сейчас так и делаю, ошибок пока не обнаружил.
Вопрос закрыт.
Гаврила (2004-09-22 10:28:00) [2]
> П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, и их можно смело типизировать под этот класс.
Действительно, этот вариант самый грамотный
Miralex (2004-09-22 10:10:00) [3]
> 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.
П7 (2004-09-22 09:38:00) [4]
> Iconka © (20.09.04 11:15) [8]
Вы можете поподробнее рассказать об TreeView.OnCreateNodeClass?
Iconka (2004-09-20 11:15:00) [5]Псмотри в сторону TreeView.OnCreateNodeClass.
Создай потомок TTreeNode c нужными тебе дополнительными полями.
Гаврила (2004-09-20 10:45:00) [6]Кстати, переменные эти должны быть именно локальными
П7 (2004-09-20 10:19:00) [7]
> Erik1 © (20.09.04 10:12) [5]
Сам ты ЛОЛ. Внимательнее ветку нужно читать. Код в первом посте достаточно условен... К тому же как ты мог заметить там нет ни одного слова, вроде function и procedure. Считай что это глобальные begin..end. Вот.
> Гаврила © (20.09.04 10:06) [3]
Спасибо, вроде как помогло, хотя ещё тестить нужно будет подольше...
Erik1 (2004-09-20 10:12:00) [8]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:11:00) [9]Эээ... Код условен. Запись объявляется глобально, как и переменная...
Вообще-то у меня есть класс...
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;
ВотЪ... После этого данные могут теряться, а могут и нет...
Гаврила (2004-09-20 10:06:00) [10]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)
KSergey (2004-09-20 10:05:00) [11]Надо выделить память (а не просто переменную, которая умирает после выхрда из ф-ции, где объявлена)
Записать указатель в Data
Где надо - использовать
После - не забыть всю память освободить.
Alx2 (2004-09-20 10:04:00) [12]У тебя заносится в Data указатель на переменную в стэке.
Естественно, никакой гарантии сохранности нет.
Объявление MyRec : TMyRec надо сделать глобальным.
А вообще гораздо чаще выделяют память.