[강좌] TreeView와 Outline (1)
먼저 강좌를 진행해 나가기 전에 TTreeView와 TOutline의 차이점을 설명하고
자 한다.
TOutline은 원래 Delphi 1.0에서부터 depth가 있는 형태의 자료를 표현하기
위해서 (File Manager, Explorer같은 형태의) 제공한 것으로것이다.
그에 비해 TTreeView는 기본적으로 win 95가 제공하는 common control
의 내용에 해당하는 것을 Delphi 2.0에서 VCL로 제공하는 것으로 이와 유사
한 것들이 많은데, PageTab 등과 같은 것들도 모두 win 95의 common
control의 내용을 VCL화 한것이다.
그러므로, 기본적인 mechanism은 비슷하지만 내부적인 동작은 꽤 다른데,
기본적으로 Outline은 index를 통해서 어떤 object를 표현하는데 비해
TreeView는 node라는 object로 Tree를 구현한다.
기본적으로 이번에 할 강좌는 Delphi 2.0의 Help file을 많이 참조하였
으며 본인이 삭제하고 첨가한 부분이 다소 있음을 미리 알려둔다.
처음에는 TOutline에 대한 설명과 Key property, method, event를 설명하고,
이것이 끝나는데로 TTreeView에 대한 설명의 글이 올라갈 예정이다.
[강좌] TreeView와 Outline (2)
TOutline Component
* TWinControl을 계승함 !
* TOutline Component는 계층적 트리구조로 데이타를 정렬해 보여주는
component이다. Outline의 각각의 item은 TOutline Node를 포함하고
있다.
* Outline의 item들은 Items property로 접근이 가능하며, 이러한 item
들은 1부터 item 전체숫자에 맞게 index되어 있다. 예를 들어 Items[1]은
가장 첫번째 item을 가리킨다. 또한, Items property는 TOutline의
default array proprerty이므로 각 item은 outline name으로 직접
접근할 수 있다.
즉, Outline1.Items[1]과 Outline1[1]은 같은 outline item을 가리킨다.
* Outline에 subitem을 추가하기 위해서 쓰는 method는 Add 또는
AddObject methods이다. 또한 현재의 item의 자리에 item을 추가하기
위해서는 Insert 또는 InsertObject methods를 쓰며, Child item을
추가하기 위해서 AddChild 또는 AddChildObject method를 쓴다.
item들을 제거할 때 쓰는 method는 Delete이다.
* item을 추가하거나, 제거하거나, 옮길 때 걸리는 시간을 절약하려면
BeginUpdate method를 써주는 것이 좋다. 이 경우 item들이
EndUpdate가 불릴 때까지 reindex되지 않는다. 즉, 여러개의 item을
추가하거나, 제거할 때는 먼저 BeginUpdate를 호출하고, 작업이 끝나면
EndUpdate를 호출하는 것이 좋다.
* 현재 선택된 item은 SelectedItem property에 의해 알 수 있다.
사용자가 outline에서 새로운 item을 선택하면 (mouse로 click하거나
화살표키를 눌러서) 새롭게 선택된 item을 SelectedItem property로
알아볼 수 있다.
* Outline item들은 그림으로 나타낼 수 있는데, OutlineStyle property
에서 어떤 종류의 그림을 보여줄 것인지를 결정한다. 또한, 각각의
상황에서 보여줄 그림을 설정할 수 있는데, 여기에 쓰이는
property가 PictureLeaf, PictureMinus, PicturePlus, PictureOpen,
PictureClosed이다. 이 property를 지정하지 않으면 default로 지정된
그림이 나타난다.
* 만약 default로 지정된 그림과 글을 바꾸고 싶으면 Style property를
otOwnerDraw로 선택한 후 OnDrawItem event handler에서 그림을
지정해 주면 된다.
Key Properties
* Items Property (runtime, readonly)
- 선언: property Items[Index: Longint]: TOutlineNode;
- 설명
: Index parameter의 값은 Index property와 일치하며 각 Item들의
배열의 위치를 나타내는 정보이다. 예를들어 outline이 Index property
1, 2, 3을 가지고 그 text property가 각각 'Orange', 'Apple',
'Banana'를 가리킨다면 Items[2]는 'Apple' item을 가리킨다.
* ItemCount Property (runtime, readonly)
- 선언: property ItemCount: Longint;
- 설명: outline에 속해 있는 item의 총수를 나타냄.
* ItemSeparator Property
- 선언: property ItemSeparator: string;
- 설명: TOutlineNode object의 FullPath property에 쓰이는 separator를
지정한다. Default로 ''가 지정되어 있다. 예를 들어 가장 상위의 item
을 'Animals' 라 하고 거기에 child item으로 Text value가
'Dogs'인 item을 추가한다면, 'Dogs' item의 FullPath property는
'AnimalsDogs'가 된다. 만약 ItemSeparator property에 '->'를
대입하면 FullPath property 'Animals->Dogs'가 된다.
* Lines property
- 선언: property Lines: TStrings;
- 설명: 각 item들의 Text property를 포함한 것이다. 각각의 Line에
TOutlineNode object의 Text property를 담고 있다. tabs과 space가
outline의 level로 convert된다. 즉, tab이나 space가 없는 Text는 level
1 item으로 표현되고, level 2 item은 tab하나 혹은 space 하나로 표현
한다. 이 property는 디자인시에 최초 outline을 표현할 때 유용하다.
예) 다음의 두 코드는 동일한 의미이다.
Edit1.text := Outline1.Lines.Strings[2];
Edit2.text := Outline1.Items[3];
( StringList는 0부터이고 Items는 1부터이다/)
* Options property
- 선언: property Options: TOutlineOptions;
- 설명: Outline에 item을 그리는 방법에 대해 나타낸다.
다음과 같은 set가 있다.
1) ooDrawTreeRoot
: 첫번째 item (Index value=1)이 outline tree의 root에 연결된다.
이 속성이 false이면 모든 첫번째 level의 item들이 outline의 가장
좌측에 정렬되며, tree에 연결되지 않는다.
2) ooDrawFocusRect
: 선택된 item의 주위에 focus rectangle을 그려준다.
3) ooStretchBitmaps
: standard bitmap들 (PictureLeaf, PictureOpen, PictureClosed,
PicturePlus, PictureMinus)을 item size에 맞게 stretch시켜준다.
* Row property (runtime)
- 선언: property Row: Longint;
- 설명: 어떤 item이 선택되었는지 run time에서 알아볼 수 있다.
* SelectedItem property (runtime)
- 선언: property SelectedItem: Longint;
- 설명: outline에서 현재 focus를 가지고 있는 item의 Index value를
나타낸다. 만약 아무것도 선택되지 않았으면 0.
예) 다음 코드는 selected item을 FullExpand 시킨다.
Outline1.Items[Outline1.SelectedItem].FullExpand;
* Style property
- 선언: property Style: TOutlineType;
- 설명: Default는osStandard로 OutlineStyle property에 결정된 데로
따르는 것이다. 이 값을 otOwnerDraw로 바꾸면 code로 각 item
의 Canvas에 그려서 item을 나타낼 수 있다. 이 때에는 각 item이
그려질 때 OnDrawItem event가 일어난다. 여기에 coding을 한다.
[강좌] TreeView와 Outline (3)
Key Methods
* Add method
- 선언: function Add(Index: LongInt; const Text: string): LongInt;
- 설명: Outline item (TOutlineNode object)을 outline에 추가하는
method이다. Index parameter의 값은 새롭게 추가할 자리의 item
을 가리키며, Text parameter는 그 item의 Text property value
가 된다. 이 함수는 추가된 item의 index를 return한다.
추가된 item은 outline의 Index parameter가 가리키는 item의 가장
마지막 sibling으로 위치하며, 동일한 parent를 가지게 된다.
Note: item을 빈 outline에 추가할 때는 Index parameter를 0으로 지정한다.
* Insert method
- 선언: function Insert(Index: LongInt; const Text: string): LongInt;
- 설명: 기본적으로 Add method와 거의 동일하다. 추가된 item은
outline의 Index parameter가 가리키는 item의 바로 앞쪽 sibling으로
위치한다.
* AddChild method
- 선언: function AddChild(Index: LongInt; const Text: string)
: LongInt;
- 설명: 새로운 item (TOutlineNode object)을 존재하는 item의 child로
추가하는 method. 기본적인 내용은 Add method와 거의 동일하다.
추가된 item은 Index parameter가 가리키는 item의 가장 마지막
child item으로 추가된다.
* AddObject method
- 선언: function AddObject(Index: LongInt; const Text: string;
const Data: Pointer): LongInt;
- 설명: 데이타를 포함한 outline item (TOutlineNode object)을 추가하는
method. Add method와 거의 동일하지만 Data parameter가
새로운 item의 Data property값을 나타낸다.
예) 다음의 코드는 TMyRec라는 record type과 PMyRec라는 pointer를
선언한다.
type
PMyRec = ^TMyRec;
TMyRec = record
FName: string;
LName: string;
end;
다음 코드는 Outline1에 새로운 노드를 추가한다. TMyRec record는
추가된 item과 연결되어 있고, FName 과 LName fields가 edit box
(Edit1, Edit2)에서 얻어진다. Index parameter는 Edit3 edit box에서
얻는다. Item은 Index가 유효할 때만 추가된다.
var
MyRecPtr: PMyRec;
OutlineIndex: LongInt;
begin
New(MyRecPtr);
MyRecPtr^.FName := Edit1.Text;
MyRecPtr^.LName := Edit2.Text;
OutlineIndex := StrToInt(Edit3.Text);
if (OutlineIndex <= Outline1.ItemCount) and (OutlineIndex >= 0)
then
Outline1.AddObject(OutlineIndex, 'New item', MyRecPtr);
end;
일단 추가된 item에서 TMyRec record의 정보를 얻는 방법은
다음과 같다. 이 코드에서는 Fname, Lname 값을 label에 표시해준다.
* BeginUpdate, EndUpdate method
- 선언: procedure BeginUpdate;, procedure EndUpdate;
- 설명: TOutline외에도 여러 items property를 가지는 Tcollection,
TListItems, TStringList, TStrings component에도 쓰이는
method로 item들을 update할 때 소요되는 reindex 시간을
줄여주어, 속도 증진에 도움이 된다.
예) 다음의 코드는 초기에 outline1에 item들을 추가하는 것으로
try...finally 구문을 쓰지 않는 경우보다 빠르게 동작한다.
Item 수가 적을 때에는 모르지만 item이 늘어나면 속도차이가 현격하다.
* SetUpdateState method
- 선언: procedure SetUpdateState(Value: Boolean);
- 설명: Outline component의 update state를 setting해주는 method.
item을 outline에 추가하거나 제거하면 default로 outline
component가 reindexe된다. 커다란 outline의 경우에는 이 작업에
시간이 많이 걸리게 된다. 그러므로, outline이 크거나 한꺼번에
많은 item을 추가하거나 삭제할 때는 이런 automatic reindexing
을 off시키는 것이 좋다. 그러나 이 경우 많은 item들의 index
value가 유효하지 않은 값을 가지므로 주의를 요한다.
일단 item의 추가, 삭제가 끝나면 reindexing을 다시 on으로 한다.
기본적으로 이 작업은 BeginUpdate, EndUpdate method와
동일하다. Value를 True로 하면 BeginUpdate, False로 하면
EndUpdate처럼 동작한다.
* FullCollapse method
- 선언: procedure FullCollapse;
- 설명: Outline에 있는 모든 item들을 collapse 시키는 method.
일단 item이 collapse되면, Expanded property가 False로 setting
되고, subitem들이 숨겨진다. 그리고 OutlineStyle property에
정해진 것에 따라 closed 또는 plus 그림이 나타나게 된다.
* FullExpand method
- 선언: procedure FullExpand;
- 설명: Outline에 있는 모든 item들을 full expand 시키는 method.
OutlineNode object의 method에도 있다. 이 경우에는 item의
subitem을 full expand 시킨다.
* GetDataItem method
- 선언: function GetDataItem(Value: Pointer): Longint;
- 설명: 이 함수는 Value parameter와 outline의 item들의 Data property
를 비교하여 일치하는 첫번째 item의 Index value를 돌려준다..
예) 다음의 코드는 Data property가 pointer 변수 P3와 일치하는 item의
text값을 label에 나타낸다.
* GetItem method
- 선언: function GetItem(X, Y: Integer): Longint;
- 설명: Pixel coordinates (X, Y)에 해당하는 item의 index를
돌려준다. 특정 screen location에 해당하는 item을 얻을 때
사용한다.
예) 다음의 코드는 screen 좌표 (34,100)에 해당하는 item을 select한다.
* OnExpand event
- 선언: EOutlineChange
= procedure (Sender: TObject; Index: LongInt) of object;
property OnExpand: EOutlineChange;
- 설명: Subitem들이 있는 collapsed outline item이 expand 될 때
일어나는 event. 사용자가 run time에 double-click하거나
Expanded property가 True로 setting되면 발생한다.
또한 TOutlineNode object의 FullExpand method에 의해서도
일어난다. Index parameter에는 선택된 item의 index가 넘어온다.
예) 다음 코드는 collapsed outline item이 expand될 때, 그 item의 text를
message dialog box에 보여준다.
procedure TForm1.Outline1Expand(Sender: TObject; Index: Longint);
var
TheStr: string;
begin
TheStr := Outline1.Items[Index].Text;
MessageDlg(TheStr+' has expanded.', mtInformation, [mbOK],0);
end;
* OnCollapse event
- 선언: EOutlineChange
= procedure (Sender: TObject; Index: LongInt) of object;
property OnCollapse: EOutlineChange;
- 설명: Subitem을 가진 expanded outline item이 collapse 될 때
일어난다. Expanded outline item이 사용자에 의해 double-click
되거나, FullCollapse method가 불려지거나, Expanded property
가 False로 setting 되면 발생한다. Index parameter에는 선택된
item의 index property가 넘어온다.
* OnDrawItem event
- 선언: TDrawItemEvent = procedure(ListBox: TListBox; Index: Integer;
Rect: TRect; State: TOwnerDrawState) of object;
property OnDrawItem: TDrawItemEvent;
- 설명: 사용자가 item을 선택하거나 scroll할 때 일어나는 event
이다. Style value가 osOwnerDraw이어야 한다. OnDrawItem
에서는 4개의 parameters를 넘겨준다. item을 담고 있는
control의 reference, item의 index, 그려질 범위인 rectangle,
item의 state (selected, focused 등)이다.
1) odSelected: The item is selected.
2) odDisabled: The entire list box is disabled.
3) odFocused: The item currently has focus.
[강좌] TreeView와 Outline (4)
TOutlineNode Object
* TOutlineNode object 는 TPersistent의 direct descendant이다.
* TOutline component의 item. Text와 Data를 포함한다. Text는
string, Data는 pointer를 가진다.
* 각각의 item은 0에서 16368개의 subitem들을 가질 수 있다.
각 item은 자기만의 Index를 가지며, 이러한 Index는 TOutline
component의 Items property의 index와 일치한다. Item의 child들은
순차적으로 index를 가지며, 첫번째 child item은 parent보다 하나
큰 값을 가진다. 예를 들어 parent item Index가 7일 경우, 그
첫번째 child의 Index는 8이고, 두번째 child는 9이다.
* Item을 새로운 location으로 옮기기 위해서 MoveTo method를
쓴다. Expanded property는 item이 현재 expanded되었는지를
나타내며, 일단 expanded되면 모든 child item이 outline에
나타난다. 이 property를 True로 setting하려면 Expand method를
쓰면 되고, False로 setting하려면 Collapse method를 쓰면 된다.
* Level property는outline에서의 item의 level 또는 column을
나타낸다. Top level의 item들의 Level 값은 0이며, 그들의
children은 1이다. Item의 level을 바꾸려면 ChangeLevelBy method
를 쓴다.
* HasItems property는 item이 children 또는 subitems을 가지는지를
나타낸다. GetFirstChild method는 item의 첫번째 child item의 Index
value를 돌려주며, 마찬가지로 GetLastChild, GetPrevChild, GetNextChild
method는 각각 마지막, 이전, 다음 child item의 index를 돌려준다.
* IsVisible property는 item이 outline에서 보이는지를 나타낸다.
만약 그 item의 모든 parent가 expand되어 있다면 visible이다.
* TopItem property는 item의 top-level parent의 index value이다.
또한, Parent property는 그 item의 바로 이전 parent outline
node를 나타낸다. FullPath property는item의 모든 parent들을
보여주며, 각각의 parent는 TOutline의 ItemSeparator string에 의해
분리되어 있다.
Key Properties
* Data property (runtime)
- 선언: property Data: Pointer;
- 설명: item과 연결된 data의 pointer를 나타낸다.
예) 다음 코드는 TBitmap인 bitmap을 create하고 이를 selected outline
item의 data로 등록한다.
var
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
Outline1.Items[Outline1.SelectedItem].Data := Bitmap;
end;
* Parent property
- 선언: property Parent: TOutlineNode;
- 설명: item의 parent item을 나타낸다. 그 값은 TOutlineNode의 형태이다.
* Text property
- 선언: property Text: string;
- 설명: Text값은 직접 집어넣을 수도 있고, TOutline component의
Lines property에서 집어넣을 수도 있다.
* Index property
- 선언: property Index: Longint;
- 설명: 첫번째 item의 index값은 1이다. 그리고, 각 item들은 순차적으로
index값을 가지게 된다. 만약 subitem들을 가지게 되면 parent
item의 index값은 첫번째 subitem의 index값보다 하나 작은 값이다.
Index property값은 TOutline component의 Items property array의
index값과 일치한다. item이 추가되거나 삭제되면 Index property
값들은 BeginUpdate method가 불려지지 않았다면 자동적으로 새로
계산된다.
* Level property (runtime, read-only)
- 선언: property Level: Word;
- 설명: Item이 TOutline component에서 얼마나 indentation 되어 있는지를
나타낸다. Level이 1이면top level이다.
예) 다음 코드는 Outline1에서 선택된 item이 subitem을 가진다면 Expand한다.
with Outline1[Outline1.SelectedItem] do
if HasItems then Expand;
* IsVisible property (runtime, read-only)
- 선언: property IsVisible: Boolean;
- 설명: Outline item이 TOutline component 내에서 보이는지
나타내는 property
예) 다음 코드는 선택된 outline item이 visible이 아니면 expand한다.
with Outline1.Items[Outline1.SelectedItem] do
if not IsVisible then FullExpand;
* TopItem property
- 선언: property TopItem: LongInt;
- 설명: outline item의 Level 1 parent의 index 값을 돌려준다.
Level 1의 item의 경우에는 TopItem 값은 그 index 값과
동일하다.
예) 다음 코드는 선택된 item의 top-level parent 를 expand한다.
with Outline1 do
if not Items[Items[SelectedItem].TopItem].Expanded then
Items[Items[SelectedItem].TopItem].Expanded := True;
* FullPath property (runtime, read-only)
- 선언: property FullPath: string;
- 설명: 선택된 item의 level 1, top item에서부터의 경로를 모두
나타낸다. 분리된 string은 TOutline component의
ItemSeparator property에 의해 결정된다.
[강좌] TreeView와 Outline (5)
Key Methods
* Create method
- 선언: constructor Create(AOwner: TCustomOutline);
- 설명: 새로운 outline node를 생성한다. 이 object의 owner는
AOwner parameter에서 넘겨주는 Outline이다.
보통의 경우 outline에서 Add method를 써서 새로운 subitem을
추가하면 저절로 불려지는 method이다.
* Free method
- 선언: procedure Free;
- 설명: 다른 object, component에서 쓰이는 것과 동일
* GetPrevChild method
- 선언: function GetPrevChild(Value: Longint): Longint;
- 설명: Value parameter로 넘겨준 index에 해당하는 item과 같은
parent를 가지는 item들 중에서 바로 앞의 item의 index를
돌려주는 method이다. 만약 앞의 item이 없으면 -1을 값으로
돌려준다.
예) 다음 코드는 선택된 item이 previous sibling이 있는지 검사해서
그 결과를 label에 표시한다.
with Outline1 do
if (Items[SelectedItem].GetPrevChild > -1) then
Label1.Caption := 'Has a prior sibling'
else
Label1.Caption := 'Has no prior sibling';
* GetFirstChild method
- 선언: function GetFirstChild: Longint;
- 설명: outline item의 첫번째 subitem의 index 값을 돌려준다.
subitem이 없다면 -1을 돌려준다.
예) 다음 코드는 선택된 item이 child item을 가졌으면 expand하고,
첫번째 child item을 선택한다.
with Outline1 do
if Items[SelectedItem].HasItems then
begin
Items[SelectedItem].Expanded := True;
SelectedItem := Items[Items[SelectedItem].GetFirstChild];
end;
* MoveTo method
- 선언: procedure MoveTo
(Destination: Longint; AttachMode: TAttachMode);
- 설명: Destination parameter는 item을 어디로 옮길지 결정한다.
AttachMode parameter는 destination positoin에 어떤 식으로
옮길지를 결정한다. Attach mode의 예는 다음과 같다.
1) oaAdd : Add method와 같은 식으로 Attach
2) oaAddChild : AddChild method와 같은 식으로 Attach
3) oaInsert : Insert method와 같은 식으로 Attach
Note : Item이 옮겨지면 subitem들이 같이 옮겨진다.
또한, outline의 다른 item들이 모두 reindex된다
(BeginUpdate가 불려지지 않았다면).
* ChangeLevelBy method
- 선언: procedure ChangeLevelBy(Value: TChangeRange);
- 설명: Item의 level을 바꿔주는 method이다.
Value parameter 값이 -1 이면 한 level 위로 (root 방향) 올라가고,
값이 1이면 한 level 아래로 내려간다. 한 level 위로 올라가면
parent item의 다음 sibling이 되고, 한 level 아래로 내려가면
이전 sibling의 마지막 child가 된다. 그러므로 outline의 첫번째
item의 level은 바꿀 수 없다. 한번에 하나의 level씩만 조정할 수 있다.
예) 다음은 2개의 button의 OnClick event handler이다. UpBtn을 click하면
선택된 item이 첫번째 level이 아니면 위쪽 level로 올라가고,
DownBtn을 click하면 선택된 item의 앞에 sibling이 있으면 아래쪽
level로 내려간다.
procedure TForm1.UpBtnClick(Sender: TObject);
begin
with Outline1[Outline1.SelectedItem] do
if Level > 1 then ChangeLevelBy(-1);
end;
procedure TForm1.DownBtnClick(Sender: TObject);
begin
with Outline1[Outline1.SelectedItem] do
if Outline1[Parent.GetPrevChild(Index)] <> -1 then
ChangeLevelBy(1);
end;
[강좌] TreeView와 Outline (6)
TTreeView Component
* TWinControl의 indirect descendent이다.
* 계층적 구조를 보여주는 component이다. 각각의 item은 label, bitmapped
images, 그리고 subitem들로 구성되어 있다.
* Items property는 TTreeNodes object를 나타낸다. 이 object는
TTreeNode object들의 container object이며, 각각의 node들은 TTreeNode
object이다. Item들은 TTreeNodes method인 AddChildFirst, AddChild,
AddChildObjectFirst, AddChildObject, AddFirst, Add, AddObjectFirst,
AddObject, Insert. InsertObject를 이용하여 추가가 가능하다.
* ShowLines property는 True 일 때 child item과 그에 해당하는 parent
item을 연결하는 선을 그려준다. ShowButtons property는 각 parent
item의 좌측에 보이는 button을 보여줄 것인지를 결정한다. 이 button을
click하면 parent item을 double click하는 것과 같은 효과를 낸다.
ShowRoot property는 True로 할 경우 계층의 root가 표시된다.
* Indent property는 child item이 표시될 때 indentation 되는 정도를
결정한다. 또한, 각각의 item들을 영문순서로 sort하고 싶을 때는
SortType property를 stText로 설정하면 된다.
* Item label을 직접 편집할 수 있도록 하려면 ReadOnly property를
False로 설정한다.
Key Properties
* Items property
- 선언: property Items: TTreeNodes;
- 설명
: 각각의 item들의 집합으로, 각 node들은 TTreeNode object로
이루어져 있다. 이들 item에 접근하기 위해 items property를 쓴다.
예를 들어 tree view의 두번째 item에 접근하는 것은 다음과 같다.
MyTreeNode := TreeView1.Items[1]
Design-time에서 이 property를 설정할 때에는 TreeView Items
Editor가 나타난다. 여기에서 New Item과 New SubItem button을
선택하면 item들을 tree view에 추가할 수 있다.
Run-time에서는 TTreeNodes method인 AddChildFirst, AddChild,
AddChildObject, AddChildObjectFirst, AddFirst, Add, AddObjectFirst,
AddObject, Insert를 이용하여 item을 추가한다.
예) 다음 코드는 TreeView에 node를 추가하는 것을 보여준다.
procedure TForm1.Button1Click(Sender: TObject);
var
MyTreeNode1, MyTreeNode2: TTreeNode;
begin
with TreeView1.Items do
begin
{Root node를 추가한다}
Add(TreeView1.Selected, 'RootTreeNode1');
{MyTreeNode를 first node로 하고, 그 child node를 추가}
MyTreeNode1 := TreeView1.Items[0];
AddChild(MyTreeNode1,'ChildNode1');
{root node를 하나 더 추가}
Add(TreeView1.Selected, 'RootTreeNode2');
Selected property (run-time)
- 선언: property Selected: TTreeNode;
- 설명: Selected property는 선택된 item을 돌려준다. 이렇게 item이
선택되면 tree view의 OnChanging, OnChange event가 발생한다.
또한, 지정된 item이 collapsed parent item의 child item이면
그 parent item은 expand 된다. 이 경우에는 OnExpanded,
OnExpanding event가 발생한다.
예) 다음 코드는 선택된 item을 delete한다.
TreeView1.Selected.Delete;
TopItem property (run-time)
- 선언: property TopItem: TTreeNode;
- 설명: Tree view의 topmost item을 돌려준다. 변경되면tree view가 수직
으로 scroll되어 변경된 item이 topmost에 위치한다.
Images property (run-time)
- 선언: property Images: TImageList;
- 설명: 어떤 image list (TImageList)와 tree view를 연결할 것인지 결정
DropTarget property (run-time)
- 선언: property DropTarget: TTreeNode;
- 설명: Drag and drop 할 때 target이 되는 item
FullExpand method, FullCollapse method
- 선언: procedure FullExpand;
procedure FullCollapse;
- 설명: Tree view control에 있는 모든 item들을 expand시키거나 collapse.
이 때 ShowButtons property가 true이면 button의 '+', '-'도 같이
전환된다.
IsEditing method (run-time)
- 선언: function IsEditing: Boolean;
- 설명: Item중 편집되는 것이 있으면 true가 돌아온다.
GetNodeAt method
- 선언: function GetNodeAt(X, Y: Integer): TTreeNode;
- 설명: parameters X, Y의 pixel에 위치하는 item의 node를 돌려준다.
만약 node가 없으면 nil이 돌아온다.
GetHitTestInfoAt method
- 선언: function GetHitTestInfoAt(X, Y: Integer): THitTests;
- 설명: X, Y parameter에 해당하는 좌표의 정보를 THitTests 라는
set type으로 돌려준다. THitTests set의 값과 의미는 다음과 같다. :
htAbove: 위치가 tree view control의 client area 윗쪽인 경우
htBelow: 위치가 tree view control의 client area 아랫쪽인 경우
htNowhere: 위치가 tree view의 client area에 있으나 마지막 item 밑에
있는 경우
htOnItem: 위치가 item의 bitmap 또는 label에 있는 경우
htOnButton: 위치가 item의 button에 있는 경우
htOnIcon: 위치가 item의 bitmap에 있는 경우
htOnIndent: 위치가 item의 indentation에 있는 경우
htOnLabel: 위치가 item의 label (text)에 있는 경우
htOnRight: 위치가 item의 우측에 있는 경우
htOnStateIcon: 위치가 사용자가 정의한 state icon에 있는 경우
htToRight: 위치가 tree view control의 client area 우측에 있는 경우
htToLeft: 위치가 tree view control의 client area 좌측에 있는 경우
예) 다음 코드는 drag and drop을 해주는 코드로, drag and drop event가
발생하면 넘어 오는 X, Y 좌표의 node를 알아내고, 그 좌표의 정보를 HT
(THitTest set)에 담은 후에 HT가 htOnItem, htOnIcon이면 child로
add하고, htNoWhere 이면 새로운 item으로 add하며, htOnIndent이면 item
사이에 insert한다.
procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
AnItem: TTreeNode;
AttachMode: TNodeAttachMode;
HT: THitTests;
begin
if TreeView1.Selected = nil then Exit;
HT := TreeView1.GetHitTestInfoAt(X, Y);
AnItem := TreeView1.GetNodeAt(X, Y);
if (HT - [htOnItem, htOnIcon, htNowhere, htOnIndent] <> HT) then
begin
if (htOnItem in HT) or (htOnIcon in HT) then AttachMode
:= naAddChild
else if htNowhere in HT then AttachMode := naAdd
else if htOnIndent in HT then AttachMode := naInsert;
TreeView1.Selected.MoveTo(AnItem, AttachMode);
end;
end;
AlphaSort method
- 선언: function AlphaSort: Boolean;
- 설명: Tree view에서는 모든 root item을 label의 알파벳순으로
정렬해주는 method. Tree node object에서는 바로 아래 child
들을 정렬. 정렬이 성공적으로 끝나면 True를 돌려준다.
CustomSort method
- 선언: function CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
- 설명
: Callback 함수를 이용해 사용자 정의 sort를 행할 수 있는 method.
SortProc parameter는 application에서 정의한 callback 함수의 pointer이다.
Data parameter는 그 함수에 넘겨줄 수 있는 optional data 값이다.
Tree node의 CustomSort는 item의 모든 child item을 정렬하고,
tree view의 CustomSort는 tree view의 모든 item을 정렬한다.
Callback 함수는 비교할 2개의 item의 node와 하나의 32bit 값을 인자로 가진다.
기본적인 형태는 다음과 같다.
function CompareFunc(Node1, Node2: TTreeNode; ParamSort: Integer):
Integer; stdcall;
Callback 함수는 반드시 첫번째 item이 두번째보다 선행해야 될 경우 return값을
음수로 해야 하며, 같거나 동등한 위치이어야 한다면 0을, 첫번째 item이 두번째
뒤로 가야한다면 양수를 돌려주어야 한다.
만약 SortProc parameter의 값이 nil이면 default로 AlphaSort method
가 수행된다.
예) 다음 코드는 button click시 알파벳의 역순으로 정렬해주는 예제이다.
Callback 함수인 CustomSortProc는 Windows API function인 lstrcmp를
이용한다.
function CustomSortProc(Node1, Node2: TTreeNode; ParamSort: integer)
: integer; stdcall;
begin
Result := -lstrcmp(PChar(Item1.Text), PChar(Item2.Text));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TreeView1.CustomSort(@CustomSortProc, 0);
end;
Key Events
OnChange event
- 선언: TTVChangedEvent
= procedure(Sender: TObject; Node: TTreeNode) of object;
property OnChange: TTVChangedEvent;
- 설명: OnChange event는 selection이 바뀔 때마다 발생한다.
OnChanging event
- 선언: TTVChangingEvent = procedure(Sender: TObject; Node: TTreeNode;
var AllowChange: Boolean) of object;
property OnChanging: TTVChangingEvent;
- 설명: selection이 바뀌려고 할 때 발생한다. AllowChange parameter는 change
를 허용할 것인지 여부를 결정한다. 이것을 False로 설정하면 그 item을
사용자가 선택할 수 없다.
OnCollapsed, OnExpanded, OnDeletion event
- 선언: TTVExpandedEvent = procedure(Sender: TObject; Node: TTreeNode)
of object;
property OnCollapsed: TTVExpandedEvent;
property OnExpanded: TTVExpandedEvent;
property OnDeletion: TTVExpandedEvent;
- 설명: Tree가 collapse, expand, deletion 되었을 때 발생
OnCollapsing event
- 선언: TTVCollapsingEvent = procedure(Sender: TObject; Node: TTreeNode;
var AllowCollapse: Boolean) of object;
TTVExpandingEvent = procedure(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean) of object;
property OnCollapsing: TTVCollapsingEvent;
property OnExpanding: TTVExpandingEvent;
- 설명: Tree가 collapse, expand 되려고 할 때 발생. AllowCollapse를
False로 설정하면 collapse, expand 되지 않는다.
[강좌] TreeView와 Outline (7)
TTreeNodes Object
* TTreeView component의 Items property와 연관되어 있다.
* Item과 child item을 추가할 수 있는 method인 Add, AddFirst, AddChild,
AddChildFirst 등의 method가 있다. Add는 list의 가장 마지막에 item을
추가하고, AddFirst는 items list의 처음에 item을 추가한다. AddChild는
item을 items child list의 마지막에, AddChildFirst는 처음에 추가한다.
Data를 포함한 item들을 추가할 때에는 AddObject, AddObjectFirst,
AddChildObject, AddChildObjectFirst등의 method를 쓴다.
* Clear method는 tree view의 모든 item을 지우며, Delete method는 하나의
item을 제거한다. Insert method는 item을 tree view에 추가할 때 쓰이며,
InsertObject는 data를 포함했을 경우에 쓴다.
* BeginUpdate method는 EndUpdate method가 불리기 전에 tree view에 나타나지
않도록 한다.
* GetFirstNode method는 tree view의 첫번째 item을 돌려주며, GetNode는 주어진
ItemID에 해당하는 item을 돌려준다. Item[Index]는 주어진 index에 해당하는
item을 돌려준다. 이 경우 첫번째 item의 index는 0이고, 순차적인 index를 가
진다.
* Owner property는 TTreeNodes object를 소유한 tree view를 지정하며, Count
property에는 TTreeNodes object의 총 item 숫자가 기록되어 있다.
* Owner property (run-time, read-only)
- 선언: property Owner: TTreeNodes;
- 설명: item을 소유하는 tree nodes object를 기록
Key Methods
* Add method
- 선언: function Add(Node: TTreeNode; const S: string): TTreeNode;
- 설명: Tree view에 새로운 item을 추가한다. 추가된 item은 가장 마지막에
추가된다.
* AddChild, AddChildFirst method
- 선언: function AddChild(Node: TTreeNode; const S: string): TTreeNode;
function AddChildFirst(Node: TTreeNode; const S: string): TTreeNode;
- 설명: 기본적으로 Add method와 같지만 각각 child item으로 AddChild는
가장 뒤에, AddChildFirst는 가장 앞에 추가된다.
* AddObject, AddObjectFirst, InsertObject, AddChildObject,
AddChildObjectFirst
- 선언: function AddObject(Node: TTreeNode; const S: string; Ptr: Pointer)
: TTreeNode;
function InsertObject(Node: TTreeNode; const S: string; Ptr: Pointer)
: TTreeNode;
function AddChildObject(Node: TTreeNode; const S: string;
Ptr: Pointer): TTreeNode;
- 설명: 기본적으로 AddMethod이하의 다른 method 들과 같지만, Ptr parameter에서
data를 지정해줄 수 있다는 점이 다르다.
* Delete method
- 선언: function Delete(Node: TTreeNode);
- 설명: Node parameter에 지정된 item을 삭제한다.
예) 다음 코드는 mouse click 할 때 X, Y 좌표가 특정 item 위에 있으면 그
item을 delete한다. 코드는 X, Y 좌표의 THitTests 형인 HT 변수에 담고,
HT가 pointer가 item위에 있음을 나타내고, checkbox에서 delete가 선택되어
있고, sender가 TreeView이면 item을 delete한다.
procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
HT : THitTests;
begin
if (CheckBox1.Checked and (Sender is TTreeView)) then
begin
HT := TreeView1.GetHitTestInfoAt(X,Y);
if (htOnItem in HT) then
TreeView1.Items.Delete(TreeView1.GetNodeAt(X,Y));
end;
end;
* GetFirstNode method
- 선언: function GetFirstNode: TTreeNode;
- 설명: Tree view의 첫번째 item (TTreeNode object)을 돌려준다.
TTreeNode Object
* TTreeNode object는 TTreeView control의 individual item이다. 각각의 tree
node는 Text 와 Data 자료를 가진다. Text에는 문자열을 Data에는 특정
data structure의 pointer를 담고 있다. EditText method는 item을 edit mode로
전환한다.
* 각 item은 독특한 Index를 가지고 있다. Index는 TTreeView control의 Items
property의 index와 동일하다. Item의 child item들은 순차적으로 indexing되며
첫번째 child item의 index 값은 0이다. IndexOf method는 child item의
position을 돌려준다. 또한, AbsoluteIndex property에는 tree view의 첫번째
item으로부터의 index를 저장하고 있다.
* Item property는 tree view의 Index postion의 item을 저장하고 있으며,
Count property는 subitem의 수를 나타낸다. Item을 새로운 위치에 옮길
때에는 MoveTo method를 쓴다.
* Expanded property는 item이 현재 expand되어 있는지 나타낸다. 만약 True
이면 모든 child item이 tree view에 나타난다. IsVisible property는 item이
tree view에 보이는지를 나타낸다. 만약 item의 parent가 모두 expand 되었다면
item은 visible이다.
* Level property는 item의 level을 나타낸다. Top level의 item의 Level은 0이다.
HasChildren property는 item이 child item을 가졌는지 여부를 나타낸다.
* GetFirstChild method는 item의 첫번째 child를 돌려주며, GetLastChild,
GetPrevChild, GetNextChild는 각각 마지막, 이전, 다음 child item을
돌려준다. 비슷하게 GetNextSibling, GetPrevSibling은 같은 level의 이전과
다음 item을 돌려준다. GetNextVisible, GetPrevVisible method는 다음과
이전의 visible item들을 돌려준다.
* HasAsParent method는 넘겨준 item이 parent item이면 True를 돌려준다.
Parent property는 item의 parent node를 담고 있으며, TreeView property는
item을 가지고 있는 tree view를 나타낸다.
* Focused property는 item이 현재 focus를 가졌는지를 나타내며, Selected
property는 현재 node가 선택 되었는지를 나타낸다. DropTarget property는
drag and drop의 target이 되는 item을 나타낸다.
* SelectedIndex property는 item이 선택되었을 때 image list에 있는 icon의
index를 나타내며, OverlayIndex property는 tree view의 image list 중에
overlay mask (tree view의 다른 image위에 투명하게 덧씌워지는 image)로
쓰일 image의 index를 나타낸다. ImageIndex property는 item이 normal state
일 때 보여 줄 image를 나타내고, StateIndex property는 Tree View의
StateImages image list에서 어떤 image를 보여줄 것인지를 나타낸다.
Key Properties
* Item property (run-time)
- 선언: property Item[Index: Integer]: TTreeNode;
- 설명: child item (TTreeNode object)으로 접근한다. 첫번째 child item의
index position 은 0이다.
* Index property
- 선언: property Index: Longint;
- 설명: 첫번째 item의 Index 값은 1이다. Subitem이 있을 경우, 첫번째 subitem
의 index값보다 parent item의 index값이 1작다.
* Data property (run-time)
- 선언: property Data: Pointer;
- 설명: TTreeView control의 tree node의 Data를 pointer 형으로 가지고 있다.
* Count property (run-time, read-only)
- 선언: property Count: Integer;
- 설명: child item의 수를 나타낸다.
* Focused property (run-time)
- 선언: property Focused: Boolean;
- 설명: 현재 item이 focus를 가졌는지(standard focus rectangle에 들었는지)를
나타낸다.
* DropTarget property (run-time)
- 선언: property DropTarget: Boolean;
- 설명: item이 drag and drop의 target이 되었는지 여부를 나타낸다.
* ImageIndex property, SelectedIndex property (run-time)
- 선언: property ImageIndex: Integer;
property SelectedIndex: Integer;
- 설명: ImageIndex는 선택되지 않은 상태에서의 item의 image의 index이고,
SelectedIndex는 선택되었을 때의 image index이다. 연결된 imagelist
의 index값을 나타낸다.
* StateIndex property (run-time)
- 선언: property StateIndex: Integer;
- 설명: StateImages에 지정된 Image list의 image index값을 나타낸다.
값이 -1이면 state image가 그려지지 않는다.
* IndexOf method
- 선언: function IndexOf(Value: TTreeNode): Integer;
- 설명: item의 바로 아래 child item (Value parameter)의 position을 알려준
다. 만약 Value 값이 child item이 아니라면, -1을 돌려준다. 첫번째
child item이 Value로 넘어갔다면 0이 돌아올 것이며, 두번째 child item
이 Value로 넘어갔다면 1이 넘어온다.
* MoveTo method
- 선언: procedure MoveTo(Destination: TTreeNode; Mode: TNodeAttachMode);
- 설명: Tree node를 다른 위치로 옮길 때 쓰는 method이다. Destination
parameter는 옮겨갈 node를 지정하며, Mode parameter는
TNodeAttachMode의 형으로 어떤 식으로 옮길 것인지 지정한다.
Mode parameter의 값은 다음과 같다.
1) naAdd: list의 가장 마지막에 item으로 이동
2) naAddFirst: list의 가장 처음에 item으로 이동
3) naAddChild: child list의 가장 마지막 child item으로 이동
4) naAddChildFirst: child list의 가장 처음 child item으로 이동
5) naInsert:: destination node의 다음으로 insert하여 이동
* EditText method, CancelEdit method
- 선언: function EditText: Boolean;
procedure CancelEdit;
- 설명: item의 text를 바로 편집할 수 있게 하거나, 편집할 수 없게 하는
method
* MakeVisible method
- 선언: procedure MakeVisible;
- 설명: item을 tree view에 보이게 한다. 만약 parent item이 collapse되어
있을 때 이 procedure를 쓰면 parent가 expand된다.
* GetPrev method, GetNext method, GetPrevVisible method,
GetNextVisible method, GetPrevSibling method, GetNextSibling method
- 선언: function GetPrev: TTreeNode;
function GetNext: TTreeNode;
function GetPrevVisible: TTreeNode;
function GetNextVisible: TTreeNode;
function GetPrevSibling: TTreeNode;
function GetNextSibling: TTreeNode;
- 설명: 각각 tree view의 이전 item, 다음 item, 이전의 visible item,
다음 visible item, 같은 parent를 가지는 이전 item, 다음 item을
돌려준다.
* GetFirstChild method, GetLastChild method
- 선언: function GetFirstChild: TTreeNode;
function GetLastChild: TTreeNode;
- 설명: 각각 item의 첫번째와 마지막 child item을 돌려준다.
만약 child item이 없으면 nil을 돌려준다.
* GetPrevChild method, GetNextChild method
- 선언: function GetPrevChild(Value: TTreeNode): TTreeNode;
function GetNextChild(Value: TTreeNode): TTreeNode;
- 설명: Value parameter의 이전 child, 다음 child를 돌려준다. 만약 child가
없거나, 이전, 다음 값이 없으면 nil을 돌려준다.
델마당 강좌란에 퍼옵니다. 차근차근 공부하시면 될꺼 같습니다.
그럼 즐프하세요..
[강좌] TreeView와 Outline (1)
먼저 강좌를 진행해 나가기 전에 TTreeView와 TOutline의 차이점을 설명하고
자 한다.
TOutline은 원래 Delphi 1.0에서부터 depth가 있는 형태의 자료를 표현하기
위해서 (File Manager, Explorer같은 형태의) 제공한 것으로것이다.
그에 비해 TTreeView는 기본적으로 win 95가 제공하는 common control
의 내용에 해당하는 것을 Delphi 2.0에서 VCL로 제공하는 것으로 이와 유사
한 것들이 많은데, PageTab 등과 같은 것들도 모두 win 95의 common
control의 내용을 VCL화 한것이다.
그러므로, 기본적인 mechanism은 비슷하지만 내부적인 동작은 꽤 다른데,
기본적으로 Outline은 index를 통해서 어떤 object를 표현하는데 비해
TreeView는 node라는 object로 Tree를 구현한다.
기본적으로 이번에 할 강좌는 Delphi 2.0의 Help file을 많이 참조하였
으며 본인이 삭제하고 첨가한 부분이 다소 있음을 미리 알려둔다.
처음에는 TOutline에 대한 설명과 Key property, method, event를 설명하고,
이것이 끝나는데로 TTreeView에 대한 설명의 글이 올라갈 예정이다.
[강좌] TreeView와 Outline (2)
TOutline Component
* TWinControl을 계승함 !
* TOutline Component는 계층적 트리구조로 데이타를 정렬해 보여주는
component이다. Outline의 각각의 item은 TOutline Node를 포함하고
있다.
* Outline의 item들은 Items property로 접근이 가능하며, 이러한 item
들은 1부터 item 전체숫자에 맞게 index되어 있다. 예를 들어 Items[1]은
가장 첫번째 item을 가리킨다. 또한, Items property는 TOutline의
default array proprerty이므로 각 item은 outline name으로 직접
접근할 수 있다.
즉, Outline1.Items[1]과 Outline1[1]은 같은 outline item을 가리킨다.
* Outline에 subitem을 추가하기 위해서 쓰는 method는 Add 또는
AddObject methods이다. 또한 현재의 item의 자리에 item을 추가하기
위해서는 Insert 또는 InsertObject methods를 쓰며, Child item을
추가하기 위해서 AddChild 또는 AddChildObject method를 쓴다.
item들을 제거할 때 쓰는 method는 Delete이다.
* item을 추가하거나, 제거하거나, 옮길 때 걸리는 시간을 절약하려면
BeginUpdate method를 써주는 것이 좋다. 이 경우 item들이
EndUpdate가 불릴 때까지 reindex되지 않는다. 즉, 여러개의 item을
추가하거나, 제거할 때는 먼저 BeginUpdate를 호출하고, 작업이 끝나면
EndUpdate를 호출하는 것이 좋다.
* 현재 선택된 item은 SelectedItem property에 의해 알 수 있다.
사용자가 outline에서 새로운 item을 선택하면 (mouse로 click하거나
화살표키를 눌러서) 새롭게 선택된 item을 SelectedItem property로
알아볼 수 있다.
* Outline item들은 그림으로 나타낼 수 있는데, OutlineStyle property
에서 어떤 종류의 그림을 보여줄 것인지를 결정한다. 또한, 각각의
상황에서 보여줄 그림을 설정할 수 있는데, 여기에 쓰이는
property가 PictureLeaf, PictureMinus, PicturePlus, PictureOpen,
PictureClosed이다. 이 property를 지정하지 않으면 default로 지정된
그림이 나타난다.
* 만약 default로 지정된 그림과 글을 바꾸고 싶으면 Style property를
otOwnerDraw로 선택한 후 OnDrawItem event handler에서 그림을
지정해 주면 된다.
Key Properties
* Items Property (runtime, readonly)
- 선언: property Items[Index: Longint]: TOutlineNode;
- 설명
: Index parameter의 값은 Index property와 일치하며 각 Item들의
배열의 위치를 나타내는 정보이다. 예를들어 outline이 Index property
1, 2, 3을 가지고 그 text property가 각각 'Orange', 'Apple',
'Banana'를 가리킨다면 Items[2]는 'Apple' item을 가리킨다.
* ItemCount Property (runtime, readonly)
- 선언: property ItemCount: Longint;
- 설명: outline에 속해 있는 item의 총수를 나타냄.
* ItemSeparator Property
- 선언: property ItemSeparator: string;
- 설명: TOutlineNode object의 FullPath property에 쓰이는 separator를
지정한다. Default로 ''가 지정되어 있다. 예를 들어 가장 상위의 item
을 'Animals' 라 하고 거기에 child item으로 Text value가
'Dogs'인 item을 추가한다면, 'Dogs' item의 FullPath property는
'AnimalsDogs'가 된다. 만약 ItemSeparator property에 '->'를
대입하면 FullPath property 'Animals->Dogs'가 된다.
* Lines property
- 선언: property Lines: TStrings;
- 설명: 각 item들의 Text property를 포함한 것이다. 각각의 Line에
TOutlineNode object의 Text property를 담고 있다. tabs과 space가
outline의 level로 convert된다. 즉, tab이나 space가 없는 Text는 level
1 item으로 표현되고, level 2 item은 tab하나 혹은 space 하나로 표현
한다. 이 property는 디자인시에 최초 outline을 표현할 때 유용하다.
예) 다음의 두 코드는 동일한 의미이다.
Edit1.text := Outline1.Lines.Strings[2];
Edit2.text := Outline1.Items[3];
( StringList는 0부터이고 Items는 1부터이다/)
* Options property
- 선언: property Options: TOutlineOptions;
- 설명: Outline에 item을 그리는 방법에 대해 나타낸다.
다음과 같은 set가 있다.
1) ooDrawTreeRoot
: 첫번째 item (Index value=1)이 outline tree의 root에 연결된다.
이 속성이 false이면 모든 첫번째 level의 item들이 outline의 가장
좌측에 정렬되며, tree에 연결되지 않는다.
2) ooDrawFocusRect
: 선택된 item의 주위에 focus rectangle을 그려준다.
3) ooStretchBitmaps
: standard bitmap들 (PictureLeaf, PictureOpen, PictureClosed,
PicturePlus, PictureMinus)을 item size에 맞게 stretch시켜준다.
* Row property (runtime)
- 선언: property Row: Longint;
- 설명: 어떤 item이 선택되었는지 run time에서 알아볼 수 있다.
* SelectedItem property (runtime)
- 선언: property SelectedItem: Longint;
- 설명: outline에서 현재 focus를 가지고 있는 item의 Index value를
나타낸다. 만약 아무것도 선택되지 않았으면 0.
예) 다음 코드는 selected item을 FullExpand 시킨다.
Outline1.Items[Outline1.SelectedItem].FullExpand;
* Style property
- 선언: property Style: TOutlineType;
- 설명: Default는osStandard로 OutlineStyle property에 결정된 데로
따르는 것이다. 이 값을 otOwnerDraw로 바꾸면 code로 각 item
의 Canvas에 그려서 item을 나타낼 수 있다. 이 때에는 각 item이
그려질 때 OnDrawItem event가 일어난다. 여기에 coding을 한다.
[강좌] TreeView와 Outline (3)
Key Methods
* Add method
- 선언: function Add(Index: LongInt; const Text: string): LongInt;
- 설명: Outline item (TOutlineNode object)을 outline에 추가하는
method이다. Index parameter의 값은 새롭게 추가할 자리의 item
을 가리키며, Text parameter는 그 item의 Text property value
가 된다. 이 함수는 추가된 item의 index를 return한다.
추가된 item은 outline의 Index parameter가 가리키는 item의 가장
마지막 sibling으로 위치하며, 동일한 parent를 가지게 된다.
Note: item을 빈 outline에 추가할 때는 Index parameter를 0으로 지정한다.
* Insert method
- 선언: function Insert(Index: LongInt; const Text: string): LongInt;
- 설명: 기본적으로 Add method와 거의 동일하다. 추가된 item은
outline의 Index parameter가 가리키는 item의 바로 앞쪽 sibling으로
위치한다.
* AddChild method
- 선언: function AddChild(Index: LongInt; const Text: string)
: LongInt;
- 설명: 새로운 item (TOutlineNode object)을 존재하는 item의 child로
추가하는 method. 기본적인 내용은 Add method와 거의 동일하다.
추가된 item은 Index parameter가 가리키는 item의 가장 마지막
child item으로 추가된다.
* AddObject method
- 선언: function AddObject(Index: LongInt; const Text: string;
const Data: Pointer): LongInt;
- 설명: 데이타를 포함한 outline item (TOutlineNode object)을 추가하는
method. Add method와 거의 동일하지만 Data parameter가
새로운 item의 Data property값을 나타낸다.
예) 다음의 코드는 TMyRec라는 record type과 PMyRec라는 pointer를
선언한다.
type
PMyRec = ^TMyRec;
TMyRec = record
FName: string;
LName: string;
end;
다음 코드는 Outline1에 새로운 노드를 추가한다. TMyRec record는
추가된 item과 연결되어 있고, FName 과 LName fields가 edit box
(Edit1, Edit2)에서 얻어진다. Index parameter는 Edit3 edit box에서
얻는다. Item은 Index가 유효할 때만 추가된다.
var
MyRecPtr: PMyRec;
OutlineIndex: LongInt;
begin
New(MyRecPtr);
MyRecPtr^.FName := Edit1.Text;
MyRecPtr^.LName := Edit2.Text;
OutlineIndex := StrToInt(Edit3.Text);
if (OutlineIndex <= Outline1.ItemCount) and (OutlineIndex >= 0)
then
Outline1.AddObject(OutlineIndex, 'New item', MyRecPtr);
end;
일단 추가된 item에서 TMyRec record의 정보를 얻는 방법은
다음과 같다. 이 코드에서는 Fname, Lname 값을 label에 표시해준다.
Label4.Caption
:= PMyRec(Outline1.Items[Outline1.SelectedItem].Data)^.FName;
Label5.Caption
:= PMyRec(Outline1.Items[Outline1.SelectedItem].Data)^.LName;
* AddChildObject method
- 선언: function AddChildObject(Index: LongInt; const Text: string;
const Data: Pointer): LongInt;
- 설명: 기본적으로 AddObject와 사용법이 동일하며 Index parameter가
가리키는 item의 마지막 child item을 추가하고, 추가된 item의
index값을 돌려준다.
* InsertObject method
- 선언: function InsertObject(Index: Longint; const Text: string;
const Data: Pointer): Longint;
- 설명: 기본적으로 AddObject method와 비슷하지만, 추가되는 item이
index parameter가 가리키는 item의 앞에 추가된다.
예) 다음 코드는 새로운 item의 Data가 Bitmap1이라는 Bitmap을 가리킨다.
var
Bitmap1: TBitmap;
begin
Bitmap1 := TBitmap.Create;
Outline1.InsertObject(1, 'New item', Bitmap1);
end;
* Clear method
- 선언: procedure Clear;
- 설명: 모든 item을 삭제한다.
* BeginUpdate, EndUpdate method
- 선언: procedure BeginUpdate;, procedure EndUpdate;
- 설명: TOutline외에도 여러 items property를 가지는 Tcollection,
TListItems, TStringList, TStrings component에도 쓰이는
method로 item들을 update할 때 소요되는 reindex 시간을
줄여주어, 속도 증진에 도움이 된다.
예) 다음의 코드는 초기에 outline1에 item들을 추가하는 것으로
try...finally 구문을 쓰지 않는 경우보다 빠르게 동작한다.
Item 수가 적을 때에는 모르지만 item이 늘어나면 속도차이가 현격하다.
Outline1.Items.BeginUpdate;
try
Outline1.Items.Clear;
Outline1.Items.Add(...);
...
Outline1.Items.Add(...);
finally
Outline1.Items.EndUpdate;
end;
* SetUpdateState method
- 선언: procedure SetUpdateState(Value: Boolean);
- 설명: Outline component의 update state를 setting해주는 method.
item을 outline에 추가하거나 제거하면 default로 outline
component가 reindexe된다. 커다란 outline의 경우에는 이 작업에
시간이 많이 걸리게 된다. 그러므로, outline이 크거나 한꺼번에
많은 item을 추가하거나 삭제할 때는 이런 automatic reindexing
을 off시키는 것이 좋다. 그러나 이 경우 많은 item들의 index
value가 유효하지 않은 값을 가지므로 주의를 요한다.
일단 item의 추가, 삭제가 끝나면 reindexing을 다시 on으로 한다.
기본적으로 이 작업은 BeginUpdate, EndUpdate method와
동일하다. Value를 True로 하면 BeginUpdate, False로 하면
EndUpdate처럼 동작한다.
* FullCollapse method
- 선언: procedure FullCollapse;
- 설명: Outline에 있는 모든 item들을 collapse 시키는 method.
일단 item이 collapse되면, Expanded property가 False로 setting
되고, subitem들이 숨겨진다. 그리고 OutlineStyle property에
정해진 것에 따라 closed 또는 plus 그림이 나타나게 된다.
* FullExpand method
- 선언: procedure FullExpand;
- 설명: Outline에 있는 모든 item들을 full expand 시키는 method.
OutlineNode object의 method에도 있다. 이 경우에는 item의
subitem을 full expand 시킨다.
* GetDataItem method
- 선언: function GetDataItem(Value: Pointer): Longint;
- 설명: 이 함수는 Value parameter와 outline의 item들의 Data property
를 비교하여 일치하는 첫번째 item의 Index value를 돌려준다..
예) 다음의 코드는 Data property가 pointer 변수 P3와 일치하는 item의
text값을 label에 나타낸다.
Label1.Caption := Outline1.Items[GetDataItem(p3)].Text;
* GetItem method
- 선언: function GetItem(X, Y: Integer): Longint;
- 설명: Pixel coordinates (X, Y)에 해당하는 item의 index를
돌려준다. 특정 screen location에 해당하는 item을 얻을 때
사용한다.
예) 다음의 코드는 screen 좌표 (34,100)에 해당하는 item을 select한다.
Outline1.SelectedItem := Outline1.GetItem(34,100);
* GetTextItem method
- 선언: function GetTextItem(Value: string): Longint;
- 설명: Value parameter의 내용이 담긴 첫번째 item의 index를 돌려주는
method.
예) 다음 코드는 Text 내용이 'Perry'인 item의 index를 돌려준다.
PerryIndex := Outline1.GetTextItem('Perry');
* LoadFromFile method, SaveToFile method
- 선언: procedure LoadFromFile(const FileName: string);
procedure SaveToFile(const FileName: string);
Key Events
* OnExpand event
- 선언: EOutlineChange
= procedure (Sender: TObject; Index: LongInt) of object;
property OnExpand: EOutlineChange;
- 설명: Subitem들이 있는 collapsed outline item이 expand 될 때
일어나는 event. 사용자가 run time에 double-click하거나
Expanded property가 True로 setting되면 발생한다.
또한 TOutlineNode object의 FullExpand method에 의해서도
일어난다. Index parameter에는 선택된 item의 index가 넘어온다.
예) 다음 코드는 collapsed outline item이 expand될 때, 그 item의 text를
message dialog box에 보여준다.
procedure TForm1.Outline1Expand(Sender: TObject; Index: Longint);
var
TheStr: string;
begin
TheStr := Outline1.Items[Index].Text;
MessageDlg(TheStr+' has expanded.', mtInformation, [mbOK],0);
end;
* OnCollapse event
- 선언: EOutlineChange
= procedure (Sender: TObject; Index: LongInt) of object;
property OnCollapse: EOutlineChange;
- 설명: Subitem을 가진 expanded outline item이 collapse 될 때
일어난다. Expanded outline item이 사용자에 의해 double-click
되거나, FullCollapse method가 불려지거나, Expanded property
가 False로 setting 되면 발생한다. Index parameter에는 선택된
item의 index property가 넘어온다.
* OnDrawItem event
- 선언: TDrawItemEvent = procedure(ListBox: TListBox; Index: Integer;
Rect: TRect; State: TOwnerDrawState) of object;
property OnDrawItem: TDrawItemEvent;
- 설명: 사용자가 item을 선택하거나 scroll할 때 일어나는 event
이다. Style value가 osOwnerDraw이어야 한다. OnDrawItem
에서는 4개의 parameters를 넘겨준다. item을 담고 있는
control의 reference, item의 index, 그려질 범위인 rectangle,
item의 state (selected, focused 등)이다.
1) odSelected: The item is selected.
2) odDisabled: The entire list box is disabled.
3) odFocused: The item currently has focus.
[강좌] TreeView와 Outline (4)
TOutlineNode Object
* TOutlineNode object 는 TPersistent의 direct descendant이다.
* TOutline component의 item. Text와 Data를 포함한다. Text는
string, Data는 pointer를 가진다.
* 각각의 item은 0에서 16368개의 subitem들을 가질 수 있다.
각 item은 자기만의 Index를 가지며, 이러한 Index는 TOutline
component의 Items property의 index와 일치한다. Item의 child들은
순차적으로 index를 가지며, 첫번째 child item은 parent보다 하나
큰 값을 가진다. 예를 들어 parent item Index가 7일 경우, 그
첫번째 child의 Index는 8이고, 두번째 child는 9이다.
* Item을 새로운 location으로 옮기기 위해서 MoveTo method를
쓴다. Expanded property는 item이 현재 expanded되었는지를
나타내며, 일단 expanded되면 모든 child item이 outline에
나타난다. 이 property를 True로 setting하려면 Expand method를
쓰면 되고, False로 setting하려면 Collapse method를 쓰면 된다.
* Level property는outline에서의 item의 level 또는 column을
나타낸다. Top level의 item들의 Level 값은 0이며, 그들의
children은 1이다. Item의 level을 바꾸려면 ChangeLevelBy method
를 쓴다.
* HasItems property는 item이 children 또는 subitems을 가지는지를
나타낸다. GetFirstChild method는 item의 첫번째 child item의 Index
value를 돌려주며, 마찬가지로 GetLastChild, GetPrevChild, GetNextChild
method는 각각 마지막, 이전, 다음 child item의 index를 돌려준다.
* IsVisible property는 item이 outline에서 보이는지를 나타낸다.
만약 그 item의 모든 parent가 expand되어 있다면 visible이다.
* TopItem property는 item의 top-level parent의 index value이다.
또한, Parent property는 그 item의 바로 이전 parent outline
node를 나타낸다. FullPath property는item의 모든 parent들을
보여주며, 각각의 parent는 TOutline의 ItemSeparator string에 의해
분리되어 있다.
Key Properties
* Data property (runtime)
- 선언: property Data: Pointer;
- 설명: item과 연결된 data의 pointer를 나타낸다.
예) 다음 코드는 TBitmap인 bitmap을 create하고 이를 selected outline
item의 data로 등록한다.
var
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
Outline1.Items[Outline1.SelectedItem].Data := Bitmap;
end;
* Parent property
- 선언: property Parent: TOutlineNode;
- 설명: item의 parent item을 나타낸다. 그 값은 TOutlineNode의 형태이다.
* Text property
- 선언: property Text: string;
- 설명: Text값은 직접 집어넣을 수도 있고, TOutline component의
Lines property에서 집어넣을 수도 있다.
* Index property
- 선언: property Index: Longint;
- 설명: 첫번째 item의 index값은 1이다. 그리고, 각 item들은 순차적으로
index값을 가지게 된다. 만약 subitem들을 가지게 되면 parent
item의 index값은 첫번째 subitem의 index값보다 하나 작은 값이다.
Index property값은 TOutline component의 Items property array의
index값과 일치한다. item이 추가되거나 삭제되면 Index property
값들은 BeginUpdate method가 불려지지 않았다면 자동적으로 새로
계산된다.
* Level property (runtime, read-only)
- 선언: property Level: Word;
- 설명: Item이 TOutline component에서 얼마나 indentation 되어 있는지를
나타낸다. Level이 1이면top level이다.
* Expand property (runtime)
- 선언: property Expanded: Boolean;
- 설명: Outline item이 expanded 되었는지, 아닌지를 나타낸다.
예) 다음 코드는 selected outline item의 Expanded property를 토글한다.
with Outline1 do
Items[SelectedItem].Expanded := not Items[SelectedItem].Expanded;
* HasItems property (runtime, read-only)
- 선언: property HasItems: Boolean;
- 설명: HasItems property는 outline item이 subitem들을 가지는지를
나타낸다.
예) 다음 코드는 Outline1에서 선택된 item이 subitem을 가진다면 Expand한다.
with Outline1[Outline1.SelectedItem] do
if HasItems then Expand;
* IsVisible property (runtime, read-only)
- 선언: property IsVisible: Boolean;
- 설명: Outline item이 TOutline component 내에서 보이는지
나타내는 property
예) 다음 코드는 선택된 outline item이 visible이 아니면 expand한다.
with Outline1.Items[Outline1.SelectedItem] do
if not IsVisible then FullExpand;
* TopItem property
- 선언: property TopItem: LongInt;
- 설명: outline item의 Level 1 parent의 index 값을 돌려준다.
Level 1의 item의 경우에는 TopItem 값은 그 index 값과
동일하다.
예) 다음 코드는 선택된 item의 top-level parent 를 expand한다.
with Outline1 do
if not Items[Items[SelectedItem].TopItem].Expanded then
Items[Items[SelectedItem].TopItem].Expanded := True;
* FullPath property (runtime, read-only)
- 선언: property FullPath: string;
- 설명: 선택된 item의 level 1, top item에서부터의 경로를 모두
나타낸다. 분리된 string은 TOutline component의
ItemSeparator property에 의해 결정된다.
[강좌] TreeView와 Outline (5)
Key Methods
* Create method
- 선언: constructor Create(AOwner: TCustomOutline);
- 설명: 새로운 outline node를 생성한다. 이 object의 owner는
AOwner parameter에서 넘겨주는 Outline이다.
보통의 경우 outline에서 Add method를 써서 새로운 subitem을
추가하면 저절로 불려지는 method이다.
* Free method
- 선언: procedure Free;
- 설명: 다른 object, component에서 쓰이는 것과 동일
* FullExpand method
- 선언: procedure FullExpand;
- 설명: Outline component의 method와 동일
* Collapse method
- 선언: procedure Collapse;
- 설명: Outline component의 method와 동일
* GetPrevChild method
- 선언: function GetPrevChild(Value: Longint): Longint;
- 설명: Value parameter로 넘겨준 index에 해당하는 item과 같은
parent를 가지는 item들 중에서 바로 앞의 item의 index를
돌려주는 method이다. 만약 앞의 item이 없으면 -1을 값으로
돌려준다.
예) 다음 코드는 선택된 item이 previous sibling이 있는지 검사해서
그 결과를 label에 표시한다.
with Outline1 do
if (Items[SelectedItem].GetPrevChild > -1) then
Label1.Caption := 'Has a prior sibling'
else
Label1.Caption := 'Has no prior sibling';
* GetFirstChild method
- 선언: function GetFirstChild: Longint;
- 설명: outline item의 첫번째 subitem의 index 값을 돌려준다.
subitem이 없다면 -1을 돌려준다.
예) 다음 코드는 선택된 item이 child item을 가졌으면 expand하고,
첫번째 child item을 선택한다.
with Outline1 do
if Items[SelectedItem].HasItems then
begin
Items[SelectedItem].Expanded := True;
SelectedItem := Items[Items[SelectedItem].GetFirstChild];
end;
* MoveTo method
- 선언: procedure MoveTo
(Destination: Longint; AttachMode: TAttachMode);
- 설명: Destination parameter는 item을 어디로 옮길지 결정한다.
AttachMode parameter는 destination positoin에 어떤 식으로
옮길지를 결정한다. Attach mode의 예는 다음과 같다.
1) oaAdd : Add method와 같은 식으로 Attach
2) oaAddChild : AddChild method와 같은 식으로 Attach
3) oaInsert : Insert method와 같은 식으로 Attach
Note : Item이 옮겨지면 subitem들이 같이 옮겨진다.
또한, outline의 다른 item들이 모두 reindex된다
(BeginUpdate가 불려지지 않았다면).
* ChangeLevelBy method
- 선언: procedure ChangeLevelBy(Value: TChangeRange);
- 설명: Item의 level을 바꿔주는 method이다.
Value parameter 값이 -1 이면 한 level 위로 (root 방향) 올라가고,
값이 1이면 한 level 아래로 내려간다. 한 level 위로 올라가면
parent item의 다음 sibling이 되고, 한 level 아래로 내려가면
이전 sibling의 마지막 child가 된다. 그러므로 outline의 첫번째
item의 level은 바꿀 수 없다. 한번에 하나의 level씩만 조정할 수 있다.
예) 다음은 2개의 button의 OnClick event handler이다. UpBtn을 click하면
선택된 item이 첫번째 level이 아니면 위쪽 level로 올라가고,
DownBtn을 click하면 선택된 item의 앞에 sibling이 있으면 아래쪽
level로 내려간다.
procedure TForm1.UpBtnClick(Sender: TObject);
begin
with Outline1[Outline1.SelectedItem] do
if Level > 1 then ChangeLevelBy(-1);
end;
procedure TForm1.DownBtnClick(Sender: TObject);
begin
with Outline1[Outline1.SelectedItem] do
if Outline1[Parent.GetPrevChild(Index)] <> -1 then
ChangeLevelBy(1);
end;
[강좌] TreeView와 Outline (6)
TTreeView Component
* TWinControl의 indirect descendent이다.
* 계층적 구조를 보여주는 component이다. 각각의 item은 label, bitmapped
images, 그리고 subitem들로 구성되어 있다.
* Items property는 TTreeNodes object를 나타낸다. 이 object는
TTreeNode object들의 container object이며, 각각의 node들은 TTreeNode
object이다. Item들은 TTreeNodes method인 AddChildFirst, AddChild,
AddChildObjectFirst, AddChildObject, AddFirst, Add, AddObjectFirst,
AddObject, Insert. InsertObject를 이용하여 추가가 가능하다.
* ShowLines property는 True 일 때 child item과 그에 해당하는 parent
item을 연결하는 선을 그려준다. ShowButtons property는 각 parent
item의 좌측에 보이는 button을 보여줄 것인지를 결정한다. 이 button을
click하면 parent item을 double click하는 것과 같은 효과를 낸다.
ShowRoot property는 True로 할 경우 계층의 root가 표시된다.
* Indent property는 child item이 표시될 때 indentation 되는 정도를
결정한다. 또한, 각각의 item들을 영문순서로 sort하고 싶을 때는
SortType property를 stText로 설정하면 된다.
* Item label을 직접 편집할 수 있도록 하려면 ReadOnly property를
False로 설정한다.
Key Properties
* Items property
- 선언: property Items: TTreeNodes;
- 설명
: 각각의 item들의 집합으로, 각 node들은 TTreeNode object로
이루어져 있다. 이들 item에 접근하기 위해 items property를 쓴다.
예를 들어 tree view의 두번째 item에 접근하는 것은 다음과 같다.
MyTreeNode := TreeView1.Items[1]
Design-time에서 이 property를 설정할 때에는 TreeView Items
Editor가 나타난다. 여기에서 New Item과 New SubItem button을
선택하면 item들을 tree view에 추가할 수 있다.
Run-time에서는 TTreeNodes method인 AddChildFirst, AddChild,
AddChildObject, AddChildObjectFirst, AddFirst, Add, AddObjectFirst,
AddObject, Insert를 이용하여 item을 추가한다.
예) 다음 코드는 TreeView에 node를 추가하는 것을 보여준다.
procedure TForm1.Button1Click(Sender: TObject);
var
MyTreeNode1, MyTreeNode2: TTreeNode;
begin
with TreeView1.Items do
begin
{Root node를 추가한다}
Add(TreeView1.Selected, 'RootTreeNode1');
{MyTreeNode를 first node로 하고, 그 child node를 추가}
MyTreeNode1 := TreeView1.Items[0];
AddChild(MyTreeNode1,'ChildNode1');
{root node를 하나 더 추가}
Add(TreeView1.Selected, 'RootTreeNode2');
{MyTreeNode를 세번째 node로 설정하고, 거기에 child node 추가}
MyTreeNode2:=TreeView1.items[2];
AddChild(MyTreeNode2,'ChildNode2');
end;
end;
Selected property (run-time)
- 선언: property Selected: TTreeNode;
- 설명: Selected property는 선택된 item을 돌려준다. 이렇게 item이
선택되면 tree view의 OnChanging, OnChange event가 발생한다.
또한, 지정된 item이 collapsed parent item의 child item이면
그 parent item은 expand 된다. 이 경우에는 OnExpanded,
OnExpanding event가 발생한다.
예) 다음 코드는 선택된 item을 delete한다.
TreeView1.Selected.Delete;
TopItem property (run-time)
- 선언: property TopItem: TTreeNode;
- 설명: Tree view의 topmost item을 돌려준다. 변경되면tree view가 수직
으로 scroll되어 변경된 item이 topmost에 위치한다.
Images property (run-time)
- 선언: property Images: TImageList;
- 설명: 어떤 image list (TImageList)와 tree view를 연결할 것인지 결정
DropTarget property (run-time)
- 선언: property DropTarget: TTreeNode;
- 설명: Drag and drop 할 때 target이 되는 item
Indent, ReadOnly, ShowButtons, ShowLines, ShowRoot, SortType property
: 도움말 참조
Key Methods
FullExpand method, FullCollapse method
- 선언: procedure FullExpand;
procedure FullCollapse;
- 설명: Tree view control에 있는 모든 item들을 expand시키거나 collapse.
이 때 ShowButtons property가 true이면 button의 '+', '-'도 같이
전환된다.
IsEditing method (run-time)
- 선언: function IsEditing: Boolean;
- 설명: Item중 편집되는 것이 있으면 true가 돌아온다.
GetNodeAt method
- 선언: function GetNodeAt(X, Y: Integer): TTreeNode;
- 설명: parameters X, Y의 pixel에 위치하는 item의 node를 돌려준다.
만약 node가 없으면 nil이 돌아온다.
GetHitTestInfoAt method
- 선언: function GetHitTestInfoAt(X, Y: Integer): THitTests;
- 설명: X, Y parameter에 해당하는 좌표의 정보를 THitTests 라는
set type으로 돌려준다. THitTests set의 값과 의미는 다음과 같다. :
htAbove: 위치가 tree view control의 client area 윗쪽인 경우
htBelow: 위치가 tree view control의 client area 아랫쪽인 경우
htNowhere: 위치가 tree view의 client area에 있으나 마지막 item 밑에
있는 경우
htOnItem: 위치가 item의 bitmap 또는 label에 있는 경우
htOnButton: 위치가 item의 button에 있는 경우
htOnIcon: 위치가 item의 bitmap에 있는 경우
htOnIndent: 위치가 item의 indentation에 있는 경우
htOnLabel: 위치가 item의 label (text)에 있는 경우
htOnRight: 위치가 item의 우측에 있는 경우
htOnStateIcon: 위치가 사용자가 정의한 state icon에 있는 경우
htToRight: 위치가 tree view control의 client area 우측에 있는 경우
htToLeft: 위치가 tree view control의 client area 좌측에 있는 경우
예) 다음 코드는 drag and drop을 해주는 코드로, drag and drop event가
발생하면 넘어 오는 X, Y 좌표의 node를 알아내고, 그 좌표의 정보를 HT
(THitTest set)에 담은 후에 HT가 htOnItem, htOnIcon이면 child로
add하고, htNoWhere 이면 새로운 item으로 add하며, htOnIndent이면 item
사이에 insert한다.
procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
AnItem: TTreeNode;
AttachMode: TNodeAttachMode;
HT: THitTests;
begin
if TreeView1.Selected = nil then Exit;
HT := TreeView1.GetHitTestInfoAt(X, Y);
AnItem := TreeView1.GetNodeAt(X, Y);
if (HT - [htOnItem, htOnIcon, htNowhere, htOnIndent] <> HT) then
begin
if (htOnItem in HT) or (htOnIcon in HT) then AttachMode
:= naAddChild
else if htNowhere in HT then AttachMode := naAdd
else if htOnIndent in HT then AttachMode := naInsert;
TreeView1.Selected.MoveTo(AnItem, AttachMode);
end;
end;
LoadFromFile, SaveToFile method
- 선언: procedure LoadFromFile(const FileName: string);
procedure SaveToFile(const FileName: string);
- 설명: TreeView의 정보를 File로 save, load
LoadFromStream, SaveToStream method
- 선언: procedure LoadFromStream(Stream: TStream);
procedure SaveToStream(Stream: TStream);
- 설명: TreeView의 정보를 stream에 save, load
AlphaSort method
- 선언: function AlphaSort: Boolean;
- 설명: Tree view에서는 모든 root item을 label의 알파벳순으로
정렬해주는 method. Tree node object에서는 바로 아래 child
들을 정렬. 정렬이 성공적으로 끝나면 True를 돌려준다.
CustomSort method
- 선언: function CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
- 설명
: Callback 함수를 이용해 사용자 정의 sort를 행할 수 있는 method.
SortProc parameter는 application에서 정의한 callback 함수의 pointer이다.
Data parameter는 그 함수에 넘겨줄 수 있는 optional data 값이다.
Tree node의 CustomSort는 item의 모든 child item을 정렬하고,
tree view의 CustomSort는 tree view의 모든 item을 정렬한다.
Callback 함수는 비교할 2개의 item의 node와 하나의 32bit 값을 인자로 가진다.
기본적인 형태는 다음과 같다.
function CompareFunc(Node1, Node2: TTreeNode; ParamSort: Integer):
Integer; stdcall;
Callback 함수는 반드시 첫번째 item이 두번째보다 선행해야 될 경우 return값을
음수로 해야 하며, 같거나 동등한 위치이어야 한다면 0을, 첫번째 item이 두번째
뒤로 가야한다면 양수를 돌려주어야 한다.
만약 SortProc parameter의 값이 nil이면 default로 AlphaSort method
가 수행된다.
예) 다음 코드는 button click시 알파벳의 역순으로 정렬해주는 예제이다.
Callback 함수인 CustomSortProc는 Windows API function인 lstrcmp를
이용한다.
function CustomSortProc(Node1, Node2: TTreeNode; ParamSort: integer)
: integer; stdcall;
begin
Result := -lstrcmp(PChar(Item1.Text), PChar(Item2.Text));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TreeView1.CustomSort(@CustomSortProc, 0);
end;
Key Events
OnChange event
- 선언: TTVChangedEvent
= procedure(Sender: TObject; Node: TTreeNode) of object;
property OnChange: TTVChangedEvent;
- 설명: OnChange event는 selection이 바뀔 때마다 발생한다.
OnChanging event
- 선언: TTVChangingEvent = procedure(Sender: TObject; Node: TTreeNode;
var AllowChange: Boolean) of object;
property OnChanging: TTVChangingEvent;
- 설명: selection이 바뀌려고 할 때 발생한다. AllowChange parameter는 change
를 허용할 것인지 여부를 결정한다. 이것을 False로 설정하면 그 item을
사용자가 선택할 수 없다.
OnCollapsed, OnExpanded, OnDeletion event
- 선언: TTVExpandedEvent = procedure(Sender: TObject; Node: TTreeNode)
of object;
property OnCollapsed: TTVExpandedEvent;
property OnExpanded: TTVExpandedEvent;
property OnDeletion: TTVExpandedEvent;
- 설명: Tree가 collapse, expand, deletion 되었을 때 발생
OnCollapsing event
- 선언: TTVCollapsingEvent = procedure(Sender: TObject; Node: TTreeNode;
var AllowCollapse: Boolean) of object;
TTVExpandingEvent = procedure(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean) of object;
property OnCollapsing: TTVCollapsingEvent;
property OnExpanding: TTVExpandingEvent;
- 설명: Tree가 collapse, expand 되려고 할 때 발생. AllowCollapse를
False로 설정하면 collapse, expand 되지 않는다.
[강좌] TreeView와 Outline (7)
TTreeNodes Object
* TTreeView component의 Items property와 연관되어 있다.
* Item과 child item을 추가할 수 있는 method인 Add, AddFirst, AddChild,
AddChildFirst 등의 method가 있다. Add는 list의 가장 마지막에 item을
추가하고, AddFirst는 items list의 처음에 item을 추가한다. AddChild는
item을 items child list의 마지막에, AddChildFirst는 처음에 추가한다.
Data를 포함한 item들을 추가할 때에는 AddObject, AddObjectFirst,
AddChildObject, AddChildObjectFirst등의 method를 쓴다.
* Clear method는 tree view의 모든 item을 지우며, Delete method는 하나의
item을 제거한다. Insert method는 item을 tree view에 추가할 때 쓰이며,
InsertObject는 data를 포함했을 경우에 쓴다.
* BeginUpdate method는 EndUpdate method가 불리기 전에 tree view에 나타나지
않도록 한다.
* GetFirstNode method는 tree view의 첫번째 item을 돌려주며, GetNode는 주어진
ItemID에 해당하는 item을 돌려준다. Item[Index]는 주어진 index에 해당하는
item을 돌려준다. 이 경우 첫번째 item의 index는 0이고, 순차적인 index를 가
진다.
* Owner property는 TTreeNodes object를 소유한 tree view를 지정하며, Count
property에는 TTreeNodes object의 총 item 숫자가 기록되어 있다.
Key Properties
* Item property (run-time, read-only)
- 선언: property Item[Index: Integer]: TTreeNode;
- 설명: Index값을 넣어주면 item을 돌려준다. 첫번째 item의 index는 0, 두번째
item의 index는 1이다.
* Count property (run-time, read-only)
- 선언: property Count: Integer;
- 설명: item의 child item의 총수
* Owner property (run-time, read-only)
- 선언: property Owner: TTreeNodes;
- 설명: item을 소유하는 tree nodes object를 기록
Key Methods
* Add method
- 선언: function Add(Node: TTreeNode; const S: string): TTreeNode;
- 설명: Tree view에 새로운 item을 추가한다. 추가된 item은 가장 마지막에
추가된다.
* AddChild, AddChildFirst method
- 선언: function AddChild(Node: TTreeNode; const S: string): TTreeNode;
function AddChildFirst(Node: TTreeNode; const S: string): TTreeNode;
- 설명: 기본적으로 Add method와 같지만 각각 child item으로 AddChild는
가장 뒤에, AddChildFirst는 가장 앞에 추가된다.
* AddObject, AddObjectFirst, InsertObject, AddChildObject,
AddChildObjectFirst
- 선언: function AddObject(Node: TTreeNode; const S: string; Ptr: Pointer)
: TTreeNode;
function InsertObject(Node: TTreeNode; const S: string; Ptr: Pointer)
: TTreeNode;
function AddChildObject(Node: TTreeNode; const S: string;
Ptr: Pointer): TTreeNode;
- 설명: 기본적으로 AddMethod이하의 다른 method 들과 같지만, Ptr parameter에서
data를 지정해줄 수 있다는 점이 다르다.
* Delete method
- 선언: function Delete(Node: TTreeNode);
- 설명: Node parameter에 지정된 item을 삭제한다.
예) 다음 코드는 mouse click 할 때 X, Y 좌표가 특정 item 위에 있으면 그
item을 delete한다. 코드는 X, Y 좌표의 THitTests 형인 HT 변수에 담고,
HT가 pointer가 item위에 있음을 나타내고, checkbox에서 delete가 선택되어
있고, sender가 TreeView이면 item을 delete한다.
procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
HT : THitTests;
begin
if (CheckBox1.Checked and (Sender is TTreeView)) then
begin
HT := TreeView1.GetHitTestInfoAt(X,Y);
if (htOnItem in HT) then
TreeView1.Items.Delete(TreeView1.GetNodeAt(X,Y));
end;
end;
* GetNode method
- 선언: function GetNode(ItemId: HTreeItem): TTreeNode;
- 설명: TreeNode object의 property인 ItemId를 넘겨주면 TTreeNode object
인 item을 돌려주는 method.
* GetFirstNode method
- 선언: function GetFirstNode: TTreeNode;
- 설명: Tree view의 첫번째 item (TTreeNode object)을 돌려준다.
TTreeNode Object
* TTreeNode object는 TTreeView control의 individual item이다. 각각의 tree
node는 Text 와 Data 자료를 가진다. Text에는 문자열을 Data에는 특정
data structure의 pointer를 담고 있다. EditText method는 item을 edit mode로
전환한다.
* 각 item은 독특한 Index를 가지고 있다. Index는 TTreeView control의 Items
property의 index와 동일하다. Item의 child item들은 순차적으로 indexing되며
첫번째 child item의 index 값은 0이다. IndexOf method는 child item의
position을 돌려준다. 또한, AbsoluteIndex property에는 tree view의 첫번째
item으로부터의 index를 저장하고 있다.
* Item property는 tree view의 Index postion의 item을 저장하고 있으며,
Count property는 subitem의 수를 나타낸다. Item을 새로운 위치에 옮길
때에는 MoveTo method를 쓴다.
* Expanded property는 item이 현재 expand되어 있는지 나타낸다. 만약 True
이면 모든 child item이 tree view에 나타난다. IsVisible property는 item이
tree view에 보이는지를 나타낸다. 만약 item의 parent가 모두 expand 되었다면
item은 visible이다.
* Level property는 item의 level을 나타낸다. Top level의 item의 Level은 0이다.
HasChildren property는 item이 child item을 가졌는지 여부를 나타낸다.
* GetFirstChild method는 item의 첫번째 child를 돌려주며, GetLastChild,
GetPrevChild, GetNextChild는 각각 마지막, 이전, 다음 child item을
돌려준다. 비슷하게 GetNextSibling, GetPrevSibling은 같은 level의 이전과
다음 item을 돌려준다. GetNextVisible, GetPrevVisible method는 다음과
이전의 visible item들을 돌려준다.
* HasAsParent method는 넘겨준 item이 parent item이면 True를 돌려준다.
Parent property는 item의 parent node를 담고 있으며, TreeView property는
item을 가지고 있는 tree view를 나타낸다.
* Focused property는 item이 현재 focus를 가졌는지를 나타내며, Selected
property는 현재 node가 선택 되었는지를 나타낸다. DropTarget property는
drag and drop의 target이 되는 item을 나타낸다.
* SelectedIndex property는 item이 선택되었을 때 image list에 있는 icon의
index를 나타내며, OverlayIndex property는 tree view의 image list 중에
overlay mask (tree view의 다른 image위에 투명하게 덧씌워지는 image)로
쓰일 image의 index를 나타낸다. ImageIndex property는 item이 normal state
일 때 보여 줄 image를 나타내고, StateIndex property는 Tree View의
StateImages image list에서 어떤 image를 보여줄 것인지를 나타낸다.
Key Properties
* Item property (run-time)
- 선언: property Item[Index: Integer]: TTreeNode;
- 설명: child item (TTreeNode object)으로 접근한다. 첫번째 child item의
index position 은 0이다.
* Index property
- 선언: property Index: Longint;
- 설명: 첫번째 item의 Index 값은 1이다. Subitem이 있을 경우, 첫번째 subitem
의 index값보다 parent item의 index값이 1작다.
* Data property (run-time)
- 선언: property Data: Pointer;
- 설명: TTreeView control의 tree node의 Data를 pointer 형으로 가지고 있다.
* Count property (run-time, read-only)
- 선언: property Count: Integer;
- 설명: child item의 수를 나타낸다.
* Parent property
- 선언: property Parent: TTreeNode;
- 설명: parent item의 node를 나타낸다.
* Focused property (run-time)
- 선언: property Focused: Boolean;
- 설명: 현재 item이 focus를 가졌는지(standard focus rectangle에 들었는지)를
나타낸다.
* DropTarget property (run-time)
- 선언: property DropTarget: Boolean;
- 설명: item이 drag and drop의 target이 되었는지 여부를 나타낸다.
* ImageIndex property, SelectedIndex property (run-time)
- 선언: property ImageIndex: Integer;
property SelectedIndex: Integer;
- 설명: ImageIndex는 선택되지 않은 상태에서의 item의 image의 index이고,
SelectedIndex는 선택되었을 때의 image index이다. 연결된 imagelist
의 index값을 나타낸다.
* StateIndex property (run-time)
- 선언: property StateIndex: Integer;
- 설명: StateImages에 지정된 Image list의 image index값을 나타낸다.
값이 -1이면 state image가 그려지지 않는다.
Key Methods
* Expand method
- 선언: procedure Expand(Recurse: Boolean);
- 설명: child item을 expand한다. Recurse parameter를 True로 넘기면 모든
child item들이 expand된다.
예) 다음 코든 선택된 item의 모든 subitem을 expand한다.
TreeView1.Selected.Expand(True);
* Collapse method
- 선언: procedure Collapse(Recurse: Boolean);
- 설명: item의 child item을 모두 collapse한다.
* Delete method
- 선언: procedure Delete;
- 설명: item을 삭제한다.
* DeleteChildren method
- 선언: procedure DeleteChildren;
- 설명: item의 모든 child item을 삭제한다.
* IndexOf method
- 선언: function IndexOf(Value: TTreeNode): Integer;
- 설명: item의 바로 아래 child item (Value parameter)의 position을 알려준
다. 만약 Value 값이 child item이 아니라면, -1을 돌려준다. 첫번째
child item이 Value로 넘어갔다면 0이 돌아올 것이며, 두번째 child item
이 Value로 넘어갔다면 1이 넘어온다.
* HasAsParent method
- 선언: function HasAsParent(Value: TTreeNode): Boolean;
- 설명: Value값이 item의 parent item이면 True를 돌려준다.
* MoveTo method
- 선언: procedure MoveTo(Destination: TTreeNode; Mode: TNodeAttachMode);
- 설명: Tree node를 다른 위치로 옮길 때 쓰는 method이다. Destination
parameter는 옮겨갈 node를 지정하며, Mode parameter는
TNodeAttachMode의 형으로 어떤 식으로 옮길 것인지 지정한다.
Mode parameter의 값은 다음과 같다.
1) naAdd: list의 가장 마지막에 item으로 이동
2) naAddFirst: list의 가장 처음에 item으로 이동
3) naAddChild: child list의 가장 마지막 child item으로 이동
4) naAddChildFirst: child list의 가장 처음 child item으로 이동
5) naInsert:: destination node의 다음으로 insert하여 이동
* EditText method, CancelEdit method
- 선언: function EditText: Boolean;
procedure CancelEdit;
- 설명: item의 text를 바로 편집할 수 있게 하거나, 편집할 수 없게 하는
method
* MakeVisible method
- 선언: procedure MakeVisible;
- 설명: item을 tree view에 보이게 한다. 만약 parent item이 collapse되어
있을 때 이 procedure를 쓰면 parent가 expand된다.
* DisplayRect method
- 선언: function DisplayRect(TextOnly: Boolean): TRect;
- 설명: item을 이루는 rectangle을 TRect type으로 돌려준다. TextOnly
parameter가 true이면 TRect는 text만을 포함하며, false이면 line까지
포함해서 돌려준다.
* GetPrev method, GetNext method, GetPrevVisible method,
GetNextVisible method, GetPrevSibling method, GetNextSibling method
- 선언: function GetPrev: TTreeNode;
function GetNext: TTreeNode;
function GetPrevVisible: TTreeNode;
function GetNextVisible: TTreeNode;
function GetPrevSibling: TTreeNode;
function GetNextSibling: TTreeNode;
- 설명: 각각 tree view의 이전 item, 다음 item, 이전의 visible item,
다음 visible item, 같은 parent를 가지는 이전 item, 다음 item을
돌려준다.
* GetFirstChild method, GetLastChild method
- 선언: function GetFirstChild: TTreeNode;
function GetLastChild: TTreeNode;
- 설명: 각각 item의 첫번째와 마지막 child item을 돌려준다.
만약 child item이 없으면 nil을 돌려준다.
* GetPrevChild method, GetNextChild method
- 선언: function GetPrevChild(Value: TTreeNode): TTreeNode;
function GetNextChild(Value: TTreeNode): TTreeNode;
- 설명: Value parameter의 이전 child, 다음 child를 돌려준다. 만약 child가
없거나, 이전, 다음 값이 없으면 nil을 돌려준다.
* AlphaSort, CustomSort method
... TreeView의 key method 참조 !
[강좌] Tree형태의 자료의 저장
Outline이나, TreeView의 정보를 File로 저장하는 방법은 하고자 하는 일에따라
여러가지가 있을 수 있습니다.
단순히 Tree의 정보 (즉, 자리정보를 나타내는 index(Outline)나 node(TreeView)
그리고, item의 text만을 저장할 경우)만을 저장할 때는 간단합니다.
그냥 다른 Control들과 마찬가지로...
LoadFromFile과 SaveToFile을 쓰면 됩니다.
즉, 예를 들면 Form에다가 기본적으로 OpenDialog와 SaveDialog를 갖다놓고,
Outline의 정보를 저장하고 싶다면,
if SaveDialog1.Execute then Outline1.SaveToFile(SaveDialog1.FileName);
과 같이 써주심되고, TreeView라면 위의 Outline이름 대시 TreeView의 이름을
쓰면 되겠죠...
저장한 Tree정보를 읽어들을 때에는..
if OpenDialog1.Execute then Outline1.LoadFromFile(OpenDialog1.FileName);
등과 같이 써주시면 됩니다.
문제는 Tree형태의 정보를 DB와 연동하거나, graphic data 등 복합적인 데이타
를 같이 저장하는 경우인데...
이 때에는 약간의 알고리즘을 알아야 하고, 간단히 설명할 수가 없습니다.
Stream에 대해서 알아야 하고, DB Table의 구조와 Tree 형태의 구조의 차이점을
이해해야 합니다.
이부분은 따로 자료를 좀 정리하고,
예제를 만들어서 차후에 연재하고자 합니다.
제가 시간이 요즘 별로 없어서 답변이 부실한점 사과 드리고...
조만간에 더 좋은 강좌를 올리도록 하겠습니다.
그럼