안녕하세요.
설명절전이나 후나 TreeView에 미쳐(?) 사는 델파이를 사랑하는 사람입니다.
제는 지금 ini파일에서 읽은 내용을 TreeView에 출력하려고 합니다.
다행히 저와 같은 경우로 많은 글들이 올라와 있어서 겨우 겨우 조금씩 조금씩 응용해가면서 일을 진행해나갔습니다. 정말 많은 도움이 되었어요...
(뒤늦게나마 델선배님들께 감사의 말씀 드립니다. 꾸벅!!)
그런데, 일을 계속 진행하던 중 막히는 부분이 생겼고, 아주 쉽게 해결될것 같다는 미련을 버리지 못해 꽤 오랜(?) 시간을 혼자 끙끙 앓다가 이제서야 도움을 요청하게 되었어요.
정말이지 궁금해요. 문제의 답이 무엇인지를.....
문제에 대해 예를 들어 말씀드리자면 다음과 같아요.
(예) ini파일의 내용이 아래와 같을때,
sample.ini
==============================
[TotalCount]
Count=6
[Address]
서울시 강남구 역삼동;
강원도 강릉시 죽헌동;
서울시 송파구 오륜동;
인천시 부평구 부평동;
강원도 강릉시 초당동;
부산시 금정구 오륜동;
-----------------------------
Treeview에서는 다음과 같이 출력되어야 해요.
[결과 A]
===========================================
서울시
강남구
역삼동
송파구
오륜동
강원도
강릉시
죽헌동
초당동
인천시
부평구
부평동
부산시
금정구
오륜동
-----------------------------------------
위에서처럼 Treeview에 출력하려면, 동적으로 생성하기전에 생성하려는 노드가 있는지 없는지 찾아보는 과정이 있어야하기에 다른 분의 FindNode라는 함수를 사용하여서 노드의 존재여부를 검색하는 루틴을 넣었습니다. 그런데 원하는 결과가 나오질 않아요.
다음의 소스는 제가 지금까지 한 내용입니다.
Function CutStr(var st : String; aLength : Integer) : String;
begin
result := Copy(st,1,aLength);
st := Copy(st,aLength+1,length(st) - aLength);
end;
function TForm1.FindNode( Str : String) : TTreeNode; // 다른 분이 만든 함수
var
CurItem: TTreeNode;
begin
Result := nil; // 이 부분은 제가 추가했습니다.
// 이걸 안하면 뒤에 FindNode함수를 사용할때 에러가 발생하더라구요.
CurItem := TreeView1.Items.GetFirstNode;
while CurItem <> nil do
begin
if CurItem.Text = Str then
begin
Result := CurItem;
exit;
end;
CurItem := CurItem.GetNext;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
I, J : Integer;
IniFile: TIniFile;
Fst,Snd,Trd, Section, FName, temp, IP : string;
Sections : TStringList;
ParentNode, ChildNode : TTreeNode;
begin
ItemCount := 0; // 전역 변수
FName := 'c:samp.ini';
Sections := TStringList.Create;
Sections.LoadFromFile(FName);
IniFile := TIniFile.Create(FName); // IniFileName = 사용자 INI 파일명
ItemCount := IniFile.ReadInteger('TotalCount', 'Count', 0);
TreeView1.Items.BeginUpdate;
temp := '';
for I := 0 to Sections.Count - 1 do
begin
Section := Sections[i];
temp := temp + Section;
if Pos(']',temp) <> 0 then CutStr(temp,Pos(']',temp));
end;
for J := 0 to ItemCount-1 do
begin
Fst := IniFile.ReadString('IP Address',temp,CutStr(temp,Pos(' ',temp)-1));
CutStr(temp,1);
Snd := IniFile.ReadString('IP Address',temp,CutStr(temp,Pos(' ',temp)-1));
CutStr(temp,1);
Trd := IniFile.ReadString('Address',temp,CutStr(temp,Pos(';',temp)-1));
CutStr(temp,1);
if (FindNode(Fst) <> nil) then ParentNode := FindNode(Fst)
else ParentNode := TreeView1.Items.Add(Treeview1.Selected,Fst);
if (FindNode(Snd) <> nil) then ChildNode := FindNode(Snd)
else ChildNode := TreeView1.Items.AddChild(ParentNode,Snd);
if (FindNode(Trd) <> nil) then ShowMessage('같은 이름이 이미 존재합니다.')
else TreeView1.Items.AddChild(ChildNode,Trd);
end;
TreeView1.Items.EndUpdate;
IniFile.Free;
end;
위 소스대로하면 "같은 이름이 이미 존재합니다."라는 메세지창이 뜨고, ini파일의 내용이 아래처럼 출력됩니다. (물론 당연한 결과이죠)
[결과 B]
===========================================
서울시
강남구
역삼동
송파구
오륜동
강원도
강릉시
죽헌동
초당동
인천시
부평구
부평동
부산시
금정구
-----------------------------------------
"오륜동"이 서울시 송파구와 부산시 금정구에 둘다 있잖아요.
같은 이름의 "동"(ChildNode)이 있어도 ParentNode는 다르니까 [결과 A]처럼 해야되는데 [결과 B]처럼 출력돼요. T.T
문제가 뭔지는 알겠는데 해결방법을 잘 모르겠어요.
FindNode라는 함수는 Treeview안에 있는 모든 노드들중에서 찾는 함수라서 제가 사용하는데 적합하지않아서 이렇게 저렇게 바꾸어 보았는데 번번히 실패예요.
저는 모든 노드에서가 아닌, 동일ParentNode안의 ChildNode중에서 같은 이름의 노드가 있는지를 체크해야 하는데 어떻게 해야하는지 도저히 모르겠습니다.
더 이상 진전이 없습니다.
지금에 이르기까지도 무척 고생했거든요. 처음 일을 시작할때는 금방 끝날줄 알았는데 ...
일의 초반부터 이렇게 헤메고 있어 앞이 캄캄합니다.
아직 갈길이 멀기만 한데...
하나 하나 풀어나가는 재미가 있긴 하지만, 혼자 공부하는것도 아닌, 기한이 있는 일인데 제자리에서 계속 맴맴하니까 답답하고 시간도 너무 많이 흘렀어요.
앞으로 동적으로 Treeview의 Items를 입력할수 있도록 해서 Ini파일에 쓰도록 해야도 되고 ... 여러가지로 할 일은 많은데...
제발 델선배님들의 따뜻한 관심과 일타를 부탁드립니다.
(얼굴도 모르는 델선배님들께 도움을 요청해서 너무 죄송하지만.... 그래도 도와주셨으면 합니다.)
늦은 인사지만 새해복 많이 많이 받으시고 건강하세요.
그리고 하시는 일 모두 모두 성취되시길 기원합니다.
@--&~~
var
aList: TStringList;
I: Integer;
begin
aList := TStringList.Create;
for I := 0 to Treeview1.Selected.Count - 1 do
begin
if aList.IndexOf(Treeview1.Selected.Item[I].Text) < 0 then
aList.Add(Treeview1.Selected.Item[I].Text)
else begin
MessageBox(handle, '이미 같은 이름의 노드가 있습니다!', '메세지',
MB_IconInformation);
continue;
end;
end;
end;
그런데, 님의 경우와 비슷한 경우를 저도 구현해본적이 있는데요...
그땐 저도 시간이 워낙 없어서 아주 빨리 만들려고 한 적이 있습니다.
저는 그것을 님의 방식과 좀더 다르게 만들었었습니다.
그래서 잠깐 보여드릴까 합니다.
물론 허접 노가다 코딩이라서 절대 님에게 도움이 될리는 없겠지만서두요...
그냥 약간의 도움이라도 됐으면 하는 바램에서 보여드립니다.
Unit의 Private절에 TreeNodeList: TStringList;
라고 하나 선언해주고 Form의 Create나 Show절에서 생성해주구요, Close절에서 Free시켜주면 되구요...
type
pvList = ^TvList;
TvList = record
Path: String;
end;
와 같이 구조체를 하나 만들어줍니다.
'서울시 강남구 역삼동' 이라는 걸 만들게 되면...
서울시 라는 노드와 그 밑에 강남구, 그리고 그 밑에 역삼동 이라는 것을 만들게 되지요.
구조체의 Path변수 에다가는 '서울시', '서울시 강남구', '서울시 강남구 역삼동'과 같은 형태로 저장을 하면 될꺼구요...
만약 역삼동 부분을 저장할때 그 저장방식은 다음과 같습니다.
var
aRecord: pvList;
aNode, bNode: TTreeNode;
I, J: Integer;
begin
for I := 0 to TreeNodeList.Count - 1 do
begin
aNode := TTreeNode(TreeNodeList.Objects[I]);
aRecord := aNode.Data;
if Trim(aRecord^.Path) = '서울시 강남구' then
begin
for J := 0 to aNode.Count - 1 do
begin
if aNode.Item[J].Text = '역삼동' then
begin
// 중복 메세지 처리
Exit;
end;
end;
bNode ;= Treeview1.Items.ADd(aNode, '역삼동');
new(aRecord);
aRecord^.Path := '서울시 강남구 역삼동';
bNode.Data := aRecord;
TreeNodeList.AddObject('역삼동', bNode);
Exit;
end;
end;
end;
위의 소스는 제가 상당히 많은 부분을 축약했습니다. 저는 당시 이걸 구현할때 각 트리의 노드의 데이타에 해당 시/구/동에 대한 정보를 바로 저장해둘 수가 있어야 했던 이유가 있어서 위와 같이 구현을 했더랬습니다.
그런데, 님의 문제를 보니깐 그냥 제가 구현했던 방법을 조금 응용해서 위와같이 변경시키면 쉽게 될것 같아서 이렇게 몇자 허접하게 끄적였습니다.
수고하십시오.
sis7 wrote:
> 안녕하세요.
> 설명절전이나 후나 TreeView에 미쳐(?) 사는 델파이를 사랑하는 사람입니다.
>
> 제는 지금 ini파일에서 읽은 내용을 TreeView에 출력하려고 합니다.
> 다행히 저와 같은 경우로 많은 글들이 올라와 있어서 겨우 겨우 조금씩 조금씩 응용해가면서 일을 진행해나갔습니다. 정말 많은 도움이 되었어요...
> (뒤늦게나마 델선배님들께 감사의 말씀 드립니다. 꾸벅!!)
>
> 그런데, 일을 계속 진행하던 중 막히는 부분이 생겼고, 아주 쉽게 해결될것 같다는 미련을 버리지 못해 꽤 오랜(?) 시간을 혼자 끙끙 앓다가 이제서야 도움을 요청하게 되었어요.
> 정말이지 궁금해요. 문제의 답이 무엇인지를.....
>
> 문제에 대해 예를 들어 말씀드리자면 다음과 같아요.
>
> (예) ini파일의 내용이 아래와 같을때,
>
> sample.ini
> ==============================
> [TotalCount]
> Count=6
>
> [Address]
> 서울시 강남구 역삼동;
> 강원도 강릉시 죽헌동;
> 서울시 송파구 오륜동;
> 인천시 부평구 부평동;
> 강원도 강릉시 초당동;
> 부산시 금정구 오륜동;
> -----------------------------
>
> Treeview에서는 다음과 같이 출력되어야 해요.
>
> [결과 A]
> ===========================================
> 서울시
> 강남구
> 역삼동
> 송파구
> 오륜동
>
> 강원도
> 강릉시
> 죽헌동
> 초당동
>
> 인천시
> 부평구
> 부평동
>
> 부산시
> 금정구
> 오륜동
> -----------------------------------------
>
> 위에서처럼 Treeview에 출력하려면, 동적으로 생성하기전에 생성하려는 노드가 있는지 없는지 찾아보는 과정이 있어야하기에 다른 분의 FindNode라는 함수를 사용하여서 노드의 존재여부를 검색하는 루틴을 넣었습니다. 그런데 원하는 결과가 나오질 않아요.
>
> 다음의 소스는 제가 지금까지 한 내용입니다.
>
> Function CutStr(var st : String; aLength : Integer) : String;
> begin
> result := Copy(st,1,aLength);
> st := Copy(st,aLength+1,length(st) - aLength);
> end;
>
> function TForm1.FindNode( Str : String) : TTreeNode; // 다른 분이 만든 함수
> var
> CurItem: TTreeNode;
> begin
> Result := nil; // 이 부분은 제가 추가했습니다.
> // 이걸 안하면 뒤에 FindNode함수를 사용할때 에러가 발생하더라구요.
> CurItem := TreeView1.Items.GetFirstNode;
> while CurItem <> nil do
> begin
> if CurItem.Text = Str then
> begin
> Result := CurItem;
> exit;
> end;
> CurItem := CurItem.GetNext;
> end;
> end;
>
> procedure TForm1.FormCreate(Sender: TObject);
> var
> I, J : Integer;
> IniFile: TIniFile;
> Fst,Snd,Trd, Section, FName, temp, IP : string;
> Sections : TStringList;
> ParentNode, ChildNode : TTreeNode;
>
> begin
> ItemCount := 0; // 전역 변수
> FName := 'c:samp.ini';
> Sections := TStringList.Create;
> Sections.LoadFromFile(FName);
>
> IniFile := TIniFile.Create(FName); // IniFileName = 사용자 INI 파일명
> ItemCount := IniFile.ReadInteger('TotalCount', 'Count', 0);
>
> TreeView1.Items.BeginUpdate;
> temp := '';
>
> for I := 0 to Sections.Count - 1 do
> begin
> Section := Sections[i];
> temp := temp + Section;
> if Pos(']',temp) <> 0 then CutStr(temp,Pos(']',temp));
> end;
>
> for J := 0 to ItemCount-1 do
> begin
> Fst := IniFile.ReadString('IP Address',temp,CutStr(temp,Pos(' ',temp)-1));
> CutStr(temp,1);
> Snd := IniFile.ReadString('IP Address',temp,CutStr(temp,Pos(' ',temp)-1));
> CutStr(temp,1);
> Trd := IniFile.ReadString('Address',temp,CutStr(temp,Pos(';',temp)-1));
> CutStr(temp,1);
>
> if (FindNode(Fst) <> nil) then ParentNode := FindNode(Fst)
> else ParentNode := TreeView1.Items.Add(Treeview1.Selected,Fst);
>
> if (FindNode(Snd) <> nil) then ChildNode := FindNode(Snd)
> else ChildNode := TreeView1.Items.AddChild(ParentNode,Snd);
>
> if (FindNode(Trd) <> nil) then ShowMessage('같은 이름이 이미 존재합니다.')
> else TreeView1.Items.AddChild(ChildNode,Trd);
> end;
>
> TreeView1.Items.EndUpdate;
> IniFile.Free;
> end;
>
>
> 위 소스대로하면 "같은 이름이 이미 존재합니다."라는 메세지창이 뜨고, ini파일의 내용이 아래처럼 출력됩니다. (물론 당연한 결과이죠)
>
> [결과 B]
> ===========================================
> 서울시
> 강남구
> 역삼동
> 송파구
> 오륜동
>
> 강원도
> 강릉시
> 죽헌동
> 초당동
>
> 인천시
> 부평구
> 부평동
>
> 부산시
> 금정구
> -----------------------------------------
>
> "오륜동"이 서울시 송파구와 부산시 금정구에 둘다 있잖아요.
> 같은 이름의 "동"(ChildNode)이 있어도 ParentNode는 다르니까 [결과 A]처럼 해야되는데 [결과 B]처럼 출력돼요. T.T
>
> 문제가 뭔지는 알겠는데 해결방법을 잘 모르겠어요.
> FindNode라는 함수는 Treeview안에 있는 모든 노드들중에서 찾는 함수라서 제가 사용하는데 적합하지않아서 이렇게 저렇게 바꾸어 보았는데 번번히 실패예요.
> 저는 모든 노드에서가 아닌, 동일ParentNode안의 ChildNode중에서 같은 이름의 노드가 있는지를 체크해야 하는데 어떻게 해야하는지 도저히 모르겠습니다.
>
> 더 이상 진전이 없습니다.
> 지금에 이르기까지도 무척 고생했거든요. 처음 일을 시작할때는 금방 끝날줄 알았는데 ...
>
> 일의 초반부터 이렇게 헤메고 있어 앞이 캄캄합니다.
> 아직 갈길이 멀기만 한데...
> 하나 하나 풀어나가는 재미가 있긴 하지만, 혼자 공부하는것도 아닌, 기한이 있는 일인데 제자리에서 계속 맴맴하니까 답답하고 시간도 너무 많이 흘렀어요.
>
> 앞으로 동적으로 Treeview의 Items를 입력할수 있도록 해서 Ini파일에 쓰도록 해야도 되고 ... 여러가지로 할 일은 많은데...
>
> 제발 델선배님들의 따뜻한 관심과 일타를 부탁드립니다.
> (얼굴도 모르는 델선배님들께 도움을 요청해서 너무 죄송하지만.... 그래도 도와주셨으면 합니다.)
>
> 늦은 인사지만 새해복 많이 많이 받으시고 건강하세요.
> 그리고 하시는 일 모두 모두 성취되시길 기원합니다.
>
> @--&~~
>
>