КАТЕГОРИИ:
АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
Листинг 5.1. Приложение Mini-Registry-browser, главный модульunit main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, Outline, ComCtrls, ImgList, ExtCtrls; type TForml = class(TForm) TreeViewl: TTreeView; ListViewl: TListView; ImageListl: TImageList; Splitterl: TSplitter; procedure FormCreate(Sender: TObject); procedure TreeViewlChange(Sender: TObject; Node: TTreeNode); procedure FormDestroy(Sender: TObject); procedure TreeViewlExpanded(Sender: TObject; Node: TTreeNode); procedure TreeViewlGetlmagelndex(Sender: TObject; Node: TTreeNode); private { Private declarations } public { Public declarations } procedure ShowSubKeys(ParentNode: TTreeNode;depth: Integer); function GetFullNodeName(Node: TTreeNode):string; end; var Forml: TForml; implementation uses registry; {$R *.DFM} var reg : TRegistry; procedure TForml.FormCreate(Sender: TObject); var root : TTreeNode; begin Reg := TRegistry.Create; ListViewl.ViewStyle := vsReport; with ListViewl do begin with Columns.Add do begin Width := ListViewl.Width div 3-2; Caption := 'Name'; end; with Columns.Add do begin Width := ListViewl.Width div 3*2-2; Caption := 'Value'; end; end; TreeViewl.Items.Clear; Reg.RootKey := HKEY_LOCAL_MACHINE; Root := TreeViewl.Items.Add(nil,'HKEY_LOCAL_MACHINE'); TreeViewl.Items.AddChildtroot,''); end; procedure TForml.FormDestroy(Sender: TObject); begin Reg.Free; end; function TForml.GetFullNodeName(Node: TTreeNode):string; var CurNode : TTreeNode; begin Result:=''; CurNode := Node; while CurNode.Parentonil do begin Result:= '\'+CurNode.Text + Result; CurNode := CurNode.Parent; end; end; procedure TForml.TreeViewlChange(Sender: TObject; Node: TTreeNode); var s: string; Keylnfo : TRegKeylnfo; ValueNames : TStringList; i : Integer; DataType : TRegDataType; begin ListViewl.Items.Clear; s:= GetFullNodeName(Node); if not Reg.OpenKeyReadOnly(s) then Exit; Reg.GetKeylnfo(Keylnfo); if Keylnfo.NumValues<=0 then Exit; ValueNames := TStringList.Create; Reg.GetValueNames(ValueNames); for i := 0 to ValueNames.Count-1 do with ListViewl.Items.Add do begin Caption := ValueNames[i]; DataType := Reg.GetDataType(ValueNames[i]); Case DataType of rdString: s := Reg.ReadString(ValueNames[i]); rdlnteger: s:= '0x'+IntToHex(Reg.Readlnteger(ValueNames[i]),8); rdBinary: s:='Binary'; else s:= '???'; end; Subltems.Add(s); Imagelndex :=1; end; ValueNames.Free; end; procedure TForml.ShowSubKeys(ParentNode: TTreeNode;depth: Integer); var ParentKey: string; KeyNames : TStringList; KeyInfo : TRegKeylnfo; CurNode : TTreeNode; i : Integer; begin Cursor := crHourglass; TreeViewl.Items.BeginUpdate; ParentKey := GetFullNodeName(ParentNode); if ParentKeyO1' then Reg.OpenKeyReadOnly(ParentKey) else Reg.OpenKeyReadOnly('\') ; Reg.GetKeylnfo(Keylnfo) ; if KeyInfo.NumSubKeys<=0 then Exit; KeyNames := TStringList.Create; Reg.GetKeyNames(KeyNames); While ParentNode.GetFirstChildonil do ParentNode.GetFirstChild.Delete; if (KeyNames.Count>0) then for i:=0 to KeyNames.Count-1 do begin Reg.OpenKeyReadOnly(ParentKey+'\'-t-KeyNames[ i ]) ; Reg.GetKeylnfo(Keylnfo); CurNode := TreeViewl.Items.AddChild(ParentNode,KeyNames[i]; if KeyInfo.NumSubKeys>0 then begin TreeViewl.Items.AddChild(CurNode, ''); end; end; KeyNames.Free; TreeViewl.Items.EndUpdate; Cursor := crDefault; end; procedure TForml.TreeViewlExpanded(Sender: TObject; Node: TTreeNode); begin ShowSubKeys(Node,1); end; procedure TForml.TreeViewlGetlmagelndex(Sender: TObject; Node: TTreeNode); begin with Node do begin if Expanded then Imagelndex := 2 else Imagelndex := 3; end; end; end. Для работы с системным реестром используется объект VCL TRegistry, удачно инкапсулирующий все предназначенные для этого функции Windows API. В обработчике события OnCreate главной формы создается объект Reg, а также к списку Listview1 добавляются два заголовка (свойство Columns). Пояснений требует принцип построения дерева ключей. Во-первых, это приложение отображает только один из системных ключей (а именно HKEY_LOCAL_MACHINE); при желании его можно заменить или добавить остальные. Во-вторых, попытка построить все "развесистое" дерево ключей сразу займет слишком много времени и наверняка не понравится пользователям. Вспомним, ведь утилита Registry Editor работает довольно быстро. Значит, придется строить дерево динамически — создавать и показывать дочерние узлы в момент развертывания родительского узла. Для этого используется событиеOnExpand компонента TreeView1. Остановимся на секунду. А какие узлы помечать кнопкой разворачивания (с пометкой "+"), ведь у родительского узла еще нет потомков? Выход из положения такой — в момент построения ключа проверить, есть ли у него дочерние. Если да, то к нему добавляется один (фиктивный) пустой ключ. Его единственная роль — дать системе поставить "+" против родительского узла. Когда же пользователь щелкнул на кнопке, отмеченной знаком "+", и родительский узел разворачивается, фиктивный дочерний узел удаляется и вместо него создаются узлы настоящие, полученные путем сканирования реестра (см. метод ShowSubKeys). Снабдим узлы картинками. Для этого в компонент imageList1 поместим картинки, соответствующие открытой и закрытой папкам. Напомним, что для отрисовки и смены картинок есть специальные события — OnGetlmageIndex И OnGetSelectedIndex. В данном примере у двух ЭТИХ событий один обработчик: развернутому узлу он сопоставляет картинку раскрытой папки, а свернутому — закрытой. В заключение нужно сказать об очень важной особенности компонента TListview. Когда он отображает большой объем информации, обработка данных может затянуться очень и очень надолго и занять слишком много памяти. Выход — перевести список в так называемый виртуальный режим. Он применяется для тех случаев, когда элементов в списке слишком много и хранить их там невозможно из соображений экономии времени или памяти. Выход из положения прост: 1. Переводим компонент в виртуальный режим установкой свойства OwnerData в значение True. 2. Сообщаем списку сколько в нем должно быть элементов установкой нужного значения items.Count. 3. Чтобы предоставить нужные данные, программист должен предусмотреть обработку событий OnData, OnDataFind, OnDataHint и OnDataStateChange. Как минимум нужно описать обработчик события OnData. TLVOwnerDataEvent = procedure(Sender: TCbject; Item: TListltem) of object; Вам передается объект TListitem, и внутри обработчика события OnData необходимо динамически "оформить" его — полностью, от заголовка до картинок. Возникает это событие перед каждой перерисовкой списка. Так что, если сбор данных для вашего списка занимает более или менее продолжительное время, лучше не связывать его с событием OnData — перерисовка сильно затянется. К тому же в виртуальном режиме сортировать список невозможно. Borland прилагает к Delphi 7 прекрасный пример к вышесказанному — Virtual Listview. К нему и отсылаем заинтересованного читателя.
|