![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Указатель на Record при добавлении узлов в TreeView [D6, MS ACCESS]
Dr. Andrey © (2004-11-02 09:16:00)Справочник подразделений на нем TreeView.
Заполняем из RST: Recordset
...
wA,wB,wC: Word; sS: String;
...
With RST do begin
while not Eof do begin
wA:= Fields[0].Value; //Код подразделения-родителя
wB:= Fields[1].Value; //Код подразделения
wC:= Fields[2].Value; //Код вида учета
sS:= Fields[3].Value; //Наименование подразделения
Для поиска родительского узла написал функцию FindUzel
MyNode:= TreeView1.Items.AddChildObject(FindUzel(pWordwA)), sS, PWord(wB));
end;
end;
function TForm_Derevo.FindUzel(pP:Pointer):TTreeNode;
var W: Word;
begin
if pP = nil then begin Result:= nil; Exit; end;
for W:= 0 to TreeView1.Items.Count-1 do
if pP = TreeView1.Items.Item[W].Data then begin result:= TreeView1.Items.Item[W]; break; end;
end;
Всё работает. Но в Data узлов нужно передавать указатель не на число (КодПодразделения), а на запись(КодПодразделения и КодВидаУчета.
Для этого описал тип данных PMyTVrec
MyTVrec= Record
X: Word;
Y: Word;
end;
PMyTVrec = ^MyTVrec;
в процедуре заполнения дерева:
...
PN: PMyTVrec
New(PN); PN^.X:= wB; PN^.Y:= wC;
MyNode:= TreeView1.Items.AddChildObject(FindUzel(pWordwA)), sS,PN);
...
function TForm_Derevo.FindUzel(pP: PMyTVrec):TTreeNode;
var W: Word;
begin
if pP = nil then begin Result:= nil; Exit; end;
for W:= 0 to TV_Derevo.Items.Count-1 do
if WORD(pP)= PMyTVrec(TreeView1.Items.Item[W].Data)^.X then
begin
Result:= TreeView1.Items.Item[w];
Break;
end;
end;
При отладке значение PMyTVrec(TreeView1.Items.Item[W].Data)^.X = 0
Пробовал передавать в FindUzel число, а не указатель, но причина не в этом.
При циклическом обходе узлов в дереве функция находит нужный узел, но почему PMyTVrec(TreeView1.Items.Item[W].Data)^.X = 0?
Почему FindUzel работает в первом случае.
сергей1 (2004-11-02 16:47:00) [1]Может я чего-то не понимаю в этой жизни, но работа с TreeView прекрасно обходиться без указателей и прочей лабуды.
Есть таблица, в которой храниться эта структура в виде (к примеру)
-Код элемента
-Название элемента
-Код родителя
Закачиваем их в treeview при помощи функций TreeView1.Items.Add, TreeView1.Items.AddChild().
Перемещаемся по дереву при помощи GetNext(), GetNextChild(), getFirstChild, getLastChild.
Также имеются полезные функции HasChildren, Parent.
Практически все что надо, решается этими функциями.
А то какие-то указатели ...
}|{yk (2004-11-02 15:13:00) [2]
{
Формат елементів усіх дерев
mem_id - обовязково. Ідентифікатор елемента
mem_pid - обовязково. Ідентифікатор "батьківського" елемента
is_leaf - обовязково. Ознака, чи є елемент елементом нижнього рівня
outlevel - обовязково. Рівень елемента
mem_order - обовязково. Порядковий номер в структурі
mem_name - обовязково. Назва елемента
mem_desc - обовязково. Описання елемента
mem_type - не обовязково. Тип елемента
}
type
TMyTreeNodes = record
mem_id: integer;
mem_pid: integer;
is_leaf: boolean;
outlevel: integer;
mem_order: integer;
mem_name: string;
mem_desc: string;
mem_type: string;
changing: boolean; // чи змінювалися дані в обєкті
inserting: boolean; //чи є обєкт доданим (без відображення в базі)
ParentNode: TTreeNode;
end;
PTMyTreeNodes = ^TMyTreeNodes;
function TFrameBase.GenerateTree(Tree: TTreeView; DataSet: TDataSet): TFunctionResult;
var
FunctionResult: TFunctionResult;
vData: PTMyTreeNodes;
Node, LastNode: TTreeNode;
begin
Result.Successful := false;
// якщо дерево чи датасет не ініціалізовані, зупинити виконання
if not Assigned(Tree) or not Assigned(DataSet) then
begin
Result.MessageOnError := 'Programmer error - not initilized objects on creating tree';
Exit;
end;
// якщо датасет не активний, то зупинити виконання
if not DataSet.Active then
begin
Result.MessageOnError := 'Programmer error - not activated Dataset';
Exit;
end;
// очистимо дерево, якщо помилка зупинити виконання
FunctionResult := ClearTree(Tree);
if not FunctionResult.Successful then
begin
Result.MessageOnError := FunctionResult.MessageOnError;
Exit;
end;
// заповнимо дерево
with DataSet do
begin
LastNode := nil;
First;
while not Eof do
begin
New(vData); // створимо елемент
with vData^ do
begin
// заповнюємо його поля
try
mem_id := FindField('mem_id').AsInteger;
mem_pid := FindField('mem_pid').AsInteger;
is_leaf := boolean(FindField('is_leaf').AsInteger);
outlevel := FindField('outlevel').AsInteger;
mem_order := FindField('mem_order').AsInteger;
mem_name := FindField('mem_name').AsString;
mem_desc := FindField('mem_desc').AsString;
if Assigned(FindField('mem_type')) then
mem_type := FindField('mem_type').AsString
else
mem_type := 'general';
changing := false;
inserting := false;
except on E: Exception do
begin
Result.MessageOnError := 'Programm error - incompatible structure' + #10#13 + 'Details: ' + E.Message;
Exit;
end;
end;
// якщо це елемент верхнього рівня, то додамо його в корінь
if vData.outlevel = 1 then
begin
Node := Tree.Items.Add(nil, vData^.mem_desc);
vData.ParentNode := nil;
end
// якщо елемент нижчого рівня, то додати як "сина"
else if PTMyTreeNodes(LastNode.Data)^.outlevel < vData.outlevel then
begin
Node := Tree.Items.AddChild(LastNode, vData^.mem_desc);
vData.ParentNode := LastNode;
end
// якщо елемент одного рівня, то додати як "брата"
else if PTMyTreeNodes(LastNode.Data)^.outlevel = vData.outlevel then
begin
Node := Tree.Items.AddChild(LastNode.Parent, vData^.mem_desc);
vData.ParentNode := LastNode.Parent;
end
// якщо елемент вищогого рівня, то знайти "підходящого батька" та додати як "сина"
else if PTMyTreeNodes(LastNode.Data)^.outlevel > vData.outlevel then
begin
while PTMyTreeNodes(LastNode.Data)^.outlevel >= vData.outlevel do
LastNode := LastNode.Parent;
Node := Tree.Items.AddChild(LastNode, vData^.mem_desc);
vData.ParentNode := LastNode.Parent;
end;
// занесення даних до структури
Node.Data := vData;
LastNode := Node;
Next;
end;
end;
end;
Result.Successful := true;
end;
Семен Сорокин (2004-11-02 15:06:00) [3]
> Dr. Andrey (02.11.04 14:29) [4]
Покажите весь код процедуры заполнения дерева
Dr. Andrey (2004-11-02 14:29:00) [4]>Семён Сорокин
Извините, это была опечатка. Должно быть так:
function TForm_Derevo.FindUzel( pP: PWord):TTreeNode;
Семен Сорокин (2004-11-02 09:55:00) [5]
> В FindUzel я передаю указатель только на код подразделения
> PWord (wA).
PWord(wA) - это не указатель, это приведение числа к типу PWord, указатель будет: @wA
опять же если Вы передаете PWord, то почему объявление ф-ции:
function TForm_Derevo.FindUzel( pP: PMyTVrec):TTreeNode;
Вы разберитесь и напишите правильно, что нужно и что не получается.
Dr. Andrey (2004-11-02 09:46:00) [6]MyNode:= TreeView1.Items.AddChildObject(FindUzel( pWord(wA)), sS,PN);
В FindUzel я передаю указатель только на код подразделения PWord (wA). Хотя пробовал и предлагаемый Вами вариант, т.е. передавать указатель типа PMyTVRec, пробовал передавать и число - эффект тот-же
Семен Сорокин (2004-11-02 09:39:00) [7]if WORD(pP)= PMyTVrec(TreeView1.Items.Item[W].Data)^.X then
может так надо:
if pP^.X = PMyTVrec(TreeView1.Items.Item[W].Data)^.X then