{---------------------------------------- 履歴 2010/06/10(木) ・ WordDecomposeをDelimitedTextUnitに変更してWordCount/WordGetを改良 2011/06/10(金) ・DelimitedTextUnit>>StringSplitterUnit //----------------------------------------} unit RightFitStatusBar; interface uses Windows, Messages, SysUtils, Classes, Controls, ComCtrls, IntValuesStr; type TRightMode = (rmNormal,rmResizeOne,rmResizeAll); TRightFitStatusBar = class(TStatusBar) private //FFitWidths: array of Integer; FFitWidthsString: String; FRightMode: TRightMode; FResizePanel: Integer; procedure SetRightMode(const Value: TRightMode); function GetFitWidthsString: TIntValuesStr; procedure SetFitWidthsString(const Value: TIntValuesStr); function CheckFitWidthsStr(ValueStr: String): Boolean; function FitWidths(Index: Integer): Integer; function MinPanelWidth: Integer; procedure InitialFitPanelsWidth; protected procedure Resize; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure CreateHandle; override; published property RightMode: TRightMode read FRightMode write SetRightMode default (rmNormal); property ResizePanel: Integer read FResizePanel write FResizePanel default 0; property FitWidthsString: TIntValuesStr read GetFitWidthsString write SetFitWidthsString; end; procedure Register; implementation uses StringSplitterUnit; procedure Register; begin RegisterComponents('Samples', [TRightFitStatusBar]); end; {------------------------------- //起動・終了 備考: 履歴: 2001/10/24 //--▼----------------------▽--} constructor TRightFitStatusBar.Create(AOwner: TComponent); begin FFitWidthsString := ''; FResizePanel := 0; FRightMode := rmNormal; inherited Create(AOwner); ControlStyle:= ControlStyle + [csAcceptsControls]; end; destructor TRightFitStatusBar.Destroy; begin inherited Destroy; end; procedure TRightFitStatusBar.CreateHandle; begin inherited; InitialFitPanelsWidth; end; //--△----------------------▲-- //------------------------------- //Sの中にSubCharがいくつあるかカウントする(2バイト対応) //SubCharと一致するコードが全角文字に存在しても無視されます function CharCount(const SubChar: Char; const S: string): Integer; var i: Integer; begin Result := 0; if (SubChar = '') or (S = '') then exit; for i := 1 to Length(S) do begin if S[i]=SubChar then begin if ByteType(S,i) = mbSingleByte then //半角なら begin Inc(Result); end; end; end; end; //ValueStrの値がFitWidthsStringとして正しいかどうか評価する関数 function TRightFitStatusBar.CheckFitWidthsStr(ValueStr: String): Boolean; var i, val: Integer; s: String; begin Result := False; {↓単語の数} if WordCount(ValueStr, [';'], dmDelimiterExactly) <> Panels.Count then Exit; {↓単語の中身} for i := 0 to Panels.Count-1 do begin s := WordGet(ValueStr, [';'], i, dmDelimiterExactly); if not ((TryStrToInt(s, val) = True)) then Exit; {↑数字じゃない場合ははじく} end; Result := True; end; //右寄せStatusBarのパラメータをセットします procedure TRightFitStatusBar.InitialFitPanelsWidth; var i: Integer; begin if CheckFitWidthsStr(FFitWidthsString)=False then begin FFitWidthsString := ''; for i := 0 to Panels.Count-1 do begin FFitWidthsString := FFitWidthsString + IntToStr(Panels[i].Width); if i = Panels.Count-1 then break; FFitWidthsString := FFitWidthsString + ';'; end; end; end; procedure TRightFitStatusBar.Resize; var BarWidth, PointPanel: Integer; i: Integer; begin //(*--▽---------------------------▼-- case FRightMode of rmNormal: ; rmResizeOne: begin {↓リサイズするPanel以外のPanelの幅を取得} BarWidth := 0; for i:=0 to Panels.Count-1 do begin if not(i=FResizePanel) then BarWidth := BarWidth + FitWidths(i); end; if (Width-BarWidth-MinPanelWidth) <= 0 then begin {↓パネルサイズがリサイズ最小サイズより小さい場合} for i := 0 to Panels.Count-1 do begin if i=FResizePanel then Panels[FResizePanel].Width := MinPanelWidth else Panels[i].Width := FitWidths(i); end; end else begin {↓パネルサイズがリサイズ最小サイズより大きい場合} for i := 0 to Panels.Count-1 do begin if i=FResizePanel then Panels[FResizePanel].Width := Width - BarWidth else Panels[i].Width := FitWidths(i); end; end; end; rmResizeAll: begin BarWidth:=0; PointPanel := Panels.Count; repeat dec(PointPanel); BarWidth := BarWidth + FitWidths(PointPanel); until (Width < BarWidth)or(PointPanel=0) ; for i:=0 to PointPanel-1 do Panels[i].Width := 0; BarWidth := 0; for i:=PointPanel+1 to Panels.Count-1 do begin Panels[i].Width := FitWidths(i); BarWidth := BarWidth + FitWidths(i); end; Panels[PointPanel].Width := Width - BarWidth; end; end;//case //--▲---------------------------△--*) inherited Resize; end; {------------------------------- //フィットサイズのプロパティ設定 備考: Get時:動的配列FFitWidthsとIndexが一致しなければ0を返す Set時:動的配列の数とPanels.Countを一致させる 履歴: 2001/10/24 //--▼----------------------▽--} function TRightFitStatusBar.GetFitWidthsString: TIntValuesStr; begin if CheckFitWidthsStr(FFitWidthsString) = False then InitialFitPanelsWidth; Result := FFitWidthsString; end; procedure TRightFitStatusBar.SetFitWidthsString(const Value: TIntValuesStr); begin if Value <> FFitWidthsString then begin if CheckFitWidthsStr(Value) = False then Exit; FFitWidthsString := Value; end; end; //--△----------------------▲-- //------------------------------- //FitWidthをIndexから求める //*の場合には0が戻る function TRightFitStatusBar.FitWidths(Index: Integer): Integer; var Count: Integer; begin Result := 0; Count := WordCount(FFitWidthsString, [';'], dmDelimiterExactly); if (Index < 0) or (Count-1 < Index) then Exit; Result := StrToIntDef(WordGet(FFitWidthsString, [';'], Index, dmDelimiterExactly), 0); end; //------------------------------- //リサイズ時最小サイズを求めている function TRightFitStatusBar.MinPanelWidth: Integer; begin Result := 0; case FRightMode of rmResizeOne: begin Result := FitWidths(FResizePanel); end; end; end; procedure TRightFitStatusBar.SetRightMode(const Value: TRightMode); begin if FRightMode<>Value then begin if SimplePanel then FRightMode := rmNormal else FRightMode := Value; end; end; end.