Форум: "Основная";
Текущий архив: 2002.02.07;
Скачать: [xml.tar.bz2];
ВнизПроблема с компонентой TTreeView и с указателями в частности. Найти похожие ветки
← →
Lipskiy (2002-01-22 00:32) [0]Господа! Есть проблема с компонентой TTreeView и с указателями в частности.
Возникает эксепшен, причем не всегда. Что я делаю неправильно?
Смысл кода таков.
Хочу реализовать событие по деселекту ноды (когда снимается выделение с нее).
Унаследовался от TTreeView.
Объявил указатель на запись с различными свойствами для каждой ноды в дереве (PntRec).
Одно из свойств - указатель на событие по деселекту (EOnDeSelect).
Есть еще много других свойств, их я здесь опускаю.
Внутри объекта объявил переменные SelNode (выбранная нода), PrevNode (предыдущая нода).
При добавлении ноды в дерево (sAddItem) назначаю обработчик.
Теперь, по событию Change (которое override) я обновляю SelNode и PrevNode и хочу вызвать обработчик на PrevNode.
Возникает ошибка (нарушение доступа...), причем не всегда, чаще всего срабатывает верно.
Sender эксепшена - TTimer, тот, что делат задержку вызова обработчика селекта новой ноды.
По всему видимо обращаюсь не в ту область памяти, но как это отловить?
И почему эта область уже не содержит нужного мне объекта?
М.б. что здесь некорректно или вообще неверно?
Буду признателен, а то затрахался уже ловить.
Вот код:
type
PntRec = ^TRec;
TRec = record
...
EOnDeSelect: TTVChangedEvent;
...
end;
var
RecPtr: PntRec;
TSTreeView = class (TTreeView)
private
...
SelNode,PrevNode:TTreeNode;
...
end;
implementation
function TSTreeView.sAddItem...
begin
New(RecPtr);
RecPtr^.EOnDeSelect:= OnDeSelect;
...
end;
procedure TSTreeView.Change(Node:TTreeNode);
begin
PrevNode:= SelNode;
SelNode:= Node;
...
if PrevNode <> nil then
if PrevNode.Data <> nil then
if Assigned(PntRec(PrevNode.Data)^.EOnDeSelect) then <-- здесь возникает ошибка
PntRec(PrevNode.Data)^.EOnDeSelect(Self,PrevNode);
...
end;
← →
Digitman (2002-01-22 08:29) [1]Ставь breakpoint на строчку
if Assigned(PntRec(PrevNode.Data)^.EOnDeSelect)
при останове на строчке вызывай контекстное меню "Evaluate/Modyfy.." и контролируй значения :
1.PrevNode
2.PrevNode.Data
3.PntRec(PrevNode.Data)^.EOnDeSelect
Одно из них будет равно nil, что и вызывает твой AV
← →
lipskiy (2002-01-22 09:33) [2]Если б все было так просто, то я б и не заморачивался писать. О том, как контролировать, я в курсе. Но вся фигня в том и состоит, что ни одно из них не nil. Да и условия стоят уже, они бы не пропустили...
← →
lipskiy (2002-01-23 21:22) [3]Так никто не подскажет?
← →
DMN (2002-01-24 11:53) [4]У объекта TTreeView кроме события OnChange есть событие OnChanging. Внутри обработчика данного события Node - тот узел, который пытаются выбрать, а TTreeView(Sender).Selected - тот узел, с которого выделение снимается. Можно запретить смену узла, сказав AllowChange := False...
← →
Digitman (2002-01-24 12:13) [5]Если не nil, значит, ссылка на то , что объектом не является. Попросту - "мусор". Где-то ты упустил момент, в который указательнужно было сбросить в nil после уничтожения объекта, ссылка на который и хранилась в указателе. Эта ссылка и стала "мусором", и ты на ней в результате "спотыкаешься" эпизодически. Выясняется - "мусор" это или не "мусор" - точно также : в отладчике при останове на строке, содержащей обращение по ссылке с подозрением на ее неактуальность - просто запросив в диалоге "ССЫЛКА Is TObject"
← →
Алексей Петров (2002-01-24 12:17) [6]Возможно причина такая:
TTreeView периодически перестраивает список Nodes полностью. С чем это связано - не знаю, но при этом, если ты сохранил указатель на некий TTreeNode - он становится не действительным и при обращении по нему естественный AV.
Для решения это проблемы нужно вместо указателей на Delphi-йские TTreeNode хранить Windows-ные идентификаторы этих узлов - они не меняются. Точного названия поля TTreeNode не помню - поищи в его описаннии.
Я сам налетел на эти грабли, делая FullScreen режим для формы, на которой лежал TreeView - при переходе туда-сюда начиналось...
← →
DMN (2002-01-24 12:29) [7]Точное название - Handle.
Но зачем так мучаться, когда всю эту обработку проще сделать в OnChanging?
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.02.07;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.005 c