Здравствуйте! Есть тема "Иерархия структуры таблицы Менделеева", в пределах которой нужно построить иерархию объектов, состоящей как минимум из 3-х уровней. Для демонстрации работы построенной иерархии классов, создаётся приложение, позволяющее: создавать, удалять объекты, изменять характеристики объектов, визуализировать объекты, манипулировать на форме объектами, сохранять/считывать текущее состояние объектов в формате XML.
Есть некоторые задумки насчёт иерархии (изображение)...Может кто-нибудь подскажет другой подход? Ну а прежде всего - трудности с визуализацией и манипулированием объектами...Может быть у кого-нибудь есть идеи, как для начала идейно подойти к этим вопросам? что можно придумать? Подскажите пожалуйста..!
volvo
4.12.2008 21:30
Цитата
прежде всего - трудности с визуализацией и манипулированием объектами
Какие именно трудности возникли? Какими компонентами ты пользуешься для визуализации? То, что ты привела - это же TTreeView в чистом виде. Пробовала его?
Для манипулирования узлами дерева - Drag and Drop, в Drkb есть примеры реализации
18192123
5.12.2008 17:56
Пока описала свой класс TBPeriod:
unit UnitClasses;
interface type TBPeriod=class private fBTitle:string; function GetBTitle:string; procedure SetBTitle(newBTitle:string);
public property BTitle:string read GetBTitle write SetBTitle; constructor Create(fBTitle:string); end;
implementation Uses UnitMain;
constructor TBPeriod.Create(fBTitle:string); begin inherited Create; BTitle:=fBTitle; end;
function TBPeriod.GetBTitle:string; begin Result:=fBTitle; end;
procedure TBPeriod.SetBTitle(newBTitle:string); begin fBTitle:=newBTitle; end;
end.
На форме имеется кнопка, по которой предполагается создать объект класса TBPeriod (при установке переключателя в положение "Большой"), название его считывается из Edit, и я хочу добавить создаваемый объект в TreeViewNew, с чем и возникла проблема..
procedure TFormMain.BitBtnCreateBPerClick(Sender: TObject); var NewBPeriod:TBPeriod; title:string; begin case RadioGroupPeriod.ItemIndex of 0: begin title:=EditTitlePer.Text; NewBPeriod:=TBPeriod.Create(title); //Вот здесь меня не пропускает с несоответствием типов... Подскажите пожалуйста, как тут быть? FormMain.TreeViewNew.Items.AddObject(title, NewBPeriod as TObject); end; 1: ; else MessageDlg('Выберите пункт создания',mtError,[mbOK],0); end; end;
end.
volvo
5.12.2008 20:02
Цитата
//Вот здесь меня не пропускает с несоответствием типов...
Правильно... AddObject принимает три параметра. Первый - Sibling, куда вставлять новый узел, ты про него забыла... Чтобы добавить еще один корневой узел - сделай:
FormMain.TreeViewNew.Items.AddObject(nil, title, NewBPeriod as TObject);
, ну или передавай вместо nil тот элемент, после которого будет вставлен новый. Проще всего выбрать нужный тебе узел, и сделать:
FormMain.TreeViewNew.Items.AddObject(FormMain.TreeViewNew.Selected, title, NewBPeriod as TObject);
, тогда новый узел добавится как сосед выбранного.
18192123
5.12.2008 23:15
Вопрос насчёт создания класса-потомка для моего класса TBPeriod..
type TRange=class(TBPeriod) // .... end;
Если предполагается, что у этого класса-потомка будет поле, конструктор, так же как и у родителя, то нужно ли эти поле и конструктор писать снова для класса-потомка или можно использовать то, что есть у родителя? Объясните пожалуйста, как это будет выглядеть при описании классов?
volvo
5.12.2008 23:38
Цитата
Если предполагается, что у этого класса-потомка будет поле, конструктор, так же как и у родителя, то нужно ли эти поле и конструктор писать снова для класса-потомка или можно использовать то, что есть у родителя?
Для инициализации тех полей, которые есть у предка, используй конструктор предка (дя этого тот конструктор, собственно, и существует - чтобы правильно выделить и заполнить поля объекта, которые ему известны). Свой конструктор используется для инициализации новых полей:
type TPeriod = class title: string;
constructor create(const s: string); end;
TRange = class(TBase) min, max: integer; // только для иллюстрации, я не знаю, что ты хочешь хранить в этом классе constructor create(const s: string; amin, amax: integer); end;
constructor TPeriod.create(const s: string); begin inherited create; title := s; end;
constructor TRange.create(const s: string; amin, amax: integer); begin inherited create(s); // <--- Поля предка инициализированы ЕГО конструктором min := amin, max := amax; // А теперь инициализируем новые поля end;
18192123
6.12.2008 1:09
Цитата(volvo @ 5.12.2008 16:02)
FormMain.TreeViewNew.Items.AddObject(FormMain.TreeViewNew.Selected, title, NewBPeriod as TObject);
, тогда новый узел добавится как сосед выбранного.
Скажите пожалуйста, а как модифицировать такую запись, если необходимо, чтобы новый узел был не соседним, а дочерним?
volvo
6.12.2008 1:38
Цитата
чтобы новый узел был не соседним, а дочерним
надо вместо AddObject использовать AddChildObject
18192123
6.12.2008 2:12
Цитата(volvo @ 5.12.2008 21:38)
надо вместо AddObject использовать AddChildObject
Аа) спасибо!)
18192123
6.12.2008 21:30
Ещё один вопрос по классам... Есть класс TPeriod и его наследник TRange..
unit UnitClasses;
interface type TPeriod=class Title:string; Feature:string; constructor Create(s:string;aFeature:string); end;
type TRange=class(TPeriod) constructor Create(s:string); end;
Тогда при записи
implementation Uses UnitMain;
constructor TPeriod.Create(s:string;aFeature:string); begin inherited Create; Title:=s; Feature:=aFeature; end;
constructor TRange.Create(s:string); begin inherited Create(s); end;
end.
во 2-м конструкторе компилятор сигнализирует об ошибке..Природа этой ошибки мне ясна (не все параметры указаны)...Но как обойти эту ошибку? Ведь у меня в потомке только поле title без Feature...
volvo
6.12.2008 22:59
Цитата
Но как обойти эту ошибку? Ведь у меня в потомке только поле title без Feature...
Неправда... У тебя в потомке И title, И feature, поскольку оба этих поля описаны в предке... Понимаешь в чем дело? Если тебе хочется сделать так, чтобы потомок содержал меньше полей, чем предок - то налицо ошибка проектирования. У каждого потомка количество полей должно быть как минимум не меньше, чем у предка.
18192123
6.12.2008 23:47
Цитата(volvo @ 6.12.2008 18:59)
Неправда... У тебя в потомке И title, И feature, поскольку оба этих поля описаны в предке... Понимаешь в чем дело? Если тебе хочется сделать так, чтобы потомок содержал меньше полей, чем предок - то налицо ошибка проектирования. У каждого потомка количество полей должно быть как минимум не меньше, чем у предка.
Большое спасибо за разъяснение!
18192123
7.12.2008 1:06
Например, я добавила в TreeView объект с некоторыми характеристиками (в TreeView отображается из них заголовок)..Выделила его..Скажите пожалуйста, что нужно сделать, чтобы теперь просмотреть этот объект?
volvo
7.12.2008 1:42
Совсем забыл уточнить, что для работы с TTreeView твои классы должны быть унаследованы от TObject... То есть, вот так:
type TBPeriod = class(TObject) // внимательно, наследник TObject !!! private fBTitle:string; function GetBTitle:string; procedure SetBTitle(newBTitle:string);
public sData: string; // Просто для иллюстрации - эта строка будет хранимой информацией property BTitle:string read GetBTitle write SetBTitle; constructor Create(fBTitle, data:string); end;
function TBPeriod.GetBTitle:string; begin Result := fBTitle; end;
procedure TBPeriod.SetBTitle(newBTitle:string); begin fBTitle := newBTitle; end;
procedure TForm1.BitBtn1Click(Sender: TObject); var NewBPeriod: TBPeriod; title: string; begin case RadioGroupPeriod.ItemIndex of 0: begin title := EditTitlePer.Text; NewBPeriod := TBPeriod.Create(title, Edit1.Text); TreeView1.Items.AddChildObject( // так заносим данные, это ты уже видела TreeView1.Selected, title, NewBPeriod as TObject ); end;
1: ;
else MessageDlg('Выберите пункт создания',mtError,[mbOK],0); end; end;
procedure TForm1.Button1Click(Sender: TObject); begin // А вот так - получаем доступ к данным ShowMessage(TBPeriod(TreeView1.Selected.Data).sData); end;
Гость
8.12.2008 6:10
У меня возник вопрос по Drag&Drop.. Я хочу реализовать такое действие: при перетаскивании элемента из TreeView на Image соответствующий узел (и связанный с ним объект) удаляется.. Попыталась таким образом:
procedure TFormMain.ImageDelDragDrop(Sender, Source: TObject; X, Y: Integer); begin if Source = TreeViewNew then // Удаляем из источника TTreeView(Source).Items.Delete(TTreeView(Source).Selected); end;
procedure TFormMain.ImageDelDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := (Source = TreeViewNew); end;
Желаемые результаты не достигаются.. Объясните пожалуйста, как нужно сделать?
18192123
8.12.2008 6:12
Цитата(Гость @ 8.12.2008 2:10)
У меня возник вопрос по Drag&Drop.. Я хочу реализовать такое действие: при перетаскивании элемента из TreeView на Image соответствующий узел (и связанный с ним объект) удаляется.. Попыталась таким образом:
procedure TFormMain.ImageDelDragDrop(Sender, Source: TObject; X, Y: Integer); begin if Source = TreeViewNew then // Удаляем из источника TTreeView(Source).Items.Delete(TTreeView(Source).Selected); end;
procedure TFormMain.ImageDelDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := (Source = TreeViewNew); end;
Желаемые результаты не достигаются.. Объясните пожалуйста, как нужно сделать?
Этот пост - мое авторство..Случайно получилось под "Гость"
volvo
8.12.2008 6:30
Цитата
Желаемые результаты не достигаются..
Для того, чтобы это работало, и для TreeView и для Image свойство DragMode должно быть установлено в dmAutomatic
Гость
8.12.2008 22:34
Пусть я определила функцию, процедуру и свойство для класса TBPeriod:
public sData: string; // Просто для иллюстрации - эта строка будет хранимой информацией function GetsData:string; procedure SetsData(newsData:string); property Data:string read GetsData write SetsData; constructor Create(fBTitle, data:string); end;
/////////// function TBPeriod.GetsData:string; begin Result:=sData; end;
procedure TBPeriod.SetsData(newsData:string); begin sData:=newsData; end;
В TreeView соответсвенно находится запись и связанный с ней объект..Выделяя эту запись, можем просмотреть значение поля sData. И предположим, пользователь захочет изменить это значение..А как это осуществить с помощью функции, процедуры и свойства моего класса? Не очень понятен механизм..объясните пожалуйста!
18192123
8.12.2008 22:38
Ой..повторилась история с постом от "Гость"..
volvo
8.12.2008 23:25
Цитата
предположим, пользователь захочет изменить это значение
Кто ж мешает?
TBPeriod(TreeViewNew.Selected.Data).Data := EditNewValue.Text; // изменяешь свойство Data нужного объекта
18192123
9.12.2008 1:39
Снова вопрос по Drag&Drop..теперь в пределах TreeView..т.е. перемещение узлов. Нашла в DRKB пример по этому вопросу...
procedure TFormMain.MoveNode(TargetNode, SourceNode: TTreeNode); var nodeTmp: TTreeNode; i: Integer; begin with TreeViewNew do begin nodeTmp := Items.AddChild(TargetNode, SourceNode.Text); for i := 0 to SourceNode.Count - 1 do begin MoveNode(nodeTmp, SourceNode.Item[i]); end; end; end;
procedure TFormMain.TreeViewNewDragDrop(Sender, Source: TObject; X, Y: Integer); var TargetNode, SourceNode: TTreeNode; begin with TreeViewNew do begin TargetNode := GetNodeAt(X, Y); // Get target node SourceNode := Selected; if (TargetNode = nil) then begin EndDrag(False); Exit; end; MoveNode(TargetNode, SourceNode); SourceNode.Free; end; end;
procedure TFormMain.TreeViewNewDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if (Sender = TreeViewNew) then // If TRUE than accept the draged item begin Accept := True; end; end;
Узлы перемещаются..Но проблема в том, чтобы переместить ещё и связанный с узлом объект... Объясните пожалуйста, как это нужно делать?
Да, получилось!! Спасибо! И теперь момент, который мне не ясен..И это реализация сохранения (того, что получили на TreeViewNew)/считывания (занесение данных в TreeViewNew) в формате XML...Как это реализуется? Какие-нибудь специальные компоненты? Объясните пожалуйста, как это должно выглядеть??
Правда приведенные там процедуры чтения/записи XML потребуют небольшой доработки, поскольку кроме самих названий узлов у тебя должны сохраняться еще и связанные с ними данные (это придется добавить несколько атрибутов в ProcessTreeItem), и потом они должны восстанавливаться из файла (это в ProcessNode, чтение этих атрибутов, создание экземпляра класса TBPeriod и использование AddChildObject вместо AddChild)...
Гость
9.12.2008 7:13
А скажите пожалуйста, где будет лежать создаваемый таким образом файлик *.XML?
18192123
9.12.2008 7:14
Цитата(Гость @ 9.12.2008 3:13)
А скажите пожалуйста, где будет лежать создаваемый таким образом файлик *.XML?
Правда приведенные там процедуры чтения/записи XML потребуют небольшой доработки, поскольку кроме самих названий узлов у тебя должны сохраняться еще и связанные с ними данные (это придется добавить несколько атрибутов в ProcessTreeItem)...
А что это за атрибуты?
volvo
12.12.2008 4:32
Твои атрибуты... Смотри, сохранять дерево (вместе с тем, что хранится в объектах, связанных с узлами), можно так:
procedure ProcessTreeItem(tn: TTreeNode; iNode: IXMLNode); var cNode : IXMLNode; begin if tn = nil then Exit;
cNode := iNode.AddChild('item'); cNode.Attributes['text'] := tn.Text; cNode.Attributes['imageIndex'] := tn.ImageIndex; cNode.Attributes['stateIndex'] := tn.StateIndex; // Вот это и есть твой атрибут ... if tn.Data <> nil then begin cNode.Attributes['sData'] := TBPeriod(tn.Data).sData; end else cNode.Attributes['sData'] := '';
tn := tn.getFirstChild; while tn <> nil do begin ProcessTreeItem(tn, cNode); tn := tn.getNextSibling; end; end; (*ProcessTreeItem*)
tn := tree.TopItem; while tn <> nil do begin ProcessTreeItem (tn, iNode); tn := tn.getNextSibling; end; XMLDoc.SaveToFile(ChangeFileExt(ParamStr(0),'.XML')); XMLDoc := nil; end; (* Tree2XML *)
procedure TForm1.btnSaveXMLClick(Sender: TObject); begin Tree2XML(TreeView1); end;
Чтобы восстановить из XML сохраненное таким образом дерево:
procedure XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument); var iNode : IXMLNode;
procedure ProcessNode(Node : IXMLNode; tn: TTreeNode); var cNode : IXMLNode; newPeriod: TBPeriod; begin if Node = nil then Exit;
with Node do begin // Есть сохраненные атрибуты? Восстанавливаем ... if Attributes['sData'] <> '' then begin newPeriod := TBPeriod.Create( Attributes['text'], Attributes['sData'] ); tn := tree.Items.AddChildObject( tn, Attributes['text'], newPeriod as TObject ); end else // Нету? И не надо ... tn := tree.Items.AddChild(tn, Attributes['text']);
cNode := Node.ChildNodes.First; while cNode <> nil do begin ProcessNode(cNode, tn); cNode := cNode.NextSibling; end; end; (*ProcessNode*) begin tree.Items.Clear; XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML'); XMLDoc.Active := True;
iNode := XMLDoc.DocumentElement.ChildNodes.First;
while iNode <> nil do begin ProcessNode(iNode,nil); iNode := iNode.NextSibling; end;
XMLDoc.Active := False; end;
procedure TForm1.btnLoadTreeClick(Sender: TObject); var ParentObj: TComponent; XMLDoc: TXMLDocument; begin ParentObj := TComponent.Create(nil); XMLDoc := TXMLDocument.Create(ParentObj); XML2Tree(TreeView2, XMLDoc); end;
(я для проверки сохранял из одного дерева, восстанавливал в другое... Из доп. информации сохраняется только строка Data, если у тебя есть еще что-то добавляй и в ProcessTreeItem, и в ProcessNode)...
Гость
12.12.2008 23:29
Мне вот ещё что не понятно... Как быть при записи/чтении в/из *.XML в случае, если TBPeriod имеет наследника TRange, который в свою очередь - TGroup, для TGroup есть наследник TUnderGroup, и для последнего - наследник TElement (причём объекты верхних ступенек иерархии имееют одни и те же поля, а TElement - в дополнии к ним ещё и новые..как учесть это??) Объясните пожалуйста!
18192123
12.12.2008 23:30
Цитата(Гость @ 12.12.2008 19:29)
Мне вот ещё что не понятно... Как быть при записи/чтении в/из *.XML в случае, если TBPeriod имеет наследника TRange, который в свою очередь - TGroup, для TGroup есть наследник TUnderGroup, и для последнего - наследник TElement (причём объекты верхних ступенек иерархии имееют одни и те же поля, а TElement - в дополнии к ним ещё и новые..как учесть это??) Объясните пожалуйста!
volvo
12.12.2008 23:50
Цитата
как учесть это??
Сохранять в XML вместе с данными еще и некоторый идентификатор, определяющий, объект какого именно типа надо будет создавать при восстановлении дерева... Скажем, при id="1", создаем TRange, если id="2", то TElement, и так далее...
Я бы сделал виртуальную функцию GetID: string, которая будет возвращать идентификатор для каждого типа объекта, тогда при записи в этот самый атрибут ID достаточно будет вызвать:
Сохранять в XML вместе с данными еще и некоторый идентификатор...
//сохраняем... if tn.Data <> nil then begin cNode.Attributes['Feature'] := TPeriod(tn.Data).Feature; cNode.Attributes['Count'] := TPeriod(tn.Data).Count; cNode.Attributes['Id']:=1; end else cNode.Attributes['sData'] := '';
Например, так? А для записи в XML наследников должен быть аналогичный код?
volvo
13.12.2008 1:17
Цитата
А для записи в XML наследников должен быть аналогичный код?
Ты ж сказала, что у тебя почти у всех классов одинаковые поля, значит изменения (т.е. добавление еще нескольких строк кода) будет только при сохранении TElement...
18192123
13.12.2008 1:42
Цитата(volvo @ 12.12.2008 21:17)
Ты ж сказала, что у тебя почти у всех классов одинаковые поля, значит изменения (т.е. добавление еще нескольких строк кода) будет только при сохранении TElement...
Да, так и будет.. Но я так и не поняла, где указывать эти несколько строк кода? В фрагменте из предыдущего поста?
volvo
13.12.2008 2:33
Ну, например, так:
if tn.Data <> nil then begin // значит, есть связанный с узлом объект... смотрим, какого он типа: if TBPeriod(tn.Data) is TElement then begin // здесь пишутся данные из класса TElement или его потомков end else begin // здесь - изо всех остальных классов (до TElement в цепочке наследования) end; end else cNode.Attributes['sData'] := '';
18192123
17.12.2008 1:42
Вот такой вопрос возник.. Если я хочу создать очередной узел (по нажатию соответствующей кнопки), то сначала в TreeView мне нужно выделить узел-родитель..Хочу сделать контроль возможности неверного выделения.. Скажите пожалуйста, как в этом случае сообщить о нарушении иерархии, если вместо предполагаемого родительского узла выделен узел того же уровня, что и новый или выделен узел, стоящий выше предполагаемого родительского?
volvo
17.12.2008 1:54
Цитата
как в этом случае сообщить о нарушении иерархии, если вместо предполагаемого родительского узла выделен узел того же уровня, что и новый
Где и как задается уровень НОВОГО узла? В предыдущей версии твоей программы новый узел добавлялся как дочерний к любому выделенному... Что теперь изменилось? Есть какие-то ограничения?
18192123
17.12.2008 2:01
Цитата(volvo @ 16.12.2008 21:54)
Есть какие-то ограничения?
ТОлько по смыслу)
volvo
17.12.2008 2:18
Ну, если дерево будет именно таким, как было сказано в самом первом посте, то с этим проблем нет, можно в конце концов выделять римские числа в заголовках узлов и проверять, подходит ли потомок к выбранному предку... А вот если я в группу "Неметаллы" захочу внести Селен и Теллур - ты сама, не заглядывая в таблицу вряд ли сможешь определить (по смыслу) ошибся ли я, и какой именно элемент не подходит для данной группы. Так что только по смыслу здесь не пойдет. Нужна какая-то доп. информация.
18192123
17.12.2008 2:30
Цитата(volvo @ 16.12.2008 22:18)
Ну, если дерево будет именно таким, как было сказано в самом первом посте, то с этим проблем нет, можно в конце концов выделять римские числа в заголовках узлов и проверять, подходит ли потомок к выбранному предку... А вот если я в группу "Неметаллы" захочу внести Селен и Теллур - ты сама, не заглядывая в таблицу вряд ли сможешь определить (по смыслу) ошибся ли я, и какой именно элемент не подходит для данной группы. Так что только по смыслу здесь не пойдет. Нужна какая-то доп. информация.
Немного другое имела ввиду: есть кнопки добавить период добавить ряд добавить группу добавить подгруппу добавить элемент
и например моё TreeView
Код
I-й период 1-й ряд I-я группа Ia VIII-я группа
И я хочу добавить в I-я группу ещё один узел Iб, т.е для этого я должна выделить этот узел [I-я группа] и нажать кнопку добавить подгруппу. И если выделить узел Ia или 1-й ряд, то при нажатии на кнопку мне приложение должно запретить действия и "сказать", что "подгруппа - это наследник Группа".. Вот чего хочу добиться, только не пойму, как..
volvo
17.12.2008 3:18
А, вот ты о чем... Ну, это просто: у каждого узла дерева есть поле Level (уровень, на котором этот узел находится), тебе надо будет всего навсего проверить его...
Скажем, при нажатии на кнопку в твоем примере проверка должна быть:
if TreeView1.Selected.Level = 2 then begin // Level начинается с 0 // Здесь добавление узла, как обычно end else ShowMessage('Подгруппа - это наследник Группа');
18192123
17.12.2008 4:52
Спасибо!!) Получилось, как и хотела!!) И ещё один вопрос..в таком же духе.. Вот таким образом было сделано перемещение узлов в пределах TreeViewNew:
procedure TFormMain.MoveNode(TargetNode, SourceNode: TTreeNode); var nodeTmp: TTreeNode; i: Integer; begin with TreeViewNew do begin nodeTmp := Items.AddChildObject(TargetNode, SourceNode.Text, SourceNode.Data); for i := 0 to SourceNode.Count - 1 do begin MoveNode(nodeTmp, SourceNode.Item[i]); end; end; end;
procedure TFormMain.TreeViewNewDragDrop(Sender, Source: TObject; X, Y: Integer); var TargetNode, SourceNode: TTreeNode; begin with TreeViewNew do begin TargetNode := GetNodeAt(X, Y); // Get target node SourceNode := Selected; if (TargetNode = nil) then begin EndDrag(False); Exit; end; MoveNode(TargetNode, SourceNode); SourceNode.Free; end; end;
procedure TFormMain.TreeViewNewDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if (Sender = TreeViewNew) then // If TRUE than accept the draged item begin Accept := True; end; end;
Можно ли как-нибудь учесть, чтоб перемещение осуществлялось в таком духе: 1-й ряд переместить только во 2-й период (ну и наоборот), исключая возможность чтоб ряд попал в группу?? ну по такой же схеме с остальным..Объясните пожалуйста!
Код
I период 1 ряд I группа VIII группа II период 2 ряд I группа II группа
volvo
17.12.2008 5:42
procedure TFormMain.TreeViewNewDragDrop(Sender, Source: TObject; X, Y: Integer); var TargetNode, SourceNode: TTreeNode; begin with TreeViewNew do begin TargetNode := GetNodeAt(X, Y); // Get target node SourceNode := Selected; if (TargetNode = nil) or (TargetNode.Level + 1 <> SourceNode.Level) then // <--- begin EndDrag(False); Exit; end; MoveNode(TargetNode, SourceNode); SourceNode.Free; end; end;
Это имела в виду?
18192123
17.12.2008 6:05
Цитата(volvo @ 17.12.2008 1:42)
Это имела в виду?
Да, большое спасибо!! Теперь понятно!!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.