![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Господа, как можно "привязать" к TTreeNode номер записи
mmms © (2005-07-11 08:52:00)Т.е. предположим есть ветка в TTreeView "Продукты", от нее дочерние ноды "Колбаса", "Хлеб" и т.п. Нужно, чтобы юзер кликнул на "Хлеб", узнать, какой ID записи у "Хлеб", TTreeView заполняю записями из БД. Можно ли TTreeNode заполнить кроме Значениямиещё и скрытые параметры у каждого значения, например как Tagу многих компанетов, и потом, при клике на строку, определять этот параметр, а там всего цифровой код товара (по нему далее вся работа и идет).
Или, как вариант, по LIKE определять ID выбранной строки, но это лишняя нагрузка на БД, т.к. даже скольжение по TTreeView создаст множество запросов к серверу... хотя конечно, ID методом LIKE, по названию, можно не постоянно определять при скольжении, а например при двойном клике не этом товаре.
Т.е. вопрос, можно ли как то рядом с позицией в TTreeView "вбивать" ее код.
Ega23 (2005-07-18 16:43:00) [21]2 msguns © (18.07.05 16:42) [57]
И ЧТО он увидит ?
а ЧТО?????
evvcom (2005-07-18 16:43:00) [22]
> И ЧТО он увидит ?
"100"!
msguns (2005-07-18 16:42:00) [23]>Ega23 © (18.07.05 16:38) [55]
>ShowMessage(IntToStr(PInteger(tv.Items.Item[0].Data)^))
И ЧТО он увидит ?
evvcom (2005-07-18 16:38:00) [24]
> не компилится
В таком виде и не скомпилится, потому как Pointer нетипизированный указатель. Могу подсказать как скомпилится, но толку не будет никакого, потому что показывать надо обе стороны: и запись, и чтение. А по отдельности говорить об этом, значит опять AV получить с большой долей вероятности.
Ega23 (2005-07-18 16:38:00) [25]ShowMessage(IntToStr(PInteger(tv.Items.Item[0].Data)^))
mmms (2005-07-18 16:35:00) [26][50] msguns © (18.07.05 16:05)
msguns, благодарю, так и не получил, горе у меня :(, гроза была в четверг, комп вылетел, не успел почту принять, а аккаунт прописан только там, ладно ноут на гарантии, сдал, сейчас через интерфейс mail.ru зайду, приму.
А что у тебя там лежит - это ты, брат, сам знать должен. Если String, то
Спасибо Ega23, теперь понятно. Только строка ShowMessage(IntToStr(tv.Items.Item[0].Data^))не компилится, но сейчас разберусь.
evvcom (2005-07-18 16:15:00) [27]
> Никакой проблемы с DATA надо и работать, а не с копиями.
Я-то знаю, я автора предупреждаю.
Anatoly Podgoretsky (2005-07-18 16:10:00) [28]evvcom © (18.07.05 16:04) [49]
Никакой проблемы с DATA надо и работать, а не с копиями.
Ega23 (2005-07-18 16:07:00) [29]Вот только как обратится к памяти, где лежит Data, так и не понял :(
(tv.Items.Item[0].Data^)
А что у тебя там лежит - это ты, брат, сам знать должен. Если String, то
ShowMessage(tv.Items.Item[0].Data^),
если Integer, то
ShowMessage(IntToStr(tv.Items.Item[0].Data^))
и т.д.
msguns (2005-07-18 16:05:00) [30]>mmms
Ты смотрел то, что я посылал тебе ?
А если смотрел, то не мог не орбратить внимание на это :
type
// Описатели объектов справочника
PGR_Info = ^GR_Info; // Группа - узел TreeView
GR_Info = record
ID: integer; // ID группы
IDP: integer; // ID родителя группы
Txt: string; // Отображаемая метка группы
Lev: integer; // Уровень группы в дереве (0 для корневых)
ChQ: integer; // Кол-во непосредственных потомков ("деток")
end;
и это:
function TfrbaseSpr.GetGroupsInTreeView: boolean;
// Процедура извлечения информации о группах справочника в список и дерево
var
gline: PGR_Info;
i,j: integer;
begin
result := false;
sttAction.Caption := 'Загрузка дерева..';
sttOpStatus.Caption := '';
pnStatus.Update;
// Инициализация TreeView
trvSpr.Items.Clear;
GR_List.Clear;
with quTree do
try
if Active then Close;
Open;
First;
// Цикл по записям НД, полученного из записей справочника запросом со
// след.обязательными условиями:
// - Выбираются только записи групп (поле XXGROUP>'')
// - Записи упорядочены по PID, ID, т.е. "родители" раньше "детей"
// - Поля в НД следуют в след.порядке: IDP, ID, NAME
While not Eof do
begin
NEW(gline);
gline^.ID := Fields[1].AsInteger;
gline^.IDP := Fields[0].AsInteger;
gline^.Txt := Fields[2].AsString;
gline^.Lev := 0; // Уровень по умолчанию = корню
gline^.ChQ := 0; // Кол-во "детишек"
GR_List.Add(gline); // Добавить в список групп
Next;
end;
except
sttOpStatus.Caption := 'Ошибка чтения справочника';
end;
quTree.Close;
if GR_List.Count>0 then
// Загрузка из списка в TreeView
for i := 0 to GR_List.Count-1 do // Перебор списка сверху вниз
begin
gline := GR_List.Items[i];
if gline^.IDP=0 then // Узел не входит никуда, добавляем его "в корень" "дерева"
trvSpr.Items.AddObject(nil,gline^.Txt,gline)
else // Узел куда-то входит. Ищем "папашку" в TreeView
for j := 0 to trvSpr.Items.Count-1 do
if PGR_Info(trvSpr.Items[j].Data)^.ID=gline^.IDP then // Нашли !
begin
trvSpr.Items.AddChildObject(trvSpr.Items[j],gline^.Txt,gline); // Добавить как "дитя"
gline^.Lev := PGR_Info(trvSpr.Items[j].Data)^.Lev+1; // Уровень
inc(PGR_Info(trvSpr.Items[j].Data)^.ChQ); // Кол-во "детишек" у "папки"
break;
end;
end;
for i := 0 to trvSpr.Items.Count-1 do
begin // Рисуем рядом с наименованием узла "красивую" иконку
trvSpr.Items[i].ImageIndex := 1;
trvSpr.Items[i].SelectedIndex := 1; // Если false, то при выборке иконка не рисуется ;(
end;
if trvSpr.Items.Count>0 then
begin // Сортируем дерево по наименованиям узлов и первый делаем активным
trvSpr.CustomSort(@CustSortTreeNodes,0);
trvSpr.Selected := trvSpr.Items[0];
end;
sttAction.Caption := 'Просмотр';
pnStatus.Update;
end;
Кроме того, у Андрей Жук © (11.07.05 16:20) [23]
схема использования для хранения в дереве данных о записях аналогичная.
И заключается в том, что объявляем объект (record), типизированныйуказатель на него и добавляем в TTreeView указательна этот объект. При извлечении информации из "дерева" (св-во Data) используем явное преобразованиек нужному типу и корректно работаем с любымиданными объекта.
evvcom (2005-07-18 16:04:00) [31]Объясни, наконец, что ты хочешь? К ноду привязать стринг, а потом его где-то использовать? Ну так и пиши:
tv.Items[0].Data := Pointer(MyString);
читай:
ShowMessage(string(tv.Items[0].Data));
Только надо быть осторожным. Любое присвоение переменной MyString, после того как она была запомнена в Data, может сделать этот указатель (Data) недействительным, и опять получишь AV при попытке чтения данных по указателю Data.
mmms (2005-07-18 15:54:00) [32][46] Ega23 © (18.07.05 15:33)
Да, у меня только значения не меняются, и хочется ТОЛЬКО считать это значение.
Так, что ли? :(
Showmessage(String(PInt(tv.Items.Item[0].Data)));
Ошибка Access...
Интересно тоже:
Showmessage(Pchar(@tv.Items.Item[0].Data));
Выдает букву "D"
Вот только как обратится к памяти, где лежит Data, так и не понял :(
Anatoly Podgoretsky (2005-07-18 15:37:00) [33]mmms (18.07.05 15:17) [44]
А что ему еще выдавать, что бы это были универсальные данные? Ты знаешь такой тип?
Ega23 (2005-07-18 15:33:00) [34]Вот смотри:
var
p:PInteger;
i:Integer;
begin
New(p); // Чему сейчас равно значение p? Это может быть что угодно, например $364F5CAD
// Так вот, это - адрес Integer'а
i:=6; //
p^:=i; // Значение ПО АДРЕСУ изменилось, но значение АДРЕСА - нет.
end;
mmms (2005-07-18 15:18:00) [35]Но там лежит Integer...
mmms (2005-07-18 15:17:00) [36]Причем тут каша, я столкнулся с единственным препятствием, может мне теперь и застрелится ещё :) Спрашиваю, если это не сложно, то хотелось бы получить ответ, как прочитать этот Data. На счет ф-и IntToStr, но куда ее тут применить? Ega23, всмотритесь внимательно в код. Data возвращает Pointer а не Integer.
Ega23 (2005-07-18 15:09:00) [37]2 mmms (18.07.05 14:59) [40]
Разобрался.. Ложу Integer, (код [2] mmms (11.07.05 09:00)), как этот интегер считать?
Чтобы показать Integer в виде строки, воспользуйся функцией IntToStr.
А вообще у тебя полная каша в голове. Тебе надо сначала разобраться и понять, что такое адрес и значение по адресу.
evvcom (2005-07-18 15:07:00) [38]А что ты хотел увидеть? Ты преобразовываешь $64 к указателю на строку. Естественно? при чтении по адресу $64 ты получаешь AV. Ложить надо туда валидный указатель на строку, чтобы так читать.
mmms (2005-07-18 14:59:00) [39]Ну и тут же ошибка.. Access...
mmms (2005-07-18 14:59:00) [40]Блин, ты сначала разберисть, что ты в tv.Selected.Data раньше положил. В каком виде?
Разобрался.. Ложу Integer, (код [2] mmms (11.07.05 09:00)), как этот интегер считать?
В режиме отладки посмотрел, tv.Items.Item[0].Data=$64,
procedure TForm1.tvClick(Sender: TObject);
begin
if tv.Items.Item[0].Data<> nil then
Showmessage(PChar(tv.Items.Item[0].Data)); //=$64
end;