![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Помогите, пожалуйста, только начал разбираться с наследниками... Где-то нашёл пример наследника StringGrid, изменил его под свои нужды - автоподбор высоты строк и автоизменение общей высоты грида, внесение данных из массива...
Теперь понадобилось создать наследник TreeView... Где-то нашёл скудный пример, но и этим всё ограничилось.. Три часа поиска не дали необходимых результатов. Нужно перекрыть событие отрисовки OnCustomDrawItem, только как его объявить - не понятно.. Объявил, но на эту функцию не переходит при отрисовке. Свойства OwnerDraw не обнаружил... Второе что необходимо - перекрыть OnCollapsed и OnExpanded, чтобы можно было автоматически изменить размер TreeView.. Вот что имеется: Код:
unit TreeViewValueEditor;
interface
uses
SysUtils,
Classes,
Controls,
ComCtrls,
Graphics,
Udatamodule,
Dialogs,
Messages,
Windows,
CommCtrl;
type
TTreeViewValueEditor = class(TTreeView)
private
FHeader: THeaderControl;
protected
public
constructor Create(AOwner: TComponent); override;
function CustomDrawItem(Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage; var PaintImages: Boolean): Boolean; override;
// procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override; public
published
property Header: THeaderControl read FHeader write FHeader;
property OnResize;
end;
type
TVVE_TArrOfStr = array of string ;
TVVE_TArrOfArrOfStr = array of TVVE_TArrOfStr;
//var
// DifferenceArray: array of array of BOOL;
procedure Register;
procedure TVVE_FillTreeViewValueEditor(TVVE: TTreeViewValueEditor; CellsData: TVVE_TArrOfArrOfStr);
procedure TVVE_RemoveUnusedNodes(TVVE: TTreeViewValueEditor; UsedNodesIds: TVVE_TArrOfStr);
//procedure SizeTreeViewValueEditor(TVVE: TTreeViewValueEditor);
implementation
procedure Register;
begin
RegisterComponents('sorockinalex', [TTreeViewValueEditor]);
end;
function FindNode(TVVE: TTreeViewValueEditor; n:integer):TTreeNode;
var
i:Integer;
begin
Result:=nil;
i:=0;
while i<TVVE.Items.Count do
begin
if Integer(TVVE.Items[i].Data)=n then
begin
Result:=TVVE.Items[i];
Exit;
end;
Inc(i);
end;
end;
function FindRootNode(TVVE: TTreeViewValueEditor; NodeId:integer):TTreeNode;
begin
Result:=FindNode(TVVE, NodeId);
if Result<>nil then
begin
while Result.Parent.Data<>Pointer(StrToInt('')) do
begin
Result:=Result.Parent;
end;
end;
end;
function GetAllParentNodesIds(TVVE: TTreeViewValueEditor):TVVE_TArrOfStr;
var
i,l:Integer;
begin
i:=0;
while i<TVVE.Items.Count do
begin
if TVVE.Items[i].Parent=Nil then
begin
l:=Length(Result);
SetLength(Result, l+1);
Result[l]:=IntToStr(Integer(TVVE.Items[i].Data));
Exit;
end;
Inc(i);
end;
end;
function TreeView_GetItemHeight(hwnd: THandle): Integer;
begin
Result := SendMessage(hwnd, TVM_GETITEMHEIGHT, 0, 0);
end;
procedure TVVE_FillTreeViewValueEditor(TVVE: TTreeViewValueEditor; CellsData: TVVE_TArrOfArrOfStr);
var
i,j,l: integer;
node: TTreeNode;
UsedNodesIds, DontRemoveNodesIds, RemoveNodesIds: array of integer;
RemoveNode:Boolean;
begin
debugtreeprefix:=debugtreeprefix+#9;
WriteDebugTxt('TVVE_FillTreeViewValueEditor: ÍÀ×ÀËÎ');
TVVE.Items.Clear;
//ñíà÷àëà ñîçäà¸ì âñ¸ â êîðíå, òàê êàê ïàðàìåòðû ïðè ñîçäàíèè ìîãóò èäòè âïåðåìåæêó
i:=0;
while i<Length(CellsData) do
begin
TVVE.Items.AddChildObject(nil, CellsData[i,1],Pointer(StrToInt(CellsData[i,0])) );
Inc(i);
end;
//òåïåðü ïåðåìåùàåì ïîä÷èí¸ííûå
i:=0;
while i<Length(CellsData) do
begin
if CellsData[i,2]<>'' then FindNode(TVVE, StrToInt(CellsData[i,0])).MoveTo(FindNode(TVVE, StrToInt(CellsData[i,2])), naAddChild);
Inc(i);
end;
//ðàñêðûâàåì âñ¸ äåðåâî
TVVE.FullExpand;
TVVE.Height:=TVVE.Items.Count* TreeView_GetItemHeight(TVVE.Items[0].Handle)+4;
WriteDebugTxt('TVVE_FillTreeViewValueEditor: ÊÎÍÅÖ');
Delete(debugtreeprefix, 1, 1);
end;
procedure TVVE_RemoveUnusedNodes(TVVE: TTreeViewValueEditor; UsedNodesIds: TVVE_TArrOfStr);
var
UsedRootNodesIds:TVVE_TArrOfStr;
i,l:Integer;
node:TTreeNode;
begin
i:=0;
while i<Length(UsedNodesIds) do
begin
node:=FindRootNode(TVVE, StrToInt(UsedNodesIds[i]));
if node<>nil then
begin
l:=Length(UsedRootNodesIds);
SetLength(UsedRootNodesIds, l+1);
UsedRootNodesIds[l]:=IntToStr(Integer(node.Data));
end;
Inc(i);
end;
end;
{ TTreeViewValueEditor }
constructor TTreeViewValueEditor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FHeader := THeaderControl.Create(AOwner);
FHeader.Name := 'TreeViewValueEditorHeader';
FHeader.Parent := Self;
FHeader.Brush.Color := clBtnFace;
end;
function TTreeViewValueEditor.CustomDrawItem(Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage; var PaintImages: Boolean): Boolean;
begin
ShowMessage('draw');
end;
end.Помогите примером, пожалуйста! Как объявить OnCustomDraw, OnExpanded, OnCollapsed. Большое заранее спасибо! Что ж, никто не подскажет??? ( Последний раз редактировалось M.A.D.M.A.N., 14.10.2013 в 11:00. |
|
#2
|
|||
|
|||
|
Цитата:
А зачем в этом случае нужен наследник. Вроде как это стандарные обработчики событий. Вот примеры: Код:
procedure TForm1.TreeView1Collapsed(Sender: TObject; Node: TTreeNode); begin ShowMessage(Node.Text + ' collapsed'); end; procedure TForm1.TreeView1Expanded(Sender: TObject; Node: TTreeNode); begin ShowMessage(Node.Text + ' expanded'); end; procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean); begin TreeView1.Canvas.Font.Color := clRed; DefaultDraw := True; end; Ничего, кроме создания item'ов не делал. Свою отрисовку лень было писать, просто поменял цвет букв и сказал, что надо отрисовать стандартным способом. Но можно и свое все написать, тогда надо в DefaultDraw вернуть False. |
|
#3
|
|||
|
|||
|
Потому, что мастерю TreeGrid, чтобы отображать древовидно таблицу параметров с подчинёнными параметрами... Вопрос не в том, зачем... Данный класс- наследник будет использоваться в разных модулях и чтобы не заморачиваться одним и тем жекодом перерисовки, подстройки размера, нужно запихнуть это в него... Так кто-нибудь подскажет как оформить эти процедуры внутри наследника?
|
|
#4
|
||||
|
||||
|
Объявить их в наследнике как override, в них вызвать inherited, а затем уже далее написать свой код.
|
|
#5
|
|||
|
|||
|
Спасибо, но мне это не поможет, мне бы пример, буду очень благодарен! Пример описания самих процедур
И ещё, как прикрутить к наследнику TreeView StringGrid, или таблицу лучше самому рисовать? Хочу сделать что-то типа делфовского ObjectInspector... Может есть бесплатный вариант? Пишу программу для работы, не хочется использовать платные модули, чтобы не было проблем... Нашёл компонент TTreeList2 - буду пробовать. Всё-таки решил использовать VirtualTreeView... Написал формочку, которую без рамки гружу на скроллбокс... Для универсализации (таких форм может несколько подгружаться как класс) нужно передавать в неё через параметр Property формы-класса указатели на Структуру массива (тип массива) и указатель на сам массив, а также количество столбцов, и StringList с названиями столбцов... Итак, вопросы, прошу помощи! 1. Код:
type
TRcrd = record
id,
parentid:Integer;
editable:boolean;
param,
value:string
end;
...
ArrRcrd:array of TRcrd ;Указатель на массив PArrRcrd: Код:
PArrRcrd = ^ArrRcrd Доступ к элементам массива ArrRcrd - ПРАВИЛЬНО?: Код:
PArrRcrd[i].id Ворос: Как, зная указатель на массив, получить указатель на его тип, то есть на структуру TRcrd??? 2. Как узнать количество элементов в структуре Record? Нужно для того, чтобы не передавать лишний параметр количества создаваемых столбцов ColumnCount 3. Немного не разобрался с получением параметров Property.. Обязательно ли использование Write? Параметры считаются полученными без использование процедуры, указанной после Write? В коде ниже возникает ошибка типов (Incompatible Types) Код:
type
TFVST = class(TForm)
VST: TVirtualStringTree;
.....
public
procedure SerProp;
property PArrRcrd:Pointer write SerProp;
property ColumnCount: integer write SerProp;
property ColumnNames:TStringList write SerProp;
end;Может есть другой, более удобный способ передачи параметров таких типов как указатели и StringList? Последний раз редактировалось M.A.D.M.A.N., 15.10.2013 в 18:25. |