VirtualTreeview Example for Lazarus/pl
│
English (en) │
español (es) │
français (fr) │
polski (pl) │
русский (ru) │
Oto kilka przykładów użycia VirtualTreeview dla Lazarusa (testowane na win32). Są one w większości zebrane z sieci, napisane dla Delphi oraz z samouczka/dokumentacji autorstwa Philippa Frenzela i Mike'a Lischke.
Samouczek/dokumenty dostępne kiedyś były na stronie http://www.soft-gems.net. Obecnie dokumentację w pliku pdf można pobrać ze strony documentation.help. Tutaj znajdziesz tylko szybki sposób korzystania z VirtualTreeview na Lazarus, a nie wyjaśnienia. Aby uzyskać wyjaśnienia i wiele innych funkcji/metod, pobierz oficjalne dokumenty i samouczek.
Podstawowe Drzewo Listview z 3 Kolumnami
1. Zainstaluj komponent. Uruchom Lazarusa.
2. Upuść komponent TVirtualStringTree na formę (znajdziesz go w zakładce Virtual Controls).
3. Przejdź do edytora źródeł (naciśnij klawisz F12). W sekcji Uses dodaj moduł o nazwie VirtualTrees (jeśli jeszcze go nie ma i nie jest to VirtualStringTree). Może to wyglądać następująco:
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
VirtualStringTree, VirtualTrees;
4. Przejdź do projektanta formularzy (naciśnij klawisz F12). Wybierz Virtual Tree Component. Na Inspektorze obiektów kliknij Nazwa, wpisz VST i naciśnij enter. Kliknij Nagłówek (rozwiń go) -> Kolumny, kliknij mały przycisk obok „0 items”. Kliknij 3 razy przycisk Dodaj, aby dodać 3 kolumny. Nie zamykaj tego okna.
5. W oknie Edycja kolumny jest teraz wybrana trzecia kolumna. Dostań się do Inspektora obiektów. Kliknij Options (rozwiń) -> ustaw coAllowClick na False.
6. Kliknij tekst. Wpisz Kolumna2.
7. Kliknij opcję Width, wpisz 100 i naciśnij klawisz Enter.
8. Przejdź do okna Edycja kolumny, wybierz pierwszą i drugą kolumnę i ustaw ich właściwość jak powyżej (w polu tekstowym użyj różnych nazw, np. Kolumna0, Kolumna1).
9. Zamknij okno edycji kolumn. Wybierz komponent Virtual Tree na formie. W Inspektorze obiektów przejdź do Header -> Options (rozwiń). Ustaw hoVisible na True.
10. Przewiń w dół, aby ustawić Header -> Style na hsFlatButtons.
11. Przewiń w dół do TreeOptions (rozwiń) -> MiscOptions (rozwiń) i ustaw toEditable na True. Ustaw toGridExtensions na True.
12. Przewiń w dół do SelectionOptions (rozwiń) -> ustaw toExtendedFocus na True. Ustaw toMultiSelect na True. W formularzu Form Designer zmień rozmiar VST (Virtual Tree Component), aby w razie potrzeby wyświetlić wszystkie kolumny.
13. Teraz dodaj 3 przyciski do formularza. Pobierz je z palety komponentów - Zakładka Standard (ikona z etykietą „Ok”).
14. Kliknij Button1, w Inspectorze obiektów zmień Caption na AddRoot. Kliknij Button2, zmień podpis na AddChild. Zmień podpis przycisku Button3 na Delete.
15. Zachowaj to tutaj i przejdź do edytora źródeł (naciśnij F12). W edytorze źródeł zamień wiersz:
{$mode objfpc}{$H+}
na
{$MODE DELPHI}
16. Pod słowem kluczowym "implementation" wklej następujące wiersze:
type
PTreeData = ^TTreeData;
TTreeData = record
Column0: String;
Column1: String;
Column2: String;
end;
17. Przejdź do projektanta formularzy (naciśnij klawisz F12). Wybierz VST. Przejdź do Inspektora obiektów, wybierz kartę Zdarzenia, przewiń w dół do zdarzenia onChange. Kliknij dwukrotnie combobox. Wklej następujący kod:
procedure TForm1.VSTChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
VST.Refresh;
end;
18. Przewiń do opcji onFocusChanged. Kliknij dwukrotnie i wklej następujący kod:
procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex);
begin
VST.Refresh;
end;
19. Przewiń do onFreeNode. Kliknij dwukrotnie i wklej następujący kod:
procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node);
if Assigned(Data) then begin
Data^.Column0 := '';
Data^.Column1 := '';
Data^.Column2 := '';
end;
end;
20. Przewiń w dół do onGetNodeDataSize. Kliknij dwukrotnie i wklej następujący kod:
procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
begin
NodeDataSize := SizeOf(TTreeData);
end;
21. Przewiń do onGetText. Kliknij dwukrotnie i wklej następujący kod:
procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node);
case Column of
0: CellText := Data^.Column0;
1: CellText := Data^.Column1;
2: CellText := Data^.Column2;
end;
end;
22. Naciśnij klawisz F12, aby przejść do projektanta formularzy. Kliknij dwukrotnie przycisk AddRoot. Wklej następujący kod:
procedure TForm1.Button1Click(Sender: TObject);
var
Data: PTreeData;
XNode: PVirtualNode;
Rand: Integer;
begin
Randomize;
Rand := Random(99);
XNode := VST.AddChild(nil);
if VST.AbsoluteIndex(XNode) > -1 then
begin
Data := VST.GetNodeData(Xnode);
Data^.Column0 := 'One ' + IntToStr(Rand);
Data^.Column1 := 'Two ' + IntToStr(Rand + 10);
Data^.Column2 := 'Three ' + IntToStr(Rand - 10);
end;
end;
23. Naciśnij klawisz F9, aby uruchomić projekt w celu sprawdzenia. Kliknij AddRoot, aby dodać węzeł. Jeśli jest w porządku, węzeł zostanie dodany na VST.
24. Zatrzymaj wykonywanie. W formularzu kliknij dwukrotnie przycisk podpisany jako AddChild. Wklej następujący kod:
procedure TForm1.Button2Click(Sender: TObject);
var
XNode: PVirtualNode;
Data: PTreeData;
begin
if not Assigned(VST.FocusedNode) then
Exit;
XNode := VST.AddChild(VST.FocusedNode);
Data := VST.GetNodeData(Xnode);
Data^.Column0 := 'Ch 1';
Data^.Column1 := 'Ch 2';
Data^.Column2 := 'Ch 3';
VST.Expanded[VST.FocusedNode] := True;
end;
25. W formularzu kliknij dwukrotnie przycisk podpisany jako Delete. Wklej następujący kod:
procedure TForm1.Button3Click(Sender: TObject);
begin
VST.DeleteSelectedNodes;
end;
26. Uruchom projekt, naciskając klawisz F9, aby sprawdzić program. Dodaj węzeł, dziecko i usuń je.
27. Spróbuj edytować węzeł. Wybierz węzeł i naciśnij F2, wpisz nową wartość. Jeśli widzisz, co piszesz, to jest OK. W przeciwnym razie przeczytaj poniżej „Nie można zobaczyć edycji komórki”.
28. Aby VST pokazywał nową wartość wprowadzoną po edycji, przejdź do Projektanta formularzy, wybierz VST. W Inspektorze obiektów -> Zdarzenia -> zdarzenie OnNewText kliknij dwukrotnie. Wklej następujący kod:
procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; NewText: WideString);
var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node);
case Column of
0: Data^.Column0 := NewText;
1: Data^.Column1 := NewText;
2: Data^.Column2 := NewText;
end;
end;
Na tym przykład podstawowego zastosowania kończy się. Możesz upuścić kilka dodatkowych przycisków na formularz, aby przetestować kilka innych poleceń podanych poniżej. Następnymi krokami byłoby pokazanie pola wyboru, obrazu, koloru czcionki i dodanie combobox w węźle.
- Inny sposób na dodanie węzła głównego
procedure TForm1.Button8Click(Sender: TObject);
begin
with VST do
RootNodeCount := RootNodeCount + 1;
end;
- Inny sposób na dodanie dziecka
procedure TForm1.Button9Click(Sender: TObject);
begin
if Assigned(VST.FocusedNode) then
VST.ChildCount[VST.FocusedNode] := VST.ChildCount[VST.FocusedNode] + 1;
end;
- Wybierz i usuń dzieci węzła
procedure TForm1.Button4Click(Sender: TObject);
var
c: Integer;
begin
if not Assigned(VST.FocusedNode) then
Exit;
if VST.HasChildren[VST.FocusedNode] then
begin
c := VST.ChildCount[VST.FocusedNode];
VST.DeleteChildren(VST.FocusedNode);
ShowMessage('Number of deleted child:' + #13#10 + IntToStr(c));
end;
end;
- Usunięcie węzeł
procedure TForm1.Button5Click(Sender: TObject);
begin
{VST.Clear; //Delete All Nodes}
if not Assigned(VST.FocusedNode) then
Exit;
VST.DeleteNode(VST.FocusedNode);
end;
- Wyszukaj i wybierz węzeł
procedure TForm1.Button6Click(Sender: TObject);
bar
XNode: PVirtualNode;
Data: PTreeData;
begin
XNode := VST.GetFirst;
while XNode <> nil do
begin
Data := VST.GetNodeData(XNode);
if Data^.Column0 = '1' then
begin
VST.ClearSelection;
VST.Selected[XNode] := True;
VST.SetFocus;
break;
end else
XNode := VST.GetNextSibling(XNode);
end;
end;
- Wybierz rodzica
procedure TForm1.Button13Click(Sender: TObject);
var
XNode: PVirtualNode;
begin
if not Assigned(VST.FocusedNode) then
Exit;
XNode := VST.FocusedNode;
while VST.GetNodeLevel(XNode) > 0 do
begin
XNode := XNode.Parent;
VST.Selected[XNode] := True;
end;
VST.Refresh;
VST.SetFocus;
end;
- Wyszukaj wszystko
procedure TForm1.Button7Click(Sender: TObject);
var
XNode: PVirtualNode;
Data: PTreeData;
begin
if VST.GetFirst = nil then Exit;
XNode := nil;
repeat
if XNode = nil then
XNode := VST.GetFirst
else
XNode := VST.GetNext(XNode);
Data := VST.GetNodeData(XNode);
if (Data^.Column0 = '1') or (Data^.Column1 = '1') or (Data^.Column2 = '1') then
begin
ShowMessage('Found at Node Level : ' + IntToStr(VST.GetNodeLevel(XNode)));
break;
end;
until XNode = VST.GetLast();
end;
- Wyszukaj następny
procedure TForm1.Button8Click(Sender: TObject);
var
XNode: PVirtualNode;
Data: PTreeData;
begin
if not Assigned(VST.GetFirst) then
Exit
else
XNode := VST.GetFirst;
repeat
XNode := VST.GetNext(XNode);
Data := VST.GetNodeData(XNode);
if Pos(LowerCase(SearchEdit.Text), LowerCase(Data^.Column0)) > 0 then
begin
VST.FocusedNode := XNode;
VST.Selected[XNode] := True;
if MessageDlg('Item found?', mtConfirmation, mbYesNo, 0) = mrYes then
begin
VST.Expanded[XNode] := True;
VST.Refresh;
VST.SetFocus;
Break;
end;
end;
until XNode = VST.GetLast;
end;
- Wstaw węzeł
procedure TForm1.Button12Click(Sender: TObject);
var
XNode: PVirtualNode;
begin
if Assigned(VST.FocusedNode) then
begin
XNode := VST.InsertNode(VST.FocusedNode,amInsertBefore);
// To Insert After Selected Node.
{XNode := VST.InsertNode(VST.FocusedNode,amInsertAfter);}
VST.Refresh;
end;
end;
- Ustaw wysokość węzła
procedure TForm1.Button14Click(Sender: TObject);
begin
if Assigned(VST.FocusedNode) then
VST.NodeHeight[VST.FocusedNode] := 32;
end;
- Zapisz i załaduj
Proste drzewo (bez kolumn) można zapisać i załadować jako:
VST.SaveToFile('filename.dat');
VST.LoadFromFile('filename.dat');
Aby zapisać i załadować powyższy przykład, umieść 2 przyciski w formularzu, zmień nazwę Caption na „Save” i „Load”. Wybierz VST, w Inspektorze obiektów -> TreeOptions -> StringOptions upewnij się, że parametr toSaveCaptions ma wartość True. Przejdź do zakładki Zdarzenia Inspektora obiektów. Przewiń w dół do OnLoadNode, kliknij dwukrotnie, a następnie wklej kod:
procedure TForm1.VSTLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
Data: PTreeData;
Len: Integer;
begin
Data := VST.GetNodeData(Node);
Stream.read(Len, SizeOf(Len));
SetLength(Data^.Column0, Len);
Stream.read(PChar(Data^.Column0)^, Len);
Stream.read(Len, SizeOf(Len));
SetLength(Data^.Column1, Len);
Stream.read(PChar(Data^.Column1)^, Len);
Stream.read(Len, SizeOf(Len));
SetLength(Data^.Column2, Len);
Stream.read(PChar(Data^.Column2)^, Len);
end;
Ponownie na karcie Zdarzenia Inspektora obiektów - przewiń w dół do OnSaveNode, kliknij dwukrotnie, i wklej kod:
procedure TForm1.VSTSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
var
Data: PTreeData;
Len: Integer;
begin
Data := VST.GetNodeData(Node);
Len := Length(Data^.Column0);
Stream.write(Len, SizeOf(Len));
Stream.write(PChar(Data^.Column0)^, Len);
Len := Length(Data^.Column1);
Stream.write(Len, SizeOf(Len));
Stream.write(PChar(Data^.Column1)^, Len);
Len := Length(Data^.Column2);
Stream.write(Len, SizeOf(Len));
Stream.write(PChar(Data^.Column2)^, Len);
end;
W formularzu kliknij dwukrotnie przycisk "Save" i wklej kod:
procedure TForm1.Button10Click(Sender: TObject);
begin
VST.SaveToFile('C:\vst.dat');
end;
W formularzu kliknij dwukrotnie przycisk "Load" i wklej kod:
procedure TForm1.Button11Click(Sender: TObject);
begin
VST.LoadFromFile('C:\vst.dat');
end;
Teraz przetestuj zapisywanie i ładowanie drzewa.
- Problem z przewijaniem
Nagłówek widoku drzewa znika całkowicie lub częściowo podczas przewijania. Nie mogłem znaleźć na to dobrego rozwiązania. Jednym ze sposobów rozwiązania tego problemu jest ustawienie wysokości nagłówka na 0, a następnie użycie ogólnej etykiety dla kolumn. Jest to dobre, gdy jest kilka kolumn i wszystkie są widoczne bez przewijania w poziomie. Lub wysokość nagłówka można ustawić na wyższą wartość, np. 25 lub 30. VST.Refresh można dodać do zdarzenia OnScroll.
W wersji 5.5.3.1 nie zaobserowałem tego efektu, więc prawdopodobnie został on naprawiony.
- Zmiana rozmiaru kolumny
Nie można zmienić rozmiaru kolumny, przeciągając myszą nagłówek VST. Może to być błąd nagłówka lub coś przeoczyłem. Jeśli dotyczy nagłówka, prawdopodobnie zostanie naprawiony w następnej wersji Lazarus. Zobacz ten link:
http://bugs.freepascal.org/view.php?id=11209
W wersji 5.5.3.1 nie zaobserowałem tego efektu, więc prawdopodobnie został on naprawiony.
Poniższy kod może być przydatny dla tych, którzy chcieliby go sprawdzić lub wykorzystać w jakimś innym celu.
W każdym razie można zmienić rozmiar kolumny z kodu. Po naciśnięciu prawego przycisku myszy i przesunięciu kółka myszy w górę szerokość wybranej kolumny zwiększa się, a następnie naciśnięcie prawego przycisku myszy i przesunięcie kółka myszy w dół, aby zmniejszyć szerokość wybranej kolumny. Aby to zrobić:
1. Dodaj zmienną w edytorze źródłowym o nazwie CurCol: Integer; Wygląda to tak:
var
Form1: TForm1;
CurCol: Integer; // <- Add this line only.
implementation
{ TForm1 }
2. W Projektancie formularzy kliknij dwukrotnie formularz, aby wygenerować zdarzenie OnCreate. Wewnątrz procedury OnCreate wpisz Form1.OnMouseWheelUp:= i naciśnij Ctrl+Shift+C, spowoduje to uzupełnienie kodu i utworzenie szkieletu zdarzenia MouseWheelUp. Wróć teraz do procedury TForm1.FormCreate(Sender: TObject); i dodaj kolejne wydarzenie dla MouseWheelDown. Wpisz Form1.OnMouseWheelDown:= i naciśnij Ctrl+Shift+C, aby wygenerować zdarzenie MouseWheelDown. Procedura FormCreate wygląda teraz następująco:
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.OnMouseWheelUp := @Form1MouseWheelUp;
Form1.OnMouseWheelDown := @Form1MouseWheelDown;
end;
3. Wypełnij procedurę TForm1.Form1MouseWheelUp w ten sposób:
procedure TForm1.Form1MouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
if VST.Focused and (ssRight in Shift) then
VST.Header.Columns[CurCol].Width := VST.Header.Columns[CurCol].Width + 10;
end;
4. Wypełnij procedurę TForm1.Form1MouseWheelDown jak poniżej:
procedure TForm1.Form1MouseWheelDown(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
if VST.Focused and (ssRight in Shift) then
VST.Header.Columns[CurCol].Width := VST.Header.Columns[CurCol].Width - 10;
end;
5. Przejdź do Projektanta formularzy (naciśnij F12), wybierz VST, na karcie Zdarzenia Inspektora obiektów przewiń do OnFocusChanged, kliknij dwukrotnie i wklej:
procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex);
begin
CurCol := Column;
end;
Po uruchomieniu programu kliknij kolumnę, a następnie przytrzymaj prawy przycisk myszy i przesuń kółko w górę, aby zwiększyć szerokość, lub kółko w dół, aby ją zmniejszyć. W razie potrzeby możesz dostosować powyższe procedury. Możesz też dodać zdarzenie klawiatury z czymś takim jak "if (key=187) i (ssShift in Shift) then", aby reagować na naciśnięcie klawiszy Shift + "+".
Pole wyboru (CheckBox)
On Form Designer select VST. Go to: W formularzu wybierz VST i wykonaj:
- Inspektor obiektów -> Właściwości -> CheckImageKind i wybierz ckDarkCheck.
- Inspektor obiektów -> Właściwości -> TreeOptions -> MiscOptions -> toCheckSupport i ustaw na True.
Teraz przejdź do zakładki Zdarzenia.
- Przewiń do OnInitNode. Kliknij dwukrotnie i wklej następujący kod:
procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
Level: Integer;
begin
Level := VST.GetNodeLevel(Node);
if Level = 0 then
Node^.CheckType := ctCheckBox;
if Level = 2 then
Node^.CheckType := ctRadioButton;
if Level = 1 then
begin
Node^.CheckType := ctTriStateCheckBox;
Node^.CheckState := csCheckedNormal;
end;
if Level = 3 then
Node^.CheckType := ctButton;
end;
Uruchom program, dodaj węzeł i dziecko, a następnie dodaj dziecko do dziecka, i sprawdź, czy możesz poprawnie zaznaczyć i odznaczyć pola wyboru. Jeśli nie, zamknij program. Przejdź do zakładki Zdarzenia Inspektora obiektów.
- Przewiń do OnChecked, kliknij dwukrotnie i wklej:
procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
VST.Refresh;
end;
- Przewiń do opcji OnChecking, kliknij dwukrotnie i wklej:
procedure TForm1.VSTChecking(Sender: TBaseVirtualTree; Node: PVirtualNode;
var NewState: TCheckState; var Allowed: Boolean);
begin
VST.Refresh;
end;
Mam nadzieję, że teraz jest ok. Aby określić stan pola wyboru, użyj:
if XNode.CheckState = csCheckedNormal then
ShowMessage('Checked.');
Inne stany to:
csUncheckedNormal = niezaznaczone i nie wciśnięte
csUncheckedPressed = niezaznaczone i wciśnięte
csCheckedNormal = zaznaczone i nie wciśnięte
csCheckedPressed = zaznaczone i wciśnięte
csMixedNormal = 3-stanowe pole wyboru i nie wciśnięte
csMixedPressed = 3-stanowe pole wyboru i wciśnięte
Inne typy to:
ctNone
ctTriStateCheckBox
ctCheckBox
ctRadioButton
ctButton
- Aby przechwycić przycisk pola wyboru (ctButton) Click
Przejdź do zakładki Zdarzenia Inspektora obiektów. Przewiń do OnChecked, kliknij dwukrotnie i wklej kod:
procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
if Node^.CheckType = ctButton then
ShowMessage('Ok.');
VST.Refresh;
end;
Koniec pola wyboru.
Obrazy
Aby wyświetlić obrazy w węzłach VST, należy utworzyć listę obrazów.
- Przejdź do palety komponentów -> Common Controls. Wybierz i upuść składnik TImageList na formularzu. Kliknij prawym przyciskiem myszy ikonę komponentu i wybierz ImageList Editor. Kliknij przycisk Dodaj i wybierz kilka zdjęć (na razie co najmniej 3), a następnie kliknij przycisk wyboru, aby zaakceptować i zamknąć Edytor ImageList. Nawiasem mówiąc, istnieje kilka fajnych zdjęć, które można pobrać ze strony http://www.famfamfam.com/lab/icons/silk/
- Teraz w Projektancie formularzy wybierz VST, a na karcie Właściwości Inspektora obiektów przewiń do Images i wybierz ImageList1
- Na karcie Zdarzenia Inspektora obiektów przewiń do OnGetImageIndex, kliknij dwukrotnie i wklej kod:
procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean;
var ImageIndex: Integer);
begin
if Kind in [ikNormal , ikSelected] then // Zarówno wybrane jak i nie
begin
if Column = 0 then // jeśli to pierwsza kolumna
ImageIndex := 0; // pierwszy obraz z listy ImageList1
if Column = 1 then // jeśli to druga kolumna
ImageIndex := 1; // drugi obraz z listy ImageList1
if Sender.FocusedNode = Node then // Pokaż tylko, jeśli wybrany
if Column = 2 then // jeśli to trzecia kolumna
ImageIndex := 2; // trzeci obraz z listy ImageList1
end;
{Sender.NodeHeight[node] := 40; //Jeśli obraz jest duży}
end;
Kolor czcionki
W Projektancie formularzy wybierz VST, a na karcie Zdarzenia Inspektora obiektów przewiń do OnPaintText, kliknij dwukrotnie i wklej kod:
procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType);
var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node);
if Data^.Column0 = 'niebo' then
TargetCanvas.Font.Color := clBlue;
if Column = 1 then
begin
TargetCanvas.Font.Color := clRed;
TargetCanvas.Font.Style := Font.Style + [fsItalic];
end;
if Column = 2 then
begin
// ImageList1.Draw(Form1.Canvas, -1, -1, 2); {draw top left of form, 3rd image of ImageList1??}
TargetCanvas.Font.Size := 9;
TargetCanvas.Font.Color := clHighlightText;
end;
end;
Teraz uruchom program. Dodaj jakieś węzły. Zobaczysz, że tekst w drugiej kolumnie jest czerwony. Spróbuj teraz zmienić tekst jakiegoś węzła w pierwszej kolumnie (klawisz F2) wpisując słowo "niebo". Po zatwierdzeniu zmiany tekst powinien stać się niebieski.
Dodanie ComboBox
- Myślę, że masz otwarty projekt w Lazarus IDE z VST i możesz edytować węzły. Jeśli nie, zobacz „Podstawowy widok drzewa z 3 kolumnami” powyżej i przynajmniej wykonaj kroki od 1 do 21.
- Poniżej znajduje się treść pliku modułu o nazwie combo. Skopiuj ten moduł i zapisz jako combo.pas w katalogu projektu. Pod klauzulą uses programu dodaj nazwę mocułu combo. Może to wyglądać następująco:
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
VirtualStringTree, VirtualTrees, combo;
- Moduł combo.pas
unit combo;
{$mode delphi}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
VirtualStringTree, VirtualTrees, messages, windows, StdCtrls;
type
TStringEditLink = class(TInterfacedObject, IVTEditLink)
private
FEdit: TWinControl;
FTree: TVirtualStringTree;
FNode: PVirtualNode;
FColumn: Integer;
protected
procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
public
destructor Destroy; override;
function BeginEdit: Boolean; stdcall;
function CancelEdit: Boolean; stdcall;
function EndEdit: Boolean; stdcall;
function GetBounds: TRect; stdcall;
function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
procedure ProcessMessage(var Message: TMessage); stdcall;
procedure SetBounds(R: TRect); stdcall;
end;
implementation
destructor TStringEditLink.Destroy;
begin
FEdit.Free;
inherited;
end;
procedure TStringEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
case Key of
VK_ESCAPE:
begin
FTree.CancelEditNode;
Key := 0;
FTree.setfocus;
end;
VK_RETURN:
begin
PostMessage(FTree.Handle, WM_KEYDOWN, VK_DOWN, 0);
Key := 0;
FTree.EndEditNode;
FTree.setfocus;
end;
end; //case
end;
function TStringEditLink.BeginEdit: Boolean;
begin
Result := True;
//FEdit.Height := (FTree.DefaultNodeHeight - 1); //Needed for editbox. Not combo
FEdit.Show;
TComboBox(FEdit).DroppedDown := True;
FEdit.SetFocus;
end;
function TStringEditLink.CancelEdit: Boolean;
begin
Result := True;
FEdit.Hide;
end;
function TStringEditLink.EndEdit: Boolean;
var
s: String;
begin
Result := True;
s := TComboBox(FEdit).Text;
FTree.Text[FNode, FColumn] := s;
FTree.InvalidateNode(FNode);
FEdit.Hide;
FTree.SetFocus;
end;
function TStringEditLink.GetBounds: TRect;
begin
Result := FEdit.BoundsRect;
end;
function TStringEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
begin
Result := True;
FTree := Tree as TVirtualStringTree;
FNode := Node;
FColumn := Column;
FEdit.Free;
FEdit := nil;
FEdit := TComboBox.Create(nil);
with FEdit as TComboBox do
begin
Visible := False;
Parent := Tree;
Items.Add('Google');
Items.Add('Yahoo');
Items.Add('Altavista');
OnKeyDown := EditKeyDown;
end;
end;
procedure TStringEditLink.ProcessMessage(var Message: TMessage);
begin
FEdit.WindowProc(Message);
end;
procedure TStringEditLink.SetBounds(R: TRect);
var
Dummy: Integer;
begin
FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
FEdit.BoundsRect := R;
end;
end.
- Po zapisaniu pliku, w Projektancie formularzy wybierz VST, a we właściwościach Inspektora obiektów przewiń do TreeOptions -> MiscOptions, ustaw wartość na toEditable na True. Następnie przejdź do TreeOptions -> SelectionOptions, ustaw toExtendedFocus na True.
- Przejdź do zakładki Zdarzenia Inspektora obiektów. Przewiń do OnCreateEditor, kliknij dwukrotnie i wklej kod:
procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
begin
EditLink := TStringEditLink.Create;
end;
- W zakładce Zdarzenia Inspektora obiektów przewiń do OnNewText, kliknij dwukrotnie i wklej kod:
procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; NewText: WideString);
var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node);
case Column of
0: Data^.Column0 := NewText;
1: Data^.Column1 := NewText;
2: Data^.Column2 := NewText;
end;
end;
Uruchom program, wybierz węzeł i naciśnij F2, aby uzyskać ComboBox. Po naciśnięciu wprowadź nową wartość, a powinna ona pojawić się w węźle.
Jeśli nie można zobaczyć edycji komórki
Otwórz plik modułu VirtualStringTree.pas (jeśli nadal pracujesz nad powyższym przykładowym projektem, kliknij prawym przyciskiem myszy VirtualStringTree w obszarze słowa kluczowego uses i wybierz Znajdź deklarację. Spowoduje to otwarcie pliku na następnej karcie. Przejdź do zakładki tego pliku). Przejdź do „funkcji TStringEditLink.BeginEdit: Boolean; stdcall;”. To wygląda jak:
function TStringEditLink.BeginEdit: Boolean; stdcall;
// Notifies the edit link that editing can start now. Descentants may cancel node edit
// by returning False.
begin
Result := not FStopping;
if Result then
begin
FEdit.Show;
FEdit.SelectAll;
FEdit.SetFocus;
end;
end;
Teraz dodaj "FEdit.Height:=18;". Powinno to wyglądać następująco:
function TStringEditLink.BeginEdit: Boolean; stdcall;
// Notifies the edit link that editing can start now. Descentants may cancel node edit
// by returning False.
begin
Result := not FStopping;
if Result then
begin
FEdit.Show;
FEdit.SelectAll;
FEdit.SetFocus;
FEdit.Height := 18; // <--- Added this line.
end;
end;
Zapisz plik (naciśnij Ctrl + S). Jeśli korzystasz z przykładowego projektu, zamknij go (Projekt -> Zamknij projekt). Kliknij Narzędzia -> Konfiguruj "Build Lazarusa" ... W Profilu budowania wybierz Czyść + Buduj wszystko, a następnie kliknij przycisk Buduj. Po kompilacji należy ponownie uruchomić Lazarusa. Teraz otwórz przykładowy projekt i spróbuj edytować węzeł na VST. Tym razem powinno być dobrze.
Linki zewnętrzne
- www.soft-gems.net (obecnie nie mogę znaleźć tutaj tej dokumentacji)
- Virtual Treeview instruktaże/dokumenty aktualna lokalizacja ww. dokumentacji
- Virtual Treeview dokumentacja w pliku pdf
- Programando en Pascal - Hiszpański samouczek poświęcony FPC/Lazarus, prowadzony w Wikibooks.
- Kurs Object Pascal - Polski samouczek poświęcony FPC, prowadzony w Wikibooks.