2012-04-06 16 views
6

Nauczyłem się korzystać z TVirtualStringTree i znalazłem to doskonałe. Mam jedną niestandardową niewizualną listę o nazwie PackedList, która jest wypełniona innym wątkiem. I chcę pokazać całą zawartość listy w TVirtualStringTree w czasie rzeczywistym. Więc umieściłem jeden timer na mainformie, aby zaktualizować HexLog's (co jest TVirtualStringTree) RootNodeCount co 500ms.TVirtualStringTree i pionowe przewijanie nie działa poprawnie

Wszystkie moje dane pojawiają się w VirtualStringTree i nie mam żadnego problemu z szybkością, bardzo miło. Ale jest jeden problem z pionowym paskiem przewijania. Kiedy naciśnie Ctrl + End na kontrolce, aby przejść do końca listy, przechodzi gdzieś pośrodku. Podobnie, gdy przeciągam pasek przewijania do końca, nie dojdzie do końca. Ale HexLog zna DataCount. Dlaczego nie przeskoczył do końca? Jeśli naciśniesz kilka razy na Ctrl + END, to osiągnie koniec.

Wewnątrz rutyny zegara, chcę powiedzieć HexLog, aby przeskoczyć do końca listy według kodu. Jak mogę to zrobić i jak poprawnie obsługiwać pionowy pasek przewijania?

procedure TMainForm.StatusUpdateTimerTimer(Sender: TObject); 
begin 
    if (FirpList.ComOperationCount > 0) and (PacketList.Items.Count <> FirpList.ComOperationCount) then 
    begin 
     HexLog.RootNodeCount := PacketList.Items.Count; 
    end; 
end; 

procedure TMainForm.HexLogMeasureItem(Sender: TBaseVirtualTree; 
    TargetCanvas: TCanvas; Node: PVirtualNode; var NodeHeight: Integer); 
begin 
    if Sender.MultiLine[Node] then 
    begin 
    TargetCanvas.Font := Sender.Font; 
    NodeHeight := HexLog.ComputeNodeHeight(TargetCanvas, Node, 1, FirpList.ComOperations[Node^.Parent^.Index].DataAsHexString(FAppSettings.HexLogColumnCharWidth) + #13#10); 
    end; 
end; 

Appearance of HexLog

Sugerowana odpowiedź przez TLama nie działa prawidłowo, zobacz zdjęcie wyjaśnienie: TLama solution is not working

Zobacz ten link szczegółowy obraz wyjaśnienie: http://i43.tinypic.com/1445thi.png

Odpowiedz

6

, aby przejść do koniec drzewa, zadzwoń pod numer ScrollIntoView(GetLast).

Aby przewinąć do określonego węzła, sterowanie musi zsumować wysokości wszystkich wcześniejszych węzłów, aby możliwe było określenie właściwego przesunięcia.

Twoje węzły mają różne wysokości. Jeśli nie zainicjalizowano rzeczywistych wysokości węzłów gdzieś, to kontrolka używa właściwości DefaultNodeHeight dla niezainicjowanych węzłów. Wygląda na to, że wysokość jest krótsza niż jakakolwiek aktualna wysokość węzła w drzewie, więc sterowanie kończy obliczanie przesunięcia, które jest mniejsze niż oczekiwano, i przewija tam, zamiast tam, gdzie zamierzałeś.

Upewnij się, że obsługujesz zdarzenie OnMeasureItem i że masz ustawioną opcję toVariableNodeHeight w Options.MiscOptions. Jeśli tego nie zrobisz, sterowanie użyje po prostu aktualnie przypisanej wysokości dla każdego węzła i użyje domyślnej wysokości dla niezainicjowanego węzła.

Możesz uzyskać opisane tutaj zachowanie, jeśli ręcznie ustawisz NodeHeight zamiast ustawiać toVariableNodeHeight i obsługiwać OnMeasureItem.

+0

Witam Rob, mam obsługę w MeasureItem, aby obliczyć wysokość dziecka MultiLine. Parametr toVariableNodeHeight nie został ustawiony na MiscOptions. Zrobiłem to i teraz ScrollIntoView() przeskakuje do końca poprawnie. Ale nieznacznie przewija się w dół i zajmuje około 2 sekund, aby dotrzeć do końca, co jest nie do zaakceptowania:/ –

+0

Najważniejszą rzeczą, która zajęłaby czas, aby obliczyć przesunięcie ostatniego węzła, oprócz obliczenia wysokości wszystkich nowych węzłów, byłaby jeśli pamięć podręczna pozycji węzła była niepoprawna. Ustaw punkt przerwania w 'GetDisplayRect' i sprawdź, czy jesteś w stanie' tsUseCache' podczas wywoływania 'ScrollIntoView'. Gdy pamięć podręczna jest poprawna, drzewo może znaleźć lokalizacje węzłów o wiele szybciej, ale zmiana liczby węzłów unieważnia pamięć podręczną. W wątku roboczym potrzebny jest czas na jego ponowne sprawdzenie. Stan –

+0

(tsUseCache w FStates) w funkcji GetDisplayRect() zwraca wartość false, gdy wywoływana jest funkcja ScrollIntoView(). Co mam teraz zrobić? W przypadku tego projektu korzystałem z kontroli RichEdita, ponieważ z powodu problemów z szybkością, z którymi miałem do czynienia, zmieniłem cały projekt, aby korzystać z VirtualStringTree.Teraz znowu jestem w tym samym punkcie:/Właściwie mam trudności ze zrozumieniem, dlaczego muszę obliczyć wysokość całej wiadomości, aby przejść do końca listy. Po prostu chcę wyświetlać ostatnie wiadomości do użytkownika co 500 ms, gdy transakcja danych jest aktywna. –