| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008 | unit PathLabel;interface{$WARN UNIT_PLATFORM OFF}uses  Messages, StdCtrls, Controls, Classes, Forms, Windows, Graphics;type  TCustomPathLabel = class;  TPathLabelGetStatusEvent = procedure(Sender: TCustomPathLabel; var Active: Boolean) of object;  TPathLabelPathClickEvent = procedure(Sender: TCustomPathLabel; Path: string) of object;  TCustomPathLabel = class(TCustomLabel)  private    FColors: array[0..5] of TColor;    FIndentHorizontal: Integer;    FIndentVertical: Integer;    FUnixPath: Boolean;    FOnGetStatus: TPathLabelGetStatusEvent;    FOnPathClick: TPathLabelPathClickEvent;    FOnMaskClick: TNotifyEvent;    FDisplayPath: string;    FShortenedDisplayPath: string;    FShortenedPath: string;    FDisplayHotTrack: string;    FDisplayMask: string;    FHotTrack: Boolean;    FMouseInView: Boolean;    FIsActive: Boolean;    FIsEnabled: Boolean;    FMask: string;    FAutoSizeVertical: Boolean;    procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW;    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;    function GetColors(Index: Integer): TColor;    procedure SetColors(Index: Integer; Value: TColor);    procedure SetIndentHorizontal(AIndent: Integer);    procedure SetIndentVertical(AIndent: Integer);    procedure SetUnixPath(AUnixPath: Boolean);    procedure SetMask(Value: string);    procedure SetAutoSizeVertical(Value: Boolean);    procedure SetFocusControl(Value: TWinControl);    function GetFocusControl: TWinControl;    function CalculateAutoHotTrackColor(C: TColor): TColor;    procedure CalculateAutoHotTrackColors;    function CalculateAutoHotTrackColorComponent(C: Byte; Bright: Boolean): Byte;    function UseHotTrack: Boolean;  protected    procedure AdjustBounds; override;    procedure Click; override;    procedure DoDrawTextIntern(var Rect: TRect; Flags: Longint; S: string);    procedure DoDrawText(var Rect: TRect; Flags: Longint); override;    procedure Notification(AComponent: TComponent;      Operation: TOperation); override;    procedure Paint; override;    function IsActive: Boolean;    function TrackingActive: Boolean;    function HotTrackPath: string;    function GetSeparator: Char;    procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;    procedure DoPathClick(Path: string); virtual;    procedure DoMaskClick;    procedure DblClick; override;    procedure DoContextPopup(MousePos: TPoint; var Handled: Boolean); override;  public    constructor Create(AnOwner: TComponent); override;    procedure UpdateStatus;    function UseRightToLeftAlignment: Boolean; override;    property ActiveColor: TColor index 1 read GetColors write SetColors      default clActiveCaption;    property ActiveTextColor: TColor index 3 read GetColors write SetColors      default clCaptionText;    property UnixPath: Boolean read FUnixPath write SetUnixPath default False;    property IndentHorizontal: Integer read FIndentHorizontal      write SetIndentHorizontal default 5;    property IndentVertical: Integer read FIndentVertical      write SetIndentVertical default 1;    property InactiveColor: TColor index 0 read GetColors write SetColors      default clInactiveCaption;    property InactiveTextColor: TColor index 2 read GetColors write SetColors      default clInactiveCaptionText;    property OnGetStatus: TPathLabelGetStatusEvent read FOnGetStatus write FOnGetStatus;    property OnPathClick: TPathLabelPathClickEvent read FOnPathClick write FOnPathClick;    property OnMaskClick: TNotifyEvent read FOnMaskClick write FOnMaskClick;    property HotTrack: Boolean read FHotTrack write FHotTrack default False;    property Mask: string read FMask write SetMask;    property AutoSizeVertical: Boolean read FAutoSizeVertical write SetAutoSizeVertical default False;    property FocusControl: TWinControl read GetFocusControl write SetFocusControl;    property Caption;    property Hint stored False;    property Align default alTop;  end;type  TPathLabel = class(TCustomPathLabel)  published    property ActiveColor;    property ActiveTextColor;    property UnixPath;    property IndentHorizontal;    property IndentVertical;    property InactiveColor;    property InactiveTextColor;    property AutoSizeVertical;    property HotTrack;    property OnGetStatus;    property OnPathClick;    property OnMaskClick;    property Align;    property Alignment;    property Anchors;    property AutoSize;    property BiDiMode;    property Constraints;    property DragCursor;    property DragKind;    property DragMode;    property Enabled;    property Font;    property ParentBiDiMode;    property ParentFont;    property PopupMenu;    property Transparent;    property Visible;    property OnClick;    property OnDblClick;    property OnDragDrop;    property OnDragOver;    property OnEndDock;    property OnEndDrag;    property OnMouseDown;    property OnMouseMove;    property OnMouseUp;    property OnStartDock;    property OnStartDrag;  end;procedure Register;implementationuses  { SysUtils must overload deprecated FileCtrl (implements MinimizeName) }  FileCtrl, SysUtils, Math, PasTools, StrUtils;const  // magic value  HotTrackMask: string = #1;procedure Register;begin  RegisterComponents('Martin', [TPathLabel]);end;{ TCustomPathLabel }constructor TCustomPathLabel.Create(AnOwner: TComponent);begin  inherited Create(AnOwner);  WordWrap := False;  Align := alTop;  ShowAccelChar := False;  FIndentHorizontal := 5;  FIndentVertical := 1;  FUnixPath := False;  FHotTrack := False;  FColors[0] := clInactiveCaption;  FColors[1] := clActiveCaption;  FColors[2] := clInactiveCaptionText;  FColors[3] := clCaptionText;  FIsEnabled := True;  CalculateAutoHotTrackColors;end;procedure TCustomPathLabel.CMHintShow(var Message: TMessage);begin  with TCMHintShow(Message).HintInfo^ do  begin    HintPos.X := ClientOrigin.X + IndentHorizontal;    HintPos.Y := ClientOrigin.Y + IndentVertical;    if UseHotTrack then Inc(HintPos.Y, Height);  end;end; { CMHintShow }procedure TCustomPathLabel.Click;var  HotPath: string;begin  if FIsEnabled then  begin    HotPath := HotTrackPath;    if HotPath <> '' then    begin      if HotPath = HotTrackMask then DoMaskClick        else      begin        if FShortenedPath <> '' then        begin          // No matter the shortening algo, when the clicked path is the full displayed path, use full original path          if HotPath = FDisplayPath then HotPath := Caption            else          begin            Assert(FShortenedDisplayPath <> '');            Assert((Length(HotPath) >= Length(FShortenedDisplayPath)) or (not ContainsStr(HotPath, '...')));            if Length(HotPath) >= Length(FShortenedDisplayPath) then            begin              Assert(StartsStr(FShortenedDisplayPath, HotPath));              if StartsStr(FShortenedDisplayPath, HotPath) then              begin                Delete(HotPath, 1, Length(FShortenedDisplayPath));                HotPath := FShortenedPath + HotPath;              end;            end;          end;        end;        if EndsStr(GetSeparator, HotPath) and           (HotPath <> GetSeparator) then          SetLength(HotPath, Length(HotPath) - 1);        DoPathClick(HotPath);      end;    end;    if Assigned(FocusControl) then FocusControl.SetFocus;    inherited;  end;end; { Click }procedure TCustomPathLabel.SetUnixPath(AUnixPath: Boolean);begin  if FUnixPath <> AUnixPath then  begin    FUnixPath := AUnixPath;    AdjustBounds;    Invalidate;  end;end;procedure TCustomPathLabel.SetMask(Value: string);begin  if FMask <> Value then  begin    FMask := Value;    AdjustBounds;    Invalidate;  end;end;procedure TCustomPathLabel.SetColors(Index: integer; Value: TColor);begin  Assert(Index in [0..3]);  if FColors[Index] <> Value then  begin    FColors[Index] := Value;    CalculateAutoHotTrackColors;    UpdateStatus;  end;end; { SetColors }// taken from PngImageListEditorconst  WeightR: single = 0.764706;  WeightG: single = 1.52941;  WeightB: single = 0.254902;function ColorDistance(C1, C2: Integer): Single;var  DR, DG, DB: Integer;begin  DR := (C1 and $FF) - (C2 and $FF);  Result := Sqr(DR * WeightR);  DG := (C1 shr 8 and $FF) - (C2 shr 8 and $FF);  Result := Result + Sqr(DG * WeightG);  DB := (C1 shr 16) - (C2 shr 16);  Result := Result + Sqr(DB * WeightB);  Result := Sqrt(Result);end;function GetAdjustedThreshold(BkgndIntensity, Threshold: Single): Single;begin  if BkgndIntensity < 220 then    Result := (2 - BkgndIntensity / 220) * Threshold  else    Result := Threshold;end;function IsContrastEnough(AColor, ABkgndColor: Integer; DoAdjustThreshold: Boolean; Threshold: Single): Boolean;begin  if DoAdjustThreshold then    Threshold := GetAdjustedThreshold(ColorDistance(ABkgndColor, $000000),      Threshold);  Result := ColorDistance(ABkgndColor, AColor) > Threshold;end;procedure AdjustContrast(var AColor: Integer; ABkgndColor: Integer; Threshold: Single);var  X, Y, Z: Single;  R, G, B: Single;  RR, GG, BB: Integer;  I1, I2, S, Q, W: Single;  DoInvert: Boolean;begin  I1 := ColorDistance(AColor, $000000);  I2 := ColorDistance(ABkgndColor, $000000);  Threshold := GetAdjustedThreshold(I2, Threshold);  if I1 > I2 then    DoInvert := I2 < 442 - Threshold  else    DoInvert := I2 < Threshold;  X := (ABkgndColor and $FF) * WeightR;  Y := (ABkgndColor shr 8 and $FF) * WeightG;  Z := (ABkgndColor shr 16) * WeightB;  R := (AColor and $FF) * WeightR;  G := (AColor shr 8 and $FF) * WeightG;  B := (AColor shr 16) * WeightB;  if DoInvert then begin    R := 195 - R;    G := 390 - G;    B := 65 - B;    X := 195 - X;    Y := 390 - Y;    Z := 65 - Z;  end;  S := Sqrt(Sqr(B) + Sqr(G) + Sqr(R));  if S < 0.01 then    S := 0.01;  Q := (R * X + G * Y + B * Z) / S;  X := Q / S * R - X;  Y := Q / S * G - Y;  Z := Q / S * B - Z;  W := Sqrt(Sqr(Threshold) - Sqr(X) - Sqr(Y) - Sqr(Z));  R := (Q - W) * R / S;  G := (Q - W) * G / S;  B := (Q - W) * B / S;  if DoInvert then begin    R := 195 - R;    G := 390 - G;    B := 65 - B;  end;  if R < 0 then    R := 0  else if R > 195 then    R := 195;  if G < 0 then    G := 0  else if G > 390 then    G := 390;  if B < 0 then    B := 0  else if B > 65 then    B := 65;  RR := Trunc(R * (1 / WeightR) + 0.5);  GG := Trunc(G * (1 / WeightG) + 0.5);  BB := Trunc(B * (1 / WeightB) + 0.5);  if RR > $FF then    RR := $FF  else if RR < 0 then    RR := 0;  if GG > $FF then    GG := $FF  else if GG < 0 then    GG := 0;  if BB > $FF then    BB := $FF  else if BB < 0 then    BB := 0;  AColor := (BB and $FF) shl 16 or (GG and $FF) shl 8 or (RR and $FF);end;procedure SetContrast(var Color: TColor; BkgndColor: TColor; Threshold: Integer);var  T: Single;begin  if Color < 0 then    Color := GetSysColor(Color and $FF);  if BkgndColor < 0 then    BkgndColor := GetSysColor(BkgndColor and $FF);  T := Threshold;  if not IsContrastEnough(Color, BkgndColor, True, T) then    AdjustContrast(Integer(Color), BkgndColor, T);end;function TCustomPathLabel.CalculateAutoHotTrackColorComponent(C: Byte; Bright: Boolean): Byte;var  Delta: Byte;begin  Delta := Max(Round(C * 0.3), 80);  if Bright then    Result := Byte(Max(Integer(C) - Delta, 0))  else    Result := Byte(Min(C + Delta, 255));end;function TCustomPathLabel.CalculateAutoHotTrackColor(C: TColor): TColor;var  R, G, B: Byte;  Bright: Boolean;begin  C := ColorToRGB(C);  R := GetRValue(C);  G := GetGValue(C);  B := GetBValue(C);  Bright := (R + G + B) > (256 / 2 * 3);  R := CalculateAutoHotTrackColorComponent(R, Bright);  G := CalculateAutoHotTrackColorComponent(G, Bright);  B := CalculateAutoHotTrackColorComponent(B, Bright);  Result := RGB(R, G, B);end;procedure TCustomPathLabel.CalculateAutoHotTrackColors;begin  FColors[4] := CalculateAutoHotTrackColor(FColors[2]);  SetContrast(FColors[4], FColors[0], 50);  FColors[5] := CalculateAutoHotTrackColor(FColors[3]);  SetContrast(FColors[5], FColors[1], 50);end;procedure TCustomPathLabel.SetIndentHorizontal(AIndent: Integer);begin  if FIndentHorizontal <> AIndent then  begin    FIndentHorizontal := AIndent;    AdjustBounds;    Invalidate;  end;end;procedure TCustomPathLabel.SetIndentVertical(AIndent: Integer);begin  if FIndentVertical <> AIndent then  begin    FIndentVertical := AIndent;    AdjustBounds;    Invalidate;  end;end;procedure TCustomPathLabel.SetAutoSizeVertical(Value: Boolean);begin  if FAutoSizeVertical <> Value then  begin    FAutoSizeVertical := Value;    AdjustBounds;    Invalidate;  end;end;function TCustomPathLabel.GetFocusControl: TWinControl;begin  Result := inherited FocusControl;end;procedure TCustomPathLabel.SetFocusControl(Value: TWinControl);begin  if FocusControl <> Value then  begin    inherited FocusControl := Value;    UpdateStatus;  end;end;function MinimizeStr(Buf: string; Canvas: TCanvas; Width: Integer): string;var  StrWidth: Integer;begin  if Canvas.TextWidth(Buf) > Width then  begin    Buf := Buf + '...';    repeat      Delete(Buf, Length(Buf) - 3, 1);      StrWidth := Canvas.TextWidth(Buf);    until (StrWidth <= Width) or (Length(Buf) = 4);  end;  Result := Buf;end;function ConvertPath(Path: string; S1, S2: Char): string;var  I: Integer;begin  for I := 1 to Length(Path) do  begin    if Path[I] = S1 then Path[I] := S2      else    if Path[I] = S2 then Path[I] := S1;  end;  Result := Path;end;function ConvertPathToWin(Path: string): string;begin  Result := ConvertPath(Path, '/', '\');end;function ConvertPathToUnix(Path: string): string;begin  Result := ConvertPath(Path, '\', '/');end;procedure TCustomPathLabel.DoDrawTextIntern(var Rect: TRect; Flags: Longint; S: string);var  I, I2, L: Integer;  Width: Integer;  WidthMask: Integer;  WidthPath: Integer;  WidthRemain: Integer;  HotTrackOffset: Integer;  HotTrackBottom: Integer;  Separator, Buf, Buf2: string;  Str: string;  HotTrackColor: TColor;  VirtualMask: string;  IsEmptyMask: Boolean;  IsVirtualMask: Boolean;begin  if (Flags and DT_CALCRECT <> 0) and ((S = '') or ShowAccelChar and    (S[1] = '&') and (S[2] = #0)) then S := S + ' ';  if not ShowAccelChar then Flags := Flags or DT_NOPREFIX;  // have to apply DrawTextBiDiModeFlags if we ever deal with dibi  Canvas.Font := Font;  Width := (Rect.Right - Rect.Left);  FDisplayPath := S;  VirtualMask := Mask;  IsVirtualMask := False;  IsEmptyMask := (VirtualMask = '');  if IsEmptyMask and UseHotTrack then  begin    VirtualMask := '*.*';    IsVirtualMask := not FMouseInView;  end;  Separator := GetSeparator;  if VirtualMask <> '' then  begin    if (Length(FDisplayPath) > 0) and (FDisplayPath[Length(FDisplayPath)] <> GetSeparator) then      Buf := Separator;    FDisplayPath := FDisplayPath + Buf;    S := S + Buf;    WidthMask := Canvas.TextWidth(VirtualMask);    if WidthMask > Width div 3 then      WidthPath := Width - (Width div 3)    else      WidthPath := Width - WidthMask;  end    else  begin    WidthMask := 0;    WidthPath := Width;  end;  if FUnixPath then    FDisplayPath := ConvertPathToWin(FDisplayPath);  Buf := FDisplayPath;  WidthRemain := WidthPath;  if EndsStr('\', FDisplayPath) then  begin    Dec(WidthRemain, Canvas.TextWidth('\'));    SetLength(Buf, Length(Buf) - 1);  end;  Buf2 := ExtractFileName(Buf);  FShortenedDisplayPath := '...\';  if WidthRemain < Canvas.TextWidth(FShortenedDisplayPath + Buf2) then  begin    Dec(WidthRemain, Canvas.TextWidth(FShortenedDisplayPath));    Buf2 := MinimizeStr(Buf2, Canvas, WidthRemain);    FShortenedPath := ExtractFilePath(Buf);    Buf := FShortenedDisplayPath + Buf2;  end    else  begin    Buf2 := MinimizeName(Buf, Canvas, WidthRemain);    if Buf2 = Buf then    begin      FShortenedPath := '';      FShortenedDisplayPath := '';    end      else    begin      I := Length(Buf);      repeat        I2 := LastDelimiter('\', Copy(Buf, 1, I - 1));        if I2 = 0 then          Break;        L := Length(Buf) - I2 + 1;        if Copy(Buf, I2, L) = Copy(Buf2, Length(Buf2) - L + 1, L) then          I := I2        else          Break;      until False;      FShortenedPath := Copy(Buf, 1, I);      FShortenedDisplayPath := Copy(Buf2, 1, Length(Buf2) - (Length(Buf) - I));      Buf := Buf2;    end;  end;  if EndsStr('\', FDisplayPath) then  begin    Buf := Buf + '\';  end;  FDisplayPath := Buf;  if FUnixPath then  begin    FDisplayPath := ConvertPathToUnix(FDisplayPath);    FShortenedPath := ConvertPathToUnix(FShortenedPath);    FShortenedDisplayPath := ConvertPathToUnix(FShortenedDisplayPath);  end;  WidthPath := Canvas.TextWidth(FDisplayPath);  if VirtualMask <> '' then  begin    VirtualMask := MinimizeStr(VirtualMask, Canvas, Width - WidthPath);    WidthMask := Canvas.TextWidth(VirtualMask);  end;  Str := FDisplayPath;  if not IsVirtualMask then  begin    Str := Str + VirtualMask;    FDisplayMask := VirtualMask;  end    else  begin    FDisplayMask := '';  end;  ShowHint :=    (FDisplayPath <> S) or    ((not IsEmptyMask) and (FDisplayMask <> Mask)) or    (WidthPath + WidthMask > Width);  if not ShowHint then Hint := ''    else Hint := S + Mask;  if not FIsEnabled then  begin    Canvas.Font.Color := clBtnShadow;    DrawText(Canvas.Handle, PChar(Str), Length(Str), Rect, Flags);  end    else  begin    FDisplayHotTrack := HotTrackPath;    HotTrackColor := TColor(0); // shut up    if FDisplayHotTrack <> '' then    begin      if TrackingActive then      begin        HotTrackColor := FColors[4 + Integer(FIsActive)]      end        else      begin        // We do not have a path label with hot-track and not tracking-active,        // so this is untested branch        Assert(False);        // As if it were active        HotTrackColor := FColors[2 + 1];      end;    end;    if (FDisplayHotTrack <> '') and (FDisplayHotTrack <> HotTrackMask) then    begin      Canvas.Font.Color := HotTrackColor;      DrawText(Canvas.Handle, PChar(FDisplayHotTrack), Length(FDisplayHotTrack), Rect, Flags);      HotTrackOffset := Canvas.TextWidth(FDisplayHotTrack);      Inc(Rect.Left, HotTrackOffset);      Delete(Str, 1, Length(FDisplayHotTrack));      HotTrackBottom := Rect.Bottom;    end      else    begin      HotTrackOffset := 0;      HotTrackBottom := 0;    end;    if TrackingActive then      Canvas.Font.Color := FColors[2 + Integer(FIsActive)]    else      Canvas.Font.Color := clWindowText;    if FDisplayHotTrack = HotTrackMask then    begin      DrawText(Canvas.Handle, PChar(FDisplayPath), Length(FDisplayPath), Rect, Flags);      HotTrackOffset := Canvas.TextWidth(FDisplayPath);      HotTrackBottom := Rect.Bottom;      Inc(Rect.Left, HotTrackOffset);      Canvas.Font.Color := HotTrackColor;      DrawText(Canvas.Handle, PChar(VirtualMask), Length(VirtualMask), Rect, Flags);    end      else    begin      DrawText(Canvas.Handle, PChar(Str), Length(Str), Rect, Flags);    end;    Dec(Rect.Left, HotTrackOffset);    Rect.Bottom := Max(Rect.Bottom, HotTrackBottom);  end;end;procedure TCustomPathLabel.DoDrawText(var Rect: TRect; Flags: Longint);begin  DoDrawTextIntern(Rect, Flags, Caption);end;function TCustomPathLabel.GetSeparator: Char;begin  if FUnixPath then Result := '/'    else Result := '\';end;function TCustomPathLabel.HotTrackPath: string;var  P: TPoint;  DelimPos: Integer;  Len: Integer;  Path: string;begin  Result := '';  if UseHotTrack and FMouseInView and (FDisplayPath <> '') then  begin    P := ScreenToClient(Mouse.CursorPos);    Len := P.X - FIndentHorizontal;    if Len >= 0 then    begin      if Len < Canvas.TextWidth(FDisplayPath) then      begin        Result := '';        Path := FDisplayPath;        repeat          Assert(Path <> '');          if (not FUnixPath) and (Result = '') and IsUncPath(Path) then          begin            Result := ExtractFileDrive(Path);            if Copy(Path, Length(Result) + 1, 1) = GetSeparator then            begin              Result := Result + GetSeparator;            end;            Delete(Path, 1, Length(Result));          end            else          begin            DelimPos := Pos(GetSeparator, Path);            if DelimPos > 0 then            begin              Result := Result + Copy(Path, 1, DelimPos);              Delete(Path, 1, DelimPos);            end              else            begin              Result := Result + Path;              Path := '';            end;          end;        until (Canvas.TextWidth(Result) >= Len) or (Path = '');      end        else      if Len < Canvas.TextWidth(FDisplayPath + FDisplayMask) then      begin        Result := HotTrackMask;      end;    end;  end;end;function TCustomPathLabel.GetColors(Index: Integer): TColor;begin  Assert(Index in [0..5]);  Result := FColors[Index];end; { GetColors }function TCustomPathLabel.UseRightToLeftAlignment: Boolean;begin  // Not sure how to properly deal with RTL atm.  // See also a comment on DrawTextBiDiModeFlags in DoDrawTextIntern  Result := False;end;procedure TCustomPathLabel.Paint;const  Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);  WordWraps: array[Boolean] of Word = (0, DT_WORDBREAK);var  Rect, CalcRect: TRect;  DrawStyle: Longint;begin  with Canvas do  begin    if not Transparent then    begin      Brush.Color := Self.Color;      Brush.Style := bsSolid;      FillRect(ClientRect);    end;    Brush.Style := bsClear;    Rect := ClientRect;    // DoDrawText takes care of BiDi alignments    DrawStyle := DT_EXPANDTABS or WordWraps[WordWrap] or Alignments[Alignment];    // MP    Rect.Left := Rect.Left + FIndentHorizontal;    Rect.Right := Rect.Right - FIndentHorizontal;    Rect.Top := Rect.Top + FIndentVertical;    Rect.Bottom := Rect.Bottom - FIndentVertical;    // Calculate vertical layout    if Layout <> tlTop then    begin      CalcRect := Rect;      DoDrawText(CalcRect, DrawStyle or DT_CALCRECT);      if Layout = tlBottom then OffsetRect(Rect, 0, Height - CalcRect.Bottom)      else OffsetRect(Rect, 0, (Height - CalcRect.Bottom) div 2);    end;    DoDrawText(Rect, DrawStyle);  end;end;procedure TCustomPathLabel.AdjustBounds;const  WordWraps: array[Boolean] of Word = (0, DT_WORDBREAK);var  DC: HDC;  X: Integer;  Rect: TRect;  AAlignment: TAlignment;  AWidth: Integer;  AHeight: Integer;  S: string;begin  if not (csReading in ComponentState) and     (AutoSize or AutoSizeVertical) then  begin    Rect := ClientRect;    DC := GetDC(0);    Canvas.Handle := DC;    S := Caption;    if S = '' then S := 'SomeTextForSizing';    DoDrawTextIntern(Rect, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[WordWrap], S);    Canvas.Handle := 0;    ReleaseDC(0, DC);    X := Left;    AAlignment := Alignment;    if UseRightToLeftAlignment then ChangeBiDiModeAlignment(AAlignment);    if AAlignment = taRightJustify then Inc(X, Width - 2*FIndentHorizontal + Rect.Right);    if AutoSize then AWidth := 2*FIndentHorizontal + Rect.Right      else AWidth := Width;    if AutoSize or AutoSizeVertical then AHeight := 2*FIndentVertical + Rect.Bottom      else AHeight := Height;    SetBounds(X, Top, AWidth, AHeight);  end;end;function TCustomPathLabel.IsActive: Boolean;begin  if csDestroying in ComponentState then Result := False    else  begin    Result := Assigned(FocusControl) and FocusControl.Focused;    if Assigned(OnGetStatus) then      OnGetStatus(Self, Result);  end;end;function TCustomPathLabel.TrackingActive: Boolean;begin  Result := Assigned(FocusControl) or Assigned(OnGetStatus);end;procedure TCustomPathLabel.UpdateStatus;var  NewIsActive: Boolean;  NewIsEnabled: Boolean;  NewColor: TColor;begin  if TrackingActive then  begin    NewIsActive := IsActive;    NewIsEnabled :=      Enabled and      ((not Assigned(FocusControl)) or FocusControl.Enabled);    NewColor := FColors[Integer(NewIsActive)];    if (NewIsActive <> FIsActive) or       (NewIsEnabled <> FIsEnabled) or       (NewColor <> Color) then    begin      FIsActive := NewIsActive;      FIsEnabled := NewIsEnabled;      Color := NewColor;      Invalidate;    end;  end    else  begin    Color := clBtnFace;  end;end; { UpdateStatus }procedure TCustomPathLabel.Notification(AComponent: TComponent;  Operation: TOperation);var  NeedUpdate: Boolean;begin  NeedUpdate :=    (Operation = opRemove) and (AComponent = FocusControl);  inherited;  if NeedUpdate then UpdateStatus;end; { Notification }function TCustomPathLabel.UseHotTrack: Boolean;begin  Result := HotTrack and FIsEnabled;end;procedure TCustomPathLabel.MouseMove(Shift: TShiftState; X: Integer; Y: Integer);begin  inherited;  if FMouseInView and UseHotTrack and (FDisplayHotTrack <> HotTrackPath) then  begin    Invalidate;  end;end;procedure TCustomPathLabel.DoPathClick(Path: string);begin  if Assigned(OnPathClick) then    OnPathClick(Self, Path);end;procedure TCustomPathLabel.DoMaskClick;begin  if Assigned(OnMaskClick) then    OnMaskClick(Self);end;procedure TCustomPathLabel.DblClick;begin  if FIsEnabled then  begin    inherited;  end;end;procedure TCustomPathLabel.DoContextPopup(MousePos: TPoint; var Handled: Boolean);begin  if FIsEnabled then  begin    inherited;  end    else  begin    Handled := True;  end;end;procedure TCustomPathLabel.CMMouseEnter(var Message: TMessage);begin  inherited;  FMouseInView := True;  Invalidate;end;procedure TCustomPathLabel.CMMouseLeave(var Message: TMessage);begin  FMouseInView := False;  Invalidate;  inherited;end;end.
 |