Представляем вашему вниманию немного переработанный компонент
TreeView, работающий быстрее своего собрата из стандартной поставки Delphi.
Кроме того, была добавлена возможность вывода текста узлов и пунктов в жирном
начертании (были использованы методы TreeView, хотя, по идее, необходимы были
свойства TreeNode. Мне показалось, что это будет удобнее).
Для сравнения:
TreeView:
128 сек. для загрузки 1000 элементов (без сортировки)*
270 сек. для сохранения 1000 элементов (4.5 минуты!!!)
HETreeView:
1.5 сек. для загрузки 1000 элементов - ускорение около 850%!!!
(2.3 секунды без сортировки = stText)*
0.7 сек. для сохранения 1000 элементов - ускорение около
3850%!!!
Примечание:
Все операции выполнялись на медленной машине 486SX 33 Mгц, 20 Mб RAM.
Если TreeView пуст, загрузка происходит за 1.5 секунды, плюс 1.5 секунды на
стирание 1000 элементов (общее время загрузки составило 3 секунды). В этих
условиях стандартный компонент TTreeView показал общее время 129.5 секунд.
Очистка компонента осуществлялась вызовом функции SendMessage(hwnd,
TVM_DELETEITEM, 0, Longint(TVI_ROOT)).
Проведите несколько приятных
минут, развлекаясь с компонентом.
unit HETreeView;
{$R-}// Описание: Реактивный TreeView(*
TREEVIEW:
128 сек. для загрузки 1000 элементов (без сортировки)*
270 сек. для сохранения 1000 элементов (4.5 минуты!!!)
HETREEVIEW:
1.5 сек. для загрузки 1000 элементов - ускорение около 850%!!!
(2.3 секунды без сортировки = stText)*
0.7 сек. для сохранения 1000 элементов - ускорение около 3850%!!!
NOTES:
- Все операции выполнялись на медленной машине 486SX 33 Mгц, 20 Mб RAM.
- * Если TTreeView пуст, загрузка происходит за 1.5 секунды,
плюс 1.5 секунды на стирание 1000 элементов
(общее время загрузки составило 3 секунды).
В этих условиях стандартный компонент TreeView показал общее время 129.5 секунд.
Очистка компонента осуществлялась вызовом функции
SendMessage(hwnd, TVM_DELETEITEM, 0, Longint(TVI_ROOT)).
*)interfaceuses
SysUtils, Windows, Messages, Classes, Graphics,
Controls, Forms, Dialogs, ComCtrls, CommCtrl;
type
THETreeView = class(TTreeView)
private
FSortType: TSortType;
procedure SetSortType(Value: TSortType);
protectedfunction GetItemText(ANode: TTreeNode): string;
publicconstructor Create(AOwner: TComponent); override;
function AlphaSort: Boolean;
function CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
procedure LoadFromFile(const AFileName: string);
procedure SaveToFile(const AFileName: string);
procedure GetItemList(AList: TStrings);
procedure SetItemList(AList: TStrings);
//Жирное начертание шрифта 'Bold' должно быть свойством TTreeNode, но...function IsItemBold(ANode: TTreeNode): Boolean;
procedure SetItemBold(ANode: TTreeNode; Value: Boolean);
publishedproperty SortType: TSortType read FSortType write SetSortType default
stNone;
end;
procedureRegister;
implementationfunction DefaultTreeViewSort(Node1, Node2: TTreeNode; lParam: Integer): Integer;
stdcall;
begin{with Node1 do
if Assigned(TreeView.OnCompare) then
TreeView.OnCompare(Node1.TreeView, Node1, Node2, lParam, Result)
else}
Result := lstrcmp(PChar(Node1.Text), PChar(Node2.Text));
end;
constructor THETreeView.Create(AOwner: TComponent);
begininherited Create(AOwner);
FSortType := stNone;
end;
procedure THETreeView.SetItemBold(ANode: TTreeNode; Value: Boolean);
var
Item: TTVItem;
Template: Integer;
beginif ANode = nilthen
Exit;
if Value then
Template := -1
else
Template := 0;
with Item dobegin
mask := TVIF_STATE;
hItem := ANode.ItemId;
stateMask := TVIS_BOLD;
state := stateMask and Template;
end;
TreeView_SetItem(Handle, Item);
end;
function THETreeView.IsItemBold(ANode: TTreeNode): Boolean;
var
Item: TTVItem;
begin
Result := False;
if ANode = nilthen
Exit;
with Item dobegin
mask := TVIF_STATE;
hItem := ANode.ItemId;
if TreeView_GetItem(Handle, Item) then
Result := (state and TVIS_BOLD) <> 0;
end;
end;
procedure THETreeView.SetSortType(Value: TSortType);
beginif SortType <> Value thenbegin
FSortType := Value;
if ((SortType in [stData, stBoth]) and Assigned(OnCompare)) or
(SortType in [stText, stBoth]) then
AlphaSort;
end;
end;
procedure THETreeView.LoadFromFile(const AFileName: string);
var
AList: TStringList;
begin
AList := TStringList.Create;
Items.BeginUpdate;
try
AList.LoadFromFile(AFileName);
SetItemList(AList);
finally
Items.EndUpdate;
AList.Free;
end;
end;
procedure THETreeView.SaveToFile(const AFileName: string);
var
AList: TStringList;
begin
AList := TStringList.Create;
try
GetItemList(AList);
AList.SaveToFile(AFileName);
finally
AList.Free;
end;
end;
procedure THETreeView.SetItemList(AList: TStrings);
var
ALevel, AOldLevel, i, Cnt: Integer;
S: string;
ANewStr: string;
AParentNode: TTreeNode;
TmpSort: TSortType;
function GetBufStart(Buffer: PChar; var ALevel: Integer): PChar;
begin
ALevel := 0;
while Buffer^ in [' ', #9] dobegin
Inc(Buffer);
Inc(ALevel);
end;
Result := Buffer;
end;
begin// Удаление всех элементов - в обычной ситуации// подошло бы Items.Clear, но уж очень медленно
SendMessage(handle, TVM_DELETEITEM, 0, Longint(TVI_ROOT));
AOldLevel := 0;
AParentNode := nil;
//Снятие флага сортировки
TmpSort := SortType;
SortType := stNone;
tryfor Cnt := 0 to AList.Count - 1 dobegin
S := AList[Cnt];
if (Length(S) = 1) and (S[1] = Chr($1A)) then
Break;
ANewStr := GetBufStart(PChar(S), ALevel);
if (ALevel > AOldLevel) or (AParentNode = nil) thenbeginif ALevel - AOldLevel > 1 thenraise Exception.Create('Неверный уровень TreeNode');
endelsebeginfor i := AOldLevel downto ALevel dobegin
AParentNode := AParentNode.Parent;
if (AParentNode = nil) and (i - ALevel > 0) thenraise Exception.Create('Неверный уровень TreeNode');
end;
end;
AParentNode := Items.AddChild(AParentNode, ANewStr);
AOldLevel := ALevel;
end;
finally//Возвращаем исходный флаг сортировки...
SortType := TmpSort;
end;
end;
procedure THETreeView.GetItemList(AList: TStrings);
var
i, Cnt: integer;
ANode: TTreeNode;
begin
AList.Clear;
Cnt := Items.Count - 1;
ANode := Items.GetFirstNode;
for i := 0 to Cnt dobegin
AList.Add(GetItemText(ANode));
ANode := ANode.GetNext;
end;
end;
function THETreeView.GetItemText(ANode: TTreeNode): string;
begin
Result := StringOfChar(' ', ANode.Level) + ANode.Text;
end;
function THETreeView.AlphaSort: Boolean;
var
I: Integer;
beginif HandleAllocated thenbegin
Result := CustomSort(nil, 0);
endelse
Result := False;
end;
function THETreeView.CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
var
SortCB: TTVSortCB;
I: Integer;
Node: TTreeNode;
begin
Result := False;
if HandleAllocated thenbeginwith SortCB dobeginifnot Assigned(SortProc) then
lpfnCompare := @DefaultTreeViewSort
else
lpfnCompare := SortProc;
hParent := TVI_ROOT;
lParam := Data;
Result := TreeView_SortChildrenCB(Handle, SortCB, 0);
end;
if Items.Count > 0 thenbegin
Node := Items.GetFirstNode;
while Node <> nildobeginif Node.HasChildren then
Node.CustomSort(SortProc, Data);
Node := Node.GetNext;
end;
end;
end;
end;
//Регистрация компонентаprocedureRegister;
begin
RegisterComponents('Win95', [THETreeView]);
end;
end.
Это модифицированная версия компонента TreeView в Delphi, предназначенная для улучшения его производительности путем уменьшения времени загрузки и сохранения больших объемов данных.
Основные изменения, сделанные в этом компоненте:
Добавлен свойство SortType, которое позволяет пользователю указать, на основе какого критерия должна быть отсортирована дерево-строка: текстом или данными.
Реализован custom-сортирующий алгоритм с помощью метода CustomSort, который позволяет пользователю предоставить функцию сравнения.
Методы LoadFromFile и SaveToFile были оптимизированы для уменьшения времени загрузки и сохранения больших объемов данных.
Добавлены методы GetItemList и SetItemList, которые позволяют пользователю программно получать и задавать список элементов дерево-строки.
Улучшение производительности демонстрируется сравнением оригинального компонента TreeView с модифицированной версией (HETreeView) в отношении загрузки и сохранения больших объемов данных. Результаты показывают, что модифицированная версия значительно быстрее оригинальной, с коэффициентом ускорения около 850% для загрузки 1000 элементов и около 3850% для их сохранения.
Код также включает в себя комментарии и примечания, объясняющие изменения, сделанные в этом компоненте, и мотивы за ними. В целом, это модифицированное дерево-строка должно быть полезно для любого, кто работает с большими объемами данных в контроле дерева-строки.
Ускорение работы TreeView: новый компонент TreeView, работающий быстрее стандартного компонента Delphi на 850% для загрузки и на 3850% для сохранения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.