お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"ツリー表示用のクラス"

この発言に対し以下のコメントが寄せられています
#01058 凛 さん RE:ツリー表示用のクラス:使用例
#01062 凛 さん RE:ツリー表示用のクラス

{ツリー表示する完全オリジナルなクラスです。(単に捜すのが面倒だった(^^;) 掲示板などで発言をTree表示するのに汎用的に使えると思ったので上げて おきます。使用サンプルもいっしょに上げておくのでご利用下さい。 サンプルとして上げるため機能は最小限にしています。 行数を減らすためにインデントやコメントも普通じゃない状態ですがご容赦下さ い。ご自由に拡張してお使い下さい。 } unit kTrees_small; interface uses SysUtils, Classes; const lnTitle=40;//タイトルのバイト数 lnWho =20;//発言者名のバイト数 type TKTIndex=Record Index:integer; Title:string[lnTitle];//タイトル Day:TDateTime;// resTo:integer;//レス対象 ルートの場合 -1 From:integer; //contents内の位置 Size:integer; //サイズ Layer:integer;//階層 Who:string[lnWho];//発言者 end; PKTIndex=^TKTIndex; TKTree=Class(TObject) private FZZ:integer; //ルート発言にツリー線付ける際に使うフラグ FPath:string; //データディレクトリ List:TList;//全タイトルレコードをぶら下げるためのList bufList:TStringList;//集計したタイトルリストを保持するためのもの FShowRootLine: boolean; procedure ClearList; function ListIndexOf(SayIndex:integer):integer; procedure LoadIndexFile; function GetCount: integer;//インデックスファイルからListに読み込む procedure SaveIndex; procedure setShowRootLine(const Value: boolean); public //ListIndexから発言番号得る function SayIndexOf(ListIndex:integer):integer; //リストインデックスを指定して発言内容を得る function LoadCtsListIndex(Index: integer): string; //発言を追加 ResToが0だとルートになります。 function AddComment(idxData:TKTIndex;data:string):boolea; procedure MakeNewFiles;//新しくidxとctsファイルを作る //指定範囲のタイトルツリー形式を得る 範囲はListIndexにて、、 function LoadIdx(startIndex,endIndex:integer):TStringList; //データのフォルダを指定してCreateする constructor Create(folderPath:string);Virtual; destructor Destroy;overRide;//Free時に保存してます。 property Count:integer read GetCount; property ShowRootLine:boolean read FShowRootLine write setShowRootLine; end; implementation const idxFN='Index.dat'; //サンプルなのでファイル名はこの名前に決め打ち cntFN='content.dat'; function TKTree.AddComment(idxData: TKTIndex;data:string):boolean; var pIndex:PKTIndex; f:File; loc:integer; InsertIndex:integer; Layer:integer; function GetInsertIndex(idx:integer):integer; var j:integer; begin Layer:=0; result:=ListIndexOf(idx); if result<>-1 then begin Layer:=PKTIndex(List[result])^.Layer+1; if result=List.Count-1 then result:=-1 else begin j:=1; while (result+j<List.Count-1) do begin if PKTIndex(List[result+j])^.Layer < Layer then begin result:=result+j; break; end; inc(j); end; end; end; end; begin result:=False; if not FileExists(FPath+cntFN) then Exit; assignFile(f,FPath+cntFN); reset(f,1); try loc:=FileSize(f); seek(f,loc); BlockWrite(f,PChar(data)^,Length(data)); new(pIndex); pIndex^:=idxData; pIndex^.From:=loc; pIndex^.Size:=Length(data); pIndex^.Day:=now; pIndex^.Index:=List.Count+1; pIndex^.Layer:=0; //発言番号は1から始まるのでresToはmaxList.Countまで可能 if (pIndex^.resTo>0) and (pIndex^.resTo<=List.Count) then begin //ルート発言のインデックスを得る InsertIndex:=GetInsertIndex(pIndex^.resTo); pIndex^.Layer:=Layer;//GetInsertIndexで設定している if InsertIndex<>-1 then begin List.Insert(InsertIndex,pIndex); end else List.Add(pIndex); end else List.Add(pIndex); result:=True; finally closeFile(f); end; end; procedure TKTree.ClearList; var i:integer; begin for i:= 0 to List.Count-1 do Dispose(PKTIndex(List[i])); end; constructor TKTree.Create(folderPath: string); begin ShowRootLine:=false; List:=TList.Create; FPath:=folderPath; if not IsDelimiter('\',FPath,Length(FPath)) then FPath:=FPath+'\'; bufList:=TStringList.Create; LoadIndexFile; end; destructor TKTree.Destroy; begin SaveIndex; ClearList; List.Free; bufList.Free; inherited; end; function TKTree.GetCount: integer; begin result:=List.Count; end; function TKTree.SayIndexOf(ListIndex: integer): integer; begin if (ListIndex<0) or (ListIndex>List.Count-1) then result:=-1 else result:=PKTIndex(List[ListIndex])^.Index; end; //指定発言番号のリスト上でのIndexを返す function TKTree.ListIndexOf(SayIndex: integer): integer; var i:integer; begin result:=-1; for i:= 0 to List.Count-1 do begin if PKTIndex(List[i])^.Index=SayIndex then begin result:=i; break; end; end; end; //Listの指定Indexの内容を得る function TKTree.LoadCtsListIndex(Index:integer):string; var f:file; buf:PChar; begin result:=''; if Index<> -1 then begin assignFile(f,FPath+cntFN); reset(f,1); try buf:=StrAlloc(PKTIndex(List[Index])^.Size+1); try seek(f,PKTIndex(List[Index])^.From); BlockRead(f,buf^,PKTIndex(List[Index])^.Size); buf[PKTIndex(List[Index])^.Size]:=#0; result:=String(buf); finally StrDispose(buf);end; finally closeFile(f);end; end; end; function TKTree.LoadIdx(startIndex, endIndex: integer): TStringList; const space=' ';//2バイトでないとだめです。 var i,sp,currLayer:integer; currHead,hook,curr:string; begin bufList.Clear; if List.Count=0 then Exit; for i:= EndIndex downto startIndex do begin with PKTIndex(List[i])^ do begin if (not FShowRootLine) and (Layer=0) then begin currHead:=''; currLayer:=Layer; hook:=''; end else if i=endIndex then begin currLayer:=Layer; currHead:=''; for sp:= 1 to currLayer-Fzz do currHead:=currHead+space; hook:='└'; end else if currLayer=Layer then hook:='├' else if currLayer<Layer then //右にシフト begin hook:='└'; if Fzz<>0 then begin if Layer<>1 then currHead:=currHead+'│' else currHead:=''; end else begin currHead:=currHead+'│'; end; for sp:= 0 to (Layer-CurrLayer)-2 do currHead:=currHead+space; currLayer:=Layer; end else begin//currLayer>Layer 左にシフト if copy(currHead,Length(currHead)-1,2)='│' then hook:='├' else hook:='└'; currLayer:=Layer; currHead:=Copy(currHead,1,(currLayer-Fzz)*2); end; curr:=currHead+Hook+Format('%d %6d %20S %40S', [Index,layer,Who,Title]); bufList.InsertObject(0,curr,Pointer(i));//List上のIndexを渡す end; end; result:=bufList; end; procedure TKTree.LoadIndexFile; var f:file of TKTIndex; curr:PKTIndex; begin clearList; if not FileExists(FPath+idxFN) then MakeNewFiles; AssignFile(f,FPath+idxFN); //↑無ければ新規 reset(f); try while not eof(f) do begin new(curr); read(f,curr^); List.Add(curr); end; finally closeFile(f);end; end; procedure TKTree.MakeNewFiles; var f:file; idx:file Of PKTIndex; begin assignFile(f,FPath+cntFN); rewrite(f); closeFile(f); assignFile(idx,FPath+idxFN); rewrite(idx); closeFile(idx); end; procedure TKTree.SaveIndex; var f:file of TKTIndex; i:integer; begin AssignFile(f,FPath+idxFN); rewrite(f); try for i:=0 to List.Count-1 do write(f,PKTIndex(List[i])^); finally closeFile(f); end; end; procedure TKTree.setShowRootLine(const Value: boolean); begin FShowRootLine := Value; if value then FZZ:=0 else FZZ:=1; end; end. 00/05/01(月) 16:08 凛(MXB01744) Original document by 凛 氏 ID:(MXB01744)



ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum