Sign in Join
Wiki copytemporary

VirtualTreeview Example for Lazarus/ru: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: VirtualTreeview Example for Lazarus/ru

OldNewLine
1+Вот несколько примеров того, как использовать [[VirtualTreeview]] для Lazarus (проверено на win32). Они в основном собираются из Интернета, написанного для Delphi, и из учебника/документов Philipp Frenzel и Mike Lischke.
2+
3+Учебник / документы можно загрузить с <http://www.soft-gems.net>. Ниже кто-либо найдет только быстрый способ использовать VirtualTreeview на Lazarus, а не объяснения. Для пояснения и множества других функций/методов, получите официальные документы и учебник.
4+
5+# Основной список дерева с тремя столбцами
6+
7+1\. Установите компонент. Запустите lazarus.
8+
9+2\. Бросьте \[на форму\] компонент TVirtualStringTree (вкладка Virtual Controls).
10+
11+3\. Перейдите в редактор исходного кода (нажмите F12). В разделе Uses добавьте модуль - VirtualTrees (если она еще не существует, и это не VirtualStringTree). Это может выглядеть так:
12+
13+``` pascal
14+uses
15+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
16+ VirtualStringTree, VirtualTrees;
17+```
18+
19+4\. Войдите в конструктор форм (нажмите F12). Выберите компонент Virtual Tree. В Инспекторе объектов нажмите Name, введите VST и нажмите enter. Кликните на заголовок (разверните его) -\> Columns, нажмите маленькую кнопку рядом с "0 items". Нажмите 3 раза кнопку Add, чтобы добавить 3 столбца. Не закрывайте это окно.
20+
21+5\. В окне редактирования столбца теперь выбирается третий столбец. Войдите в Инспектор объектов. Кликните Options (разверните его) -\> установите для параметра `coAllowClick` значение `False`.
22+
23+6\. Нажмите на Text. Введите Column2.
24+
25+7\. Нажмите `Width`, введите 100 и нажмите enter.
26+
27+8\. Перейдите в окно редактирования столбцов, выберите 1-й и 2-й столбцы и установите их свойство, как указано выше (для текстового поля используйте разные имена, то есть Column0, Column1).
28+
29+9\. Закройте окно редактирования столбцов. Выберите компонент Virtual Tree в форме. В Object Inspector перейдите к Header -\> Options (\[раскройте спиcок\]). Установите значение `hoVisible` в значение True.
30+
31+10\. Прокрутите вниз до Style, чтобы установить его в hsFlatButtons.
32+
33+![](/wiki-images/7/70/ExempleVirtualtreeView1.jpg)
34+
35+11\. Прокрутите вниз до TreeOptions (раскройте) -\> MiscOption (раскройте), установите `toEditable` в значение `True`. Установите `toGridExtensions` в значение `True`.
36+
37+12\. Прокрутите вниз до пункта SelectionOptions(раскройте) -\> установите toExtendedFocus в значение True. Установите toMultiSelect в значение True. В конструкторе форм измените размер VST (Virtual Tree Component) так, чтобы получить представление обо всех столбцах, если необходимо.
38+
39+13\. Теперь добавьте 3 кнопки на форму. Получите их из палитры компонентов - вкладка Standard (ярлык "OK").
40+
41+14\. Нажмите кнопку Button1, изменив в Object Inspector \[ее свойство\] `Caption` на AddRoot. Нажмите кнопку Button2, измените заголовок на AddChild. Измените заголовок Button3 на Delete.
42+
43+![](/wiki-images/7/76/ExempleVirtualtreeView2.jpg)
44+
45+15\. Сохраните это и перейдите в редактор исходного кода (нажмите F12). В редакторе исходного кода замените строку:
46+
47+``` pascal
48+{$mode objfpc}{$H+}
49+```
50+
51+на
52+
53+``` pascal
54+{$MODE DELPHI}
55+```
56+
57+16\. В разделе "implementation" вставьте следующие строки:
58+
59+``` pascal
60+type
61+ PTreeData = ^TTreeData;
62+ TTreeData = record
63+ Column0: String;
64+ Column1: String;
65+ Column2: String;
66+ end;
67+```
68+
69+17\. Войдите в конструктор форм (нажмите F12). Выберите VST. Перейдите к Object Inspector, выберите вкладку `Events`, прокрутите вниз до `onChange`. Дважды щелкните значок со списком. Вставьте следующие данные:
70+
71+``` pascal
72+procedure TForm1.VSTChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
73+begin
74+ VST.Refresh;
75+end;
76+```
77+
78+18\. Прокрутите до `onFocusChanged`. Дважды щелкните и вставьте следующее:
79+
80+``` pascal
81+procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
82+ Column: TColumnIndex);
83+begin
84+ VST.Refresh;
85+end;
86+```
87+
88+19\. Прокрутите до `onFreeNode`. Дважды щелкните и вставьте следующее:
89+
90+``` pascal
91+procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
92+var
93+ Data: PTreeData;
94+begin
95+ Data := VST.GetNodeData(Node);
96+ if Assigned(Data) then begin
97+ Data^.Column0 := '';
98+ Data^.Column1 := '';
99+ Data^.Column2 := '';
100+ end;
101+end;
102+```
103+
104+20\. Прокрутите вниз до `onGetNodeDataSize`. Дважды кликните и вставьте следующее:
105+
106+``` pascal
107+procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
108+begin
109+ NodeDataSize := SizeOf(TTreeData);
110+end;
111+```
112+
113+21\. Прокрутите вниз до `onGetText`. Дважды кликните и вставьте следующее:
114+
115+``` pascal
116+procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
117+ Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
118+var
119+ Data: PTreeData;
120+begin
121+ Data := VST.GetNodeData(Node);
122+ case Column of
123+ 0: CellText := Data^.Column0;
124+ 1: CellText := Data^.Column1;
125+ 2: CellText := Data^.Column2;
126+ end;
127+end;
128+```
129+
130+22\. Нажмите F12 для перехода дизайнер форм. Дважды кликните кнопку AddRoot. Вставьте следующее:
131+
132+``` pascal
133+procedure TForm1.Button1Click(Sender: TObject);
134+var
135+ Data: PTreeData;
136+ XNode: PVirtualNode;
137+ Rand: Integer;
138+begin
139+ Randomize;
140+ Rand := Random(99);
141+ XNode := VST.AddChild(nil);
142+
143+ if VST.AbsoluteIndex(XNode) > -1 then
144+ begin
145+ Data := VST.GetNodeData(Xnode);
146+ Data^.Column0 := 'One ' + IntToStr(Rand);
147+ Data^.Column1 := 'Two ' + IntToStr(Rand + 10);
148+ Data^.Column2 := 'Three ' + IntToStr(Rand - 10);
149+ end;
150+end;
151+```
152+
153+23\. Нажмите F9 для запуска проекта с целью проверки. Нажмите AddRoot, чтобы добавить узел. Если все нормально, узел будет добавлен в VST.
154+
155+![](/wiki-images/8/86/ExempleVirtualtreeView3.jpg)
156+
157+24\. Прервите выполнение. В конструкторе форм кликните дважды кнопку с надписью AddChild. Вставьте следующее:
158+
159+``` pascal
160+procedure TForm1.Button2Click(Sender: TObject);
161+var
162+ XNode: PVirtualNode;
163+ Data: PTreeData;
164+begin
165+ if not Assigned(VST.FocusedNode) then
166+ Exit;
167+
168+ XNode := VST.AddChild(VST.FocusedNode);
169+ Data := VST.GetNodeData(Xnode);
170+
171+ Data^.Column0 := 'Ch 1';
172+ Data^.Column1 := 'Ch 2';
173+ Data^.Column2 := 'Ch 3';
174+
175+ VST.Expanded[VST.FocusedNode] := True;
176+end;
177+```
178+
179+25\. В конструкторе форм дважды нажмите кнопку Delete. Вставьте следующее:
180+
181+``` pascal
182+procedure TForm1.Button3Click(Sender: TObject);
183+begin
184+ VST.DeleteSelectedNodes;
185+end;
186+```
187+
188+26\. Запустите проект, нажав F9 для проверки. Добавьте узел, дочерний элемент и удалите их.
189+
190+![](/wiki-images/3/3d/ExempleVirtualtreeView4.jpg)
191+
192+27\. Попробуйте отредактировать узел. Выберите узел и нажмите F2, напишите новое значение. Если вы видите, что напечатали, тогда все в порядке. Иначе, читайте ниже: [[VirtualTreeview Example for Lazarus/ru|Если правки ячейки не отображаются]].
193+
194+28\. Чтобы отображалось полученное VST новое значение, введенное после редактирования, перейдите в конструктор форм, выберите VST. В инспекторе объектов \[дважды кликаем\] по комбобоксу `OnNewText` на вкладке Events. Вставляем следующее:
195+
196+``` pascal
197+procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
198+ Column: TColumnIndex; NewText: WideString);
199+var
200+ Data: PTreeData;
201+begin
202+ Data := VST.GetNodeData(Node);
203+ case Column of
204+ 0: Data^.Column0 := NewText;
205+ 1: Data^.Column1 := NewText;
206+ 2: Data^.Column2 := NewText;
207+ end;
208+end;
209+```
210+
211+Пока что пример базового использования заканчивается здесь. Вы можете бросить \[еще\] несколько кнопок на форму, чтобы проверить несколько команд, приведенных ниже. Далее будут показаны \[примеры работы с\] checkbox'ом, изображением, цветом шрифта и добавлением combobox'а на узле.
212+
213+- Другой способ добавления корневого узла
214+
215+``` pascal
216+procedure TForm1.Button8Click(Sender: TObject);
217+begin
218+ with VST do
219+ RootNodeCount := RootNodeCount + 1;
220+end;
221+```
222+
223+- Другой способ добавления дочернего узла
224+
225+``` pascal
226+procedure TForm1.Button9Click(Sender: TObject);
227+begin
228+ if Assigned(VST.FocusedNode) then
229+ VST.ChildCount[VST.FocusedNode] := VST.ChildCount[VST.FocusedNode] + 1;
230+end;
231+```
232+
233+- Определение и удаление потомков узла
234+
235+``` pascal
236+procedure TForm1.Button4Click(Sender: TObject);
237+var
238+ c: Integer;
239+begin
240+ if not Assigned(VST.FocusedNode) then
241+ Exit;
242+ if VST.HasChildren[VST.FocusedNode] then
243+ begin
244+ c := VST.ChildCount[VST.FocusedNode];
245+ VST.DeleteChildren(VST.FocusedNode);
246+ ShowMessage('Number of deleted child:' + #13#10 + IntToStr(c));
247+ end;
248+end;
249+```
250+
251+- Удаление узла
252+
253+``` pascal
254+procedure TForm1.Button5Click(Sender: TObject);
255+begin
256+{VST.Clear; //Удаляет все узлы}
257+ if not Assigned(VST.FocusedNode) then
258+ Exit;
259+ VST.DeleteNode(VST.FocusedNode);
260+end;
261+```
262+
263+- Поиск и выделение узла
264+
265+``` pascal
266+procedure TForm1.Button6Click(Sender: TObject);
267+bar
268+ XNode: PVirtualNode;
269+ Data: PTreeData;
270+begin
271+ XNode := VST.GetFirst;
272+
273+ while XNode <> nil do
274+ begin
275+ Data := VST.GetNodeData(XNode);
276+ if Data^.Column0 = '1' then
277+ begin
278+ VST.ClearSelection;
279+ VST.Selected[XNode] := True;
280+ VST.SetFocus;
281+ break;
282+ end else
283+ XNode := VST.GetNextSibling(XNode);
284+ end;
285+end;
286+```
287+
288+- Определение родителя
289+
290+``` pascal
291+procedure TForm1.Button13Click(Sender: TObject);
292+var
293+ XNode: PVirtualNode;
294+begin
295+ if not Assigned(VST.FocusedNode) then
296+ Exit;
297+ XNode := VST.FocusedNode;
298+ while VST.GetNodeLevel(XNode) > 0 do
299+ begin
300+ XNode := XNode.Parent;
301+ VST.Selected[XNode] := True;
302+ end;
303+ VST.Refresh;
304+ VST.SetFocus;
305+end;
306+```
307+
308+- Поиск всего
309+
310+``` pascal
311+procedure TForm1.Button7Click(Sender: TObject);
312+var
313+ XNode: PVirtualNode;
314+ Data: PTreeData;
315+begin
316+ if VST.GetFirst = nil then Exit;
317+ XNode := nil;
318+ repeat
319+ if XNode = nil then
320+ XNode := VST.GetFirst
321+ else
322+ XNode := VST.GetNext(XNode);
323+ Data := VST.GetNodeData(XNode);
324+ if (Data^.Column0 = '1') or (Data^.Column1 = '1') or (Data^.Column2 = '1') then
325+ begin
326+ ShowMessage('Found at Node Level : ' + IntToStr(VST.GetNodeLevel(XNode)));
327+ break;
328+ end;
329+ until XNode = VST.GetLast();
330+end;
331+```
332+
333+- Поиск следующего
334+
335+``` pascal
336+procedure TForm1.Button8Click(Sender: TObject);
337+var
338+ XNode: PVirtualNode;
339+ Data: PTreeData;
340+begin
341+ if not Assigned(VST.GetFirst) then
342+ Exit
343+ else
344+ XNode := VST.GetFirst;
345+ repeat
346+ XNode := VST.GetNext(XNode);
347+ Data := VST.GetNodeData(XNode);
348+ if Pos(LowerCase(SearchEdit.Text), LowerCase(Data^.Column0)) > 0 then
349+ begin
350+ VST.FocusedNode := XNode;
351+ VST.Selected[XNode] := True;
352+ if MessageDlg('Item found?', mtConfirmation, mbYesNo, 0) = mrYes then
353+ begin
354+ VST.Expanded[XNode] := True;
355+ VST.Refresh;
356+ VST.SetFocus;
357+ Break;
358+ end;
359+ end;
360+ until XNode = VST.GetLast;
361+end;
362+```
363+
364+- Вставка узла
365+
366+``` pascal
367+procedure TForm1.Button12Click(Sender: TObject);
368+var
369+ XNode: PVirtualNode;
370+begin
371+ if Assigned(VST.FocusedNode) then
372+ begin
373+ XNode := VST.InsertNode(VST.FocusedNode,amInsertBefore);
374+ // Вставка после выделенного узла
375+ {XNode := VST.InsertNode(VST.FocusedNode,amInsertAfter);}
376+ VST.Refresh;
377+ end;
378+end;
379+```
380+
381+- Установка высоты узла
382+
383+``` pascal
384+procedure TForm1.Button14Click(Sender: TObject);
385+begin
386+ if Assigned(VST.FocusedNode) then
387+ VST.NodeHeight[VST.FocusedNode] := 32;
388+end;
389+```
390+
391+- Сохранение и загрузка
392+
393+Простое дерево (без столбцов) можно сохранить и загрузить как:
394+
395+``` pascal
396+VST.SaveToFile('filename.dat');
397+VST.LoadFromFile('filename.dat');
398+```
399+
400+Чтобы сохранить и загрузить вышеупомянутый пример, поместите 2 кнопки на форму, переименуйте заголовок в "Save" и "Load". Выберите VST, в Object Inspector -\> TreeOptions -\> StringOptions убедитесь, что \[значение\] toSaveCaptions установлено в True. Перейдите на вкладку Events инспектора объектов. Прокрутите вниз до OnLoadNode, дважды щелкните \[его\] и вставьте:
401+
402+``` pascal
403+procedure TForm1.VSTLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
404+ Stream: TStream);
405+var
406+ Data: PTreeData;
407+ Len: Integer;
408+begin
409+ Data := VST.GetNodeData(Node);
410+ Stream.read(Len, SizeOf(Len));
411+ SetLength(Data^.Column0, Len);
412+ Stream.read(PChar(Data^.Column0)^, Len);
413+
414+ Stream.read(Len, SizeOf(Len));
415+ SetLength(Data^.Column1, Len);
416+ Stream.read(PChar(Data^.Column1)^, Len);
417+
418+ Stream.read(Len, SizeOf(Len));
419+ SetLength(Data^.Column2, Len);
420+ Stream.read(PChar(Data^.Column2)^, Len);
421+end;
422+```
423+
424+Снова перейдите на вкладку Events инспектора объектов - прокрутите до OnSaveNode, дважды щелкните и вставьте:
425+
426+``` pascal
427+procedure TForm1.VSTSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
428+ Stream: TStream);
429+var
430+ Data: PTreeData;
431+ Len: Integer;
432+begin
433+ Data := VST.GetNodeData(Node);
434+ Len := Length(Data^.Column0);
435+ Stream.write(Len, SizeOf(Len));
436+ Stream.write(PChar(Data^.Column0)^, Len);
437+
438+ Len := Length(Data^.Column1);
439+ Stream.write(Len, SizeOf(Len));
440+ Stream.write(PChar(Data^.Column1)^, Len);
441+
442+ Len := Length(Data^.Column2);
443+ Stream.write(Len, SizeOf(Len));
444+ Stream.write(PChar(Data^.Column2)^, Len);
445+end;
446+```
447+
448+В редакторе форм дважды щелкните по кнопке с заголовком Save, вставьте:
449+
450+``` pascal
451+procedure TForm1.Button10Click(Sender: TObject);
452+begin
453+ VST.SaveToFile('C:\vst.dat');
454+end;
455+```
456+
457+В редакторе форм дважды щелкните по кнопке с заголовком Load, вставьте:
458+
459+``` pascal
460+procedure TForm1.Button11Click(Sender: TObject);
461+begin
462+ VST.LoadFromFile('C:\vst.dat');
463+end;
464+```
465+
466+Теперь тест сохраняет и загружает дерево.
467+
468+- Проблемы с прокруткой
469+
470+Заголовок дерева полностью или частично исчезает при прокрутке. Я не смог найти для этого хорошего решения. Один из способов преодолеть это - установить высоту заголовка в 0, а затем использовать общую надпись для столбцов. Это хорошо, когда имеется несколько столбцов, и все они видны без горизонтальной прокрутки. Или высота заголовка может быть установлена на большее значение, например 25 или 30. VST.Refresh можно добавить в событие OnScroll.
471+
472+- Изменение размера столбцов
473+
474+Невозможно изменить размер столбца перетаскиванием мышью заголовка VST. Может быть, это ошибка заголовка, или я что-то пропустил. Если это для заголовка, вероятно, будет исправлено в следующей версии Lazarus. См. Эту ссылку: <http://bugs.freepascal.org/view.php?id=11209>\
475+Во всяком случае, можно изменить размер столбца из кода. \[Сделав так:\] когда вы зажимаете правую кнопку мыши и крутите колесико мыши вверх, ширина выбранного столбца \[будет\] увеличиваться; а \[когда\] зажимаете правую кнопку мыши и крутите колесико мыши вниз, ширина выбранного столбца будет уменьшаться. Для этого:\
476+1\. Добавьте переменную в исходный код под именем `CurCol: Integer;`, чтобы это выглядело так:
477+
478+``` pascal
479+var
480+ Form1: TForm1;
481+ CurCol: Integer; // <- Добавьте только эту строчку.
482+
483+implementation
484+
485+{ TForm1 }
486+```
487+
488+2\. В конструкторе форм дважды щелкните по форме, чтобы создать событие OnCreate. Внутри процедуры OnCreate напишите `Form1.OnMouseWheelUp:=` и нажмите `Ctrl` + `Shift` + `C`, это завершит код и сделает скелет события MouseWheelUp. Теперь вернемся к процедуре `TForm1.FormCreate(Sender: TObject);`. Добавьте еще одно событие для MouseWheelDown. Введите `Form1.OnMouseWheelDown:=` и нажмите `Ctrl` + `Shift` + `C`, чтобы сгенерировать событие MouseWheelDown. Процедура FormCreate теперь выглядит так:
489+
490+``` pascal
491+procedure TForm1.FormCreate(Sender: TObject);
492+begin
493+ Form1.OnMouseWheelUp := @Form1MouseWheelUp;
494+ Form1.OnMouseWheelDown := @Form1MouseWheelDown;
495+end;
496+```
497+
498+3\. Заполните процедуру TForm1.Form1MouseWheelUp как:
499+
500+``` pascal
501+procedure TForm1.Form1MouseWheelUp(Sender: TObject; Shift: TShiftState;
502+ MousePos: TPoint; var Handled: Boolean);
503+begin
504+ if VST.Focused and (ssRight in Shift) then
505+ VST.Header.Columns[CurCol].Width := VST.Header.Columns[CurCol].Width + 10;
506+end;
507+```
508+
509+4\. Заполните процедуру TForm1.Form1MouseWheelDown как:
510+
511+``` pascal
512+procedure TForm1.Form1MouseWheelDown(Sender: TObject; Shift: TShiftState;
513+ MousePos: TPoint; var Handled: Boolean);
514+begin
515+ if VST.Focused and (ssRight in Shift) then
516+ VST.Header.Columns[CurCol].Width := VST.Header.Columns[CurCol].Width - 10;
517+end;
518+```
519+
520+5\. Перейдите в конструктор форм (нажмите F12), выберите VST, на вкладке Events инспектора объектов прокрутите список до OnFocusChanged, дважды кликните \[по нему\] и вставьте:
521+
522+``` pascal
523+procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree;
524+ Node: PVirtualNode; Column: TColumnIndex);
525+begin
526+ CurCol := Column;
527+end;
528+```
529+
530+Когда вы запустите \[программу\], щелкните по столбцу, затем удерживайте зажатой правую кнопку мыши и перемещайте колесико \[прокрутки мыши\] вверх, чтобы увеличить ширину, и вниз\[, чтобы ее\] уменьшить. При необходимости вы можете настроить вышеуказанные процедуры. Или добавить событие клавиатуры, что-то вроде *"if (key = 187) and (ssShift в Shift) then"* для просмотра по `Shift` + `+`.
531+
532+# Checkbox
533+
534+В дизайнере форм выберите VST. Перейдите к:\
535+\#Object Inspector -\> Properties -\> CheckImageKind и выберите ckDarkCheck.
536+
537+1. Object Inspector -\> Properties -\> TreeOptions -\> MiscOptions -\> toCheckSupport и установите его значение в True.\
538+
539+Теперь переключитесь на вкладку Events.\
540+*Прокрутите до OnInitNode. Дважды кликните \[на нем\] и вставьте следующее:
541+
542+``` pascal
543+procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
544+ Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
545+var
546+ Level: Integer;
547+begin
548+ Level := VST.GetNodeLevel(Node);//уровень вложенности
549+
550+ case Level of
551+ 0: Node^.CheckType:= ctCheckBox;//Root (пустой checkbox)
552+ 1:
553+ begin
554+ Node^.CheckType := ctTriStateCheckBox;//checkbox c 3-мя состояниями
555+ Node^.CheckState := csUncheckedNormal;//пустой checkbox
556+ end;
557+ 2: Node^.CheckType := ctRadioButton;//RadioButton
558+ 3: Node^.CheckType := ctButton;//кнопка выпадающего списка
559+ 4:
560+ begin
561+ Node^.CheckType := ctTriStateCheckBox;//checkbox c 3-мя состояниями
562+ Node^.CheckState := cscheckedNormal;//отмеченный checkbox
563+ end;
564+ end;
565+end;
566+```
567+
568+![](/wiki-images/d/de/Vst_checkbox.png)
569+
570+Запустите программу, добавьте родительский узел и дочерний, затем дочерний элемент дочернего узла, и проверьте, можете ли вы изменять состояние \[checkbox'а\]. Если нет, закройте программу. Перейдите на вкладку Events инспектора объектов.
571+
572+- Прокрутите до OnChecked, дважды кликните \[на нем\] и вставьте:
573+
574+``` pascal
575+procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
576+begin
577+ VST.Refresh;
578+end;
579+```
580+
581+- Прокрутите до OnChecking, дважды кликните \[на нем\] и вставьте:
582+
583+``` pascal
584+procedure TForm1.VSTChecking(Sender: TBaseVirtualTree; Node: PVirtualNode;
585+ var NewState: TCheckState; var Allowed: Boolean);
586+begin
587+ VST.Refresh;
588+end;
589+```
590+
591+Надеюсь, теперь все в порядке. Определить состояние checkbox'а можно так:\
592+
593+``` pascal
594+if XNode.CheckState = csCheckedNormal then
595+ShowMessage('Checked');
596+```
597+
598+Другие значения флажов состояний:\
599+
600+``` pascal
601+csUncheckedNormal = не отмечен и не нажат
602+csUncheckedPressed = не отмечен и нажат
603+csCheckedNormal = отмечен и не нажат
604+csCheckedPressed = отмечен и нажат
605+csMixedNormal = checkbox имеет 3 состояния и не нажат
606+csMixedPressed = checkbox имеет 3 состояния и нажат
607+```
608+
609+------------------------------------------------------------------------
610+
611+Прим.перев: визуально свойство `CheckState` выглядит примерно так:\
612+![](/wiki-images/1/11/Checkstate_enum.png)\
613+----
614+
615+Другие типы:\
616+
617+``` pascal
618+ctNone
619+ctTriStateCheckBox
620+ctCheckBox
621+ctRadioButton
622+ctButton
623+```
624+
625+------------------------------------------------------------------------
626+
627+Прим.перев: визуально свойство `CheckType` выглядит примерно так:\
628+![](/wiki-images/a/ab/Checktype_enum.png)\
629+----
630+
631+- Отлов нажатия кнопки Checkbox'а (ctButton)
632+
633+Перейдите на вкладку Events объекта инспектора. Прокрутите до OnChecked, дважды кликните \[на нем\] и вставьте:
634+
635+``` pascal
636+procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
637+begin
638+ if Node.CheckType = ctButton then
639+ ShowMessage('Ok.');
640+ VST.Refresh;
641+end;
642+```
643+
644+# Картинки
645+
646+Чтобы показать изображение в узлах VST, необходимо создать список изображений.
647+
648+- Перейдите в палитру компонентов -\> вкладка Common Controls. Выберите и бросьте на форму компонент TImageList. Щелкните правой кнопкой мыши значок компонента и выберите редактор ImageList. Нажмите кнопку "Add" и выберите какие-нибудь изображения (по крайней мере 3 на данный момент), затем нажмите кнопку "OK", чтобы принять и закрыть редактор ImageList. Кстати, есть несколько хороших изображений, которые вы можете скачать с <http://www.famfamfam.com/lab/icons/silk/>
649+- Теперь в дизайнере форм выберите VST и на вкладке Properties инспектора объектов прокрутите до \[свойства\] Images и выберите ImageList1
650+- На вкладке Events инспектора объектов прокрутите до OnGetImageIndex, дважды кликните \[на нем\] и вставьте:
651+
652+``` pascal
653+procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
654+ Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean;
655+ var ImageIndex: Integer);
656+begin
657+ if Kind in [ikNormal , ikSelected] then // либо выбран, либо нет
658+ begin
659+ if Column = 0 then // если 1-й столбец
660+ ImageIndex := 0; // 1-е изображение ImageList1'а
661+
662+ if Column = 1 then // если 2-й столбец
663+ ImageIndex := 1; // 2-е изображение ImageList1'а
664+
665+ if Sender.FocusedNode = Node then // Показывать, только если в фокусе
666+ if Column = 2 then // если 3-й столбец
667+ ImageIndex := 2; // 3-е изображение ImageList1'а
668+ end;
669+ {Sender.NodeHeight[node] := 40; //Если изображение большое}
670+end;
671+```
672+
673+# Цвет шрифта
674+
675+В дизайнере форм выберите VST и на вкладке Events инспектора объектов прокрутите до OnPaintText, дважды кликните \[на нем\] и вставьте:
676+
677+``` pascal
678+procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
679+ const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
680+ TextType: TVSTTextType);
681+var
682+ Data: PTreeData;
683+begin
684+ Data := VST.GetNodeData(Node);
685+
686+ if Data^.Column0 = 'sky' then
687+ TargetCanvas.Font.Color := clBlue;
688+
689+ if Column = 1 then
690+ begin
691+ TargetCanvas.Font.Color := clRed;
692+ TargetCanvas.Font.Style := Font.Style + [fsItalic];
693+ end;
694+
695+ if Column = 2 then
696+ begin
697+// ImageList1.Draw(Form1.Canvas, -1, -1, 2); {рисует верхнюю левую часть формы, третье изображение ImageList1 ??}
698+ TargetCanvas.Font.Size := 9;
699+ TargetCanvas.Font.Color := clHighlightText;
700+ end;
701+end;
702+```
703+
704+# Добавление Combobox'а
705+
706+- Я предполагаю, что у вас есть открытый проект на Lazarus IDE с VST на нем и возможность редактировать узлы. Если нет, см. выше [[VirtualTreeview Example for Lazarus/ru|Основной список дерева с тремя столбцами]] и, по крайней мере, выполните шаги с 1 по 21.
707+
708+- Ниже приведен файл модуля с именем combo. Скопируйте этот модуль и сохраните его как combo.pas внутри каталога проекта. Добавьте \[модуль\] комбо в раздел uses вашей программы. Это может выглядеть так:
709+
710+``` pascal
711+uses
712+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
713+ VirtualStringTree, VirtualTrees, combo;
714+```
715+
716+- Модуль combo.pas
717+
718+``` pascal
719+unit combo;
720+
721+{$mode delphi}
722+
723+interface
724+
725+uses
726+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
727+ VirtualStringTree, VirtualTrees, messages, windows, StdCtrls;
728+
729+type
730+ TStringEditLink = class(TInterfacedObject, IVTEditLink)
731+ private
732+ FEdit: TWinControl;
733+ FTree: TVirtualStringTree;
734+ FNode: PVirtualNode;
735+ FColumn: Integer;
736+ protected
737+ procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
738+ public
739+ destructor Destroy; override;
740+ function BeginEdit: Boolean; stdcall;
741+ function CancelEdit: Boolean; stdcall;
742+ function EndEdit: Boolean; stdcall;
743+ function GetBounds: TRect; stdcall;
744+ function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
745+ procedure ProcessMessage(var Message: TMessage); stdcall;
746+ procedure SetBounds(R: TRect); stdcall;
747+ end;
748+
749+implementation
750+
751+destructor TStringEditLink.Destroy;
752+begin
753+ FEdit.Free;
754+ inherited;
755+end;
756+
757+procedure TStringEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
758+begin
759+ case Key of
760+ VK_ESCAPE:
761+ begin
762+ FTree.CancelEditNode;
763+ Key := 0;
764+ FTree.setfocus;
765+ end;
766+ VK_RETURN:
767+ begin
768+ PostMessage(FTree.Handle, WM_KEYDOWN, VK_DOWN, 0);
769+ Key := 0;
770+ FTree.EndEditNode;
771+ FTree.setfocus;
772+ end;
773+ end; //case
774+end;
775+
776+function TStringEditLink.BeginEdit: Boolean;
777+begin
778+ Result := True;
779+ //FEdit.Height := (FTree.DefaultNodeHeight - 1); //Нужен для editbox. Не для combo
780+ FEdit.Show;
781+ TComboBox(FEdit).DroppedDown := True;
782+ FEdit.SetFocus;
783+end;
784+
785+function TStringEditLink.CancelEdit: Boolean;
786+begin
787+ Result := True;
788+ FEdit.Hide;
789+end;
790+
791+function TStringEditLink.EndEdit: Boolean;
792+var
793+ s: String;
794+begin
795+ Result := True;
796+ s := TComboBox(FEdit).Text;
797+ FTree.Text[FNode, FColumn] := s;
798+
799+ FTree.InvalidateNode(FNode);
800+ FEdit.Hide;
801+ FTree.SetFocus;
802+end;
803+
804+function TStringEditLink.GetBounds: TRect;
805+begin
806+ Result := FEdit.BoundsRect;
807+end;
808+
809+function TStringEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
810+begin
811+ Result := True;
812+ FTree := Tree as TVirtualStringTree;
813+ FNode := Node;
814+ FColumn := Column;
815+
816+ FEdit.Free;
817+ FEdit := nil;
818+
819+ FEdit := TComboBox.Create(nil);
820+ with FEdit as TComboBox do
821+ begin
822+ Visible := False;
823+ Parent := Tree;
824+ Items.Add('Google');
825+ Items.Add('Yahoo');
826+ Items.Add('Altavista');
827+ OnKeyDown := EditKeyDown;
828+ end;
829+end;
830+
831+procedure TStringEditLink.ProcessMessage(var Message: TMessage);
832+begin
833+ FEdit.WindowProc(Message);
834+end;
835+
836+procedure TStringEditLink.SetBounds(R: TRect);
837+var
838+ Dummy: Integer;
839+begin
840+ FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
841+ FEdit.BoundsRect := R;
842+end;
843+
844+end.
845+```
846+
847+- После сохранения файла в дизайнере форм выберите VST и \[на вкладке\] Properties инспектора объектов прокрутите до \[свойства\] TreeOptions -\> MiscOptions, установите \[параметр\] toEdeitable в значение True. Затем перейдите в TreeOptions -\> SelectionOptions, установите \[параметр\] toExtendedFocus в значение True.
848+
849+- Переключитесь на вкладку Events инспектора объектов. Прокрутите до OnCreateEditor, дважды кликните \[на нем\] и вставьте:
850+
851+``` pascal
852+procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree;
853+ Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
854+begin
855+ EditLink := TStringEditLink.Create;
856+end;
857+```
858+
859+- На вкладке Events инспектора объектов. Прокрутите до OnNewText, дважды кликните \[на нем\] и вставьте:
860+
861+``` pascal
862+procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
863+ Column: TColumnIndex; NewText: WideString);
864+var
865+ Data: PTreeData;
866+begin
867+ Data := VST.GetNodeData(Node);
868+ case Column of
869+ 0: Data^.Column0 := NewText;
870+ 1: Data^.Column1 := NewText;
871+ 2: Data^.Column2 := NewText;
872+ end;
873+end;
874+```
875+
876+Запустите программу, выберите узел и нажмите F2, чтобы получить combobox. При нажатии Enter на узле должно появиться новое значение.\
877+
878+# Если правки ячейки не отображаются
879+
880+Откройте файл модуль VirtualStringTree.pas (если вы все еще находитесь в приведенном выше примере проекта, щелкните правой кнопкой мыши на VirtualStringTree в разделе Uses и выберите "Найти объявление". Это откроет файл на следующей вкладке. Перейдите на вкладку этого файла.). Войдите в "function TStringEditLink.BeginEdit: Boolean; stdcall;". Это выглядит как:
881+
882+``` pascal
883+function TStringEditLink.BeginEdit: Boolean; stdcall;
884+
885+// Сообщает ссылку на редактирование, которая может начать редактирование. Потомки могут отменить редактирование узла,
886+// вернув False.
887+
888+begin
889+ Result := not FStopping;
890+ if Result then
891+ begin
892+ FEdit.Show;
893+ FEdit.SelectAll;
894+ FEdit.SetFocus;
895+ end;
896+end;
897+```
898+
899+Теперь добавьте "FEdit.Height:=18;". Это должен выглядеть так:
900+
901+``` pascal
902+function TStringEditLink.BeginEdit: Boolean; stdcall;
903+
904+// Сообщает ссылку на редактирование, которая может начать редактирование. Потомки могут отменить редактирование узла,
905+// вернув False.
906+
907+begin
908+ Result := not FStopping;
909+ if Result then
910+ begin
911+ FEdit.Show;
912+ FEdit.SelectAll;
913+ FEdit.SetFocus;
914+ FEdit.Height := 18; // <--- Добавлена эта строчка.
915+ end;
916+end;
917+```
918+
919+Сохраните файл (нажмите `Ctrl` + `S`). Если вы находитесь в примере проекта, закройте его (Project -\> Close Project). Нажмите Tools -\> Configure "Build Lazarus" ... Выберите Clean Up + Build All, а затем нажмите кнопку Build. После компиляции Lazarus следует перезапустить. Теперь откройте пример проекта и попробуйте отредактировать узел на VST. На этот раз все должно быть хорошо.\
920+
921+# Внешние ссылки
922+
923+- [1](http://www.soft-gems.net) - Virtual Treeview tutorials/docs
924+- [Programando en Pascal](http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_Pascal) - Испанский учебник, посвященный FPC/Lazarus, размещается на Wikibooks.
925+
926+---
927+*From the Free Pascal wiki, page "VirtualTreeview Example for Lazarus/ru", as it stood on 2022-03-02 after a change by Zoltanleo, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history