Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

TVirtualStringTree & TList

6
13 октября 2009 года
George
4.1K / / 05.01.2007
Вот в общем какая задача. Есть у меня свой класс TNodeCollection - наследник от TList. Хранит ссылки на объекты типа TNode - тоже мой класс. У типа TNode есть поле Name, в общем нужно создать дерево узлов в TVirtualStringTree и к каждому узлу "привязать" текст - это то самое поле Name.
Саму древовидную конструкцию я делаю. Ноды добавляются вот таким способом:
[highlight=delphi]
{ CurNode - это указатель на родительскую ноду в ДЕРЕВЕ, FCollection - указатель на текущую ноду в КОЛЛЕКЦИИ. }
ProductsTree.AddChild(CurNode, FCollection);
[/highlight]
Работает оно так, что создает дочернюю для CurNode ноду, и помещает в нее ссылку на ноду в коллекции. Причем у VirtualStringTree есть поле, где хранится размер ссылки, чтобы потом его нормально достать. Поэтому при создании ссылки я указываю этот размер:
[highlight=delphi]
ProductsTree.NodeDataSize := SizeOf(TNode);
[/highlight]
Далее чтобы узлам присвоить текст делаю так:
[highlight=delphi]
procedure TMainForm.ProductsTreeGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
ANode: Pointer;
begin
ANode := ProductsTree.GetNodeData(Node);
if Assigned(ANode) then
CellText := TNode(ANode).Name;
end;
[/highlight]
Вроде все правильно, но при попытке привести указатель к типу TNode - вылететает старый добрый AV. Похоже что перемудрено с указателями.

Постарался объяснить подробно, но если возникнут вопросы - готов ответить. Что то запарка...
6
13 октября 2009 года
George
4.1K / / 05.01.2007
хм, я вот так думаю, что мне придется разбираться самому, уж больно запутанный код с кучей преобразований типов, весь его выкладывать нецелесообразно.
288
13 октября 2009 года
nikitozz
1.2K / / 09.03.2007
Ну первое, что приходит в голову: а в FCollection указатели точно валидные?
303
13 октября 2009 года
makbeth
1.0K / / 25.11.2004
Что-то ты походу перемудрил с VirtualTreeView. Насколько я помню, там все завязано на тип record, у тебя же везде используются классы. Видимо, там где-то нестыковка с ссылкой на класс и указателем на данные типа record. Кури маны по виртуалу внимательнее.
6
13 октября 2009 года
George
4.1K / / 05.01.2007
Цитата: nikitozz
Ну первое, что приходит в голову: а в FCollection указатели точно валидные?


да, нормальные там указатели.

Цитата: makbeth
Что-то ты походу перемудрил с VirtualTreeView. Насколько я помню, там все завязано на тип record, у тебя же везде используются классы. Видимо, там где-то нестыковка с ссылкой на класс и указателем на данные типа record. Кури маны по виртуалу внимательнее.


это я видел. но думал, что должно проканать и с ссылками на экземпляры классов. это ж иначе как компонент то юзать? лажа, факт. заменил на обычный TTreeView, а фигли делать.

303
14 октября 2009 года
makbeth
1.0K / / 25.11.2004
Цитата: Washington
лажа, факт. заменил на обычный TTreeView, а фигли делать.


Ты просто не умеешь его готовить :D Там на самом деле сделано все нормально. Как ты думаешь, зачем нужен размер структуры в ноде? Чтобы выделять и освобождать память посредством New/Dispose. Как-то так...

6
14 октября 2009 года
George
4.1K / / 05.01.2007
ну это понятно. собственно предложили такое решение:
[highlight=delphi]
type
PMyRec = ^TMyRec;
TMyRec = record
NodeData: Pointer;
end;
[/highlight]
Ну собственно NodeData - указатель на объект в коллекции. Попробую так.
14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
Только единственный указатель облачать в структуру совершенно ни к чему :)
6
14 октября 2009 года
George
4.1K / / 05.01.2007
а как иначе? если оно только со структурой работает...
14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
М-м-м.. А покажи мне где именно оно требует структуру?
6
14 октября 2009 года
George
4.1K / / 05.01.2007
нигде. но без рекорда не работает и все. =) когда вместо указателя на структуру даю ему указатель на объект в коллекции - получается левак. через этот указатель потом я не могу получить доступ к объекту в коллекции. вылетает АВ.
14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
Да надо дать адрес того указателя что сейчас у тебя в структуре лежит и все :) (и так ясно что адрес структуры этой = адресу лежащего в ней единственного указателя)
А с объектом не работает т.к. память по указателю на объект <> памяти по указателю на структуру.
И всеж я б вообще сделал без NodeData. Правда, подробностей о формировании дерева не знаю..
Впрочем, делай как тебе понятнее :)
6
14 октября 2009 года
George
4.1K / / 05.01.2007
опа. то есть надо передать не FCollection, а ^FCollection?
14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
Я это говорил про последний вариант, где TMyRec = record NodeData: Pointer; end;
А ты все-равно думаешь по старому.
FCollection - указатель на объект
FCollection^ - сам объект
ANode := ProductsTree.GetNodeData(Node) - указатель на структуру размером
.NodeDataSize := SizeOf(TNode) = вообще 4. Ибо класс, объект - суть указатель.
TNode ж у тебя класс, я ничего не путаю?
6
14 октября 2009 года
George
4.1K / / 05.01.2007
TNode - да, класс. Только я все ж не могу понять тебя. Пример в виде кода хоть приведи что-ли. А то я уже запутываюсь в этих указателях, ссылках и адресах. )))
14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
вот. я так не делаю и не советую, но примера ради..
кривости присутствуют но не до них
Код:
unit FormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Contnrs, VirtualTrees;

type
  TfrmMain = class(TForm)
    vstData: TVirtualStringTree;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure vstDataGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType;
      var CellText: WideString);
  private
    { Private declarations }
    FList: TObjectList;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ TfrmMain }

procedure TfrmMain.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  { Действия при создании формы / запуске приложения }
  FList := TObjectList.Create;
  for i := 0 to 99 do
  begin
    FList.Add(TStringList.Create);
    TStringList(FList).Text := IntToStr(i + 1);
  end;

  vstData.NodeDataSize := sizeof(Pointer);
  for i := 99 downto 0 do
  begin
    vstData.AddChild(vstData.RootNode, FList); //исп. только первые 4 байта переданного <буфера>. Остальное разве что в InitNode
  end;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  { Действия при разрушении формы / закрытии приложения }
  FList.Free;
end;

procedure TfrmMain.vstDataGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
  P: ^TStringList;
begin
  P := vstData.GetNodeData(Node);
  CellText := P.Text;
end;

end.
6
14 октября 2009 года
George
4.1K / / 05.01.2007
Изменил:
[highlight=delphi]
procedure TMainForm.ProductsTreeGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
ANode: ^TNode;
begin
ANode := ProductsTree.GetNodeData(Node);
if Assigned(ANode) then
CellText := ANode^.Name;
end; [/highlight]
Работает. :)
Видимо из за пробелов в знаниях по поводу операторов ^, @ и всяких указателей.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог