home *** CD-ROM | disk | FTP | other *** search
- {$I DFS.INC} { Standard defines for all Delphi Free Stuff components }
-
- {------------------------------------------------------------------------------}
- { TdfsEllipsisPanel v1.19 }
- {------------------------------------------------------------------------------}
- { A panel that can shorten the caption text, replacing it with '...' when }
- { it does not fit the available space. Also provided is a generic function }
- { that will "ellipsify" a string. This function can be used to produce }
- { other components like TdfsEllipsisPanel, such as TdfsEllipsisLabel. }
- { }
- { Copyright 2000-2001, Brad Stowers. All Rights Reserved. }
- { }
- { Copyright: }
- { All Delphi Free Stuff (hereafter "DFS") source code is copyrighted by }
- { Bradley D. Stowers (hereafter "author"), and shall remain the exclusive }
- { property of the author. }
- { }
- { Distribution Rights: }
- { You are granted a non-exlusive, royalty-free right to produce and distribute }
- { compiled binary files (executables, DLLs, etc.) that are built with any of }
- { the DFS source code unless specifically stated otherwise. }
- { You are further granted permission to redistribute any of the DFS source }
- { code in source code form, provided that the original archive as found on the }
- { DFS web site (http://www.delphifreestuff.com) is distributed unmodified. For }
- { example, if you create a descendant of TDFSColorButton, you must include in }
- { the distribution package the colorbtn.zip file in the exact form that you }
- { downloaded it from http://www.delphifreestuff.com/mine/files/colorbtn.zip. }
- { }
- { Restrictions: }
- { Without the express written consent of the author, you may not: }
- { * Distribute modified versions of any DFS source code by itself. You must }
- { include the original archive as you found it at the DFS site. }
- { * Sell or lease any portion of DFS source code. You are, of course, free }
- { to sell any of your own original code that works with, enhances, etc. }
- { DFS source code. }
- { * Distribute DFS source code for profit. }
- { }
- { Warranty: }
- { There is absolutely no warranty of any kind whatsoever with any of the DFS }
- { source code (hereafter "software"). The software is provided to you "AS-IS", }
- { and all risks and losses associated with it's use are assumed by you. In no }
- { event shall the author of the softare, Bradley D. Stowers, be held }
- { accountable for any damages or losses that may occur from use or misuse of }
- { the software. }
- { }
- { Support: }
- { Support is provided via the DFS Support Forum, which is a web-based message }
- { system. You can find it at http://www.delphifreestuff.com/discus/ }
- { All DFS source code is provided free of charge. As such, I can not guarantee }
- { any support whatsoever. While I do try to answer all questions that I }
- { receive, and address all problems that are reported to me, you must }
- { understand that I simply can not guarantee that this will always be so. }
- { }
- { Clarifications: }
- { If you need any further information, please feel free to contact me directly.}
- { This agreement can be found online at my site in the "Miscellaneous" section.}
- {------------------------------------------------------------------------------}
- { The lateset version of my components are always available on the web at: }
- { http://www.delphifreestuff.com/ }
- { See ElpsPanl.txt for notes, known issues, and revision history. }
- {------------------------------------------------------------------------------}
- { Date last modified: June 27, 2001 }
- {------------------------------------------------------------------------------}
-
- unit ElpsPanl;
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, ExtCtrls, Menus;
-
- const
- { This shuts up C++Builder 3 about the redefiniton being different. There
- seems to be no equivalent in C1. Sorry. }
- {$IFDEF DFS_CPPB_3_UP}
- {$EXTERNALSYM DFS_COMPONENT_VERSION}
- {$ENDIF}
- DFS_COMPONENT_VERSION = 'TdfsEllipsisPanel v1.19';
-
- type
- TAutoHintOption = (ahEnabled, ahWindowOnly, ahOnEllipsis);
- { ahEnabled - Enable auto hint (set hint when caption too big. }
- { ahWindowOnly - Don't generate applicatoin events, only the popup hint. }
- { Basically, it sticks an '|' on the end of the hint string. }
- { ahOnEllipsis - When Caption too big, Hint is set to Caption. When Caption }
- { fits, Hint is set to last value assigned to it, either in }
- { IDE or code. For example, you set Hint = "My hint" and the }
- { panel has to use "..." when it displayes the caption }
- { "Some Text String". The hint would pop up as "Some Text }
- { String". You then resize and the entire caption can be }
- { displayed in the panel. The hint would then be "My hint". }
-
- TAutoHintOptions = set of TAutoHintOption;
-
- const
- DEF_AUTOHINTOPTIONS = [ahEnabled, ahWindowOnly, ahOnEllipsis];
-
- type
- TdfsEllipsisPanel = class(TCustomPanel)
- private
- FAutoHintOptions: TAutoHintOptions;
- FIsPath: boolean;
- FCaption: string;
- FSaveHint: string;
-
- procedure SetAutoHintOptions(Val: TAutoHintOptions);
- procedure SetIsPath(Val: boolean);
- procedure SetCaption(const Val: string);
- function GetCaption: string;
-
- procedure WMSize(var Msg: TWMSize); message WM_SIZE;
- procedure CMFontChanged(var Msg: TMessage); message CM_FONTCHANGED;
- protected
- procedure UpdatePanelText;
- procedure UpdateHintText;
- procedure Loaded; override;
- function GetVersion: string;
- procedure SetVersion(const Val: string);
- public
- constructor Create(AOwner: TComponent); override;
- {$IFDEF DFS_COMPILER_4_UP}
- property DockManager;
- {$ENDIF}
- published
- property Version: string
- read GetVersion
- write SetVersion
- stored FALSE;
- property AutoHintOptoins: TAutoHintOptions
- read FAutoHintOptions
- write SetAutoHintOptions
- default DEF_AUTOHINTOPTIONS;
- property IsPath: boolean
- read FIsPath
- write SetIsPath
- default FALSE;
- property Caption: string
- read GetCaption
- write SetCaption;
-
- { Publish inherited stuff }
- property Align;
- property Alignment;
- property BevelInner;
- property BevelOuter;
- property BevelWidth;
- property BorderWidth;
- property BorderStyle;
- property DragCursor;
- property DragMode;
- property Enabled;
- property Color;
- property Ctl3D;
- property Font;
- property Locked;
- property ParentColor;
- property ParentCtl3D;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint default TRUE;
- property TabOrder;
- property TabStop;
- property Visible;
- property OnClick;
- property OnDblClick;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnResize;
- {$IFDEF DFS_COMPILER_2_UP}
- property OnStartDrag;
- {$ENDIF}
- {$IFDEF DFS_COMPILER_3_UP}
- property FullRepaint;
- {$ENDIF}
- {$IFDEF DFS_COMPILER_4_UP}
- property Anchors;
- property AutoSize;
- property BiDiMode;
- property Constraints;
- property UseDockManager default True;
- property DockSite;
- property DragKind;
- property ParentBiDiMode;
- property OnCanResize;
- property OnConstrainedResize;
- property OnDockDrop;
- property OnDockOver;
- property OnEndDock;
- property OnGetSiteInfo;
- property OnStartDock;
- property OnUnDock;
- {$ENDIF}
- {$IFDEF DFS_COMPILER_5_UP}
- property OnContextPopup;
- {$ENDIF}
- {$IFDEF DFS_COMPILER_7_UP}
- Make sure to add any new properties introduced in TPanel.
- {$ENDIF}
- end;
-
- function EllipsifyText(AsPath: boolean; const Text: string;
- const Canvas: TCanvas; MaxWidth: integer): string;
-
-
- implementation
-
-
- {$IFNDEF DFS_WIN32}
- procedure SetLength(var s: string; NewLen: byte);
- begin
- S[0] := chr(NewLen);
- end;
- {$ENDIF}
-
- function EllipsifyText(AsPath: boolean; const Text: string;
- const Canvas: TCanvas; MaxWidth: integer): string;
- {$IFDEF DFS_WIN32}
- var
- TempPChar: PChar;
- TempRect: TRect;
- Params: UINT;
- begin
- // Alocate mem for PChar
- GetMem(TempPChar, Length(Text)+1);
- try
- // Copy Text into PChar
- TempPChar := StrPCopy(TempPChar, Text);
- // Create Rectangle to Store PChar
- TempRect := Rect(0,0, MaxWidth, High(Integer));
- // Set Params depending wether it's a path or not
- if AsPath then
- Params := DT_PATH_ELLIPSIS
- else
- Params := DT_END_ELLIPSIS;
- // Tell it to Modify the PChar, and do not draw to the canvas
- Params := Params + DT_MODIFYSTRING + DT_CALCRECT;
- // Ellipsify the string based on availble space to draw in
- DrawTextEx(Canvas.Handle, TempPChar, -1, TempRect, Params, nil);
- // Copy the modified PChar into the result
- Result := StrPas(TempPChar);
- finally
- // Free Memory from PChar
- FreeMem(TempPChar, Length(Text)+1);
- end;
- {$ELSE}
- procedure CutFirstDirectory(var S: string);
- var
- Root: Boolean;
- P: Integer;
- begin
- if S = '' then exit;
- if S = '\' then
- S := ''
- else begin
- if S[1] = '\' then begin
- Root := True;
- Delete(S, 1, 1);
- end else
- Root := False;
- if S[1] = '.' then
- Delete(S, 1, 4);
- P := Pos('\',S);
- if P <> 0 then begin
- Delete(S, 1, P);
- S := '...\' + S;
- end else
- S := '';
- if Root then
- S := '\' + S;
- end;
- end;
-
- function MinimizeName(const Filename: string; const Canvas: TCanvas;
- MaxLen: Integer): string;
- var
- Drive: string;
- Dir: string;
- Name: string;
- begin
- Result := FileName;
- Dir := ExtractFilePath(Result);
- Name := ExtractFileName(Result);
-
- if (Length(Dir) >= 2) and (Dir[2] = ':') then begin
- Drive := Copy(Dir, 1, 2);
- Delete(Dir, 1, 2);
- end else
- Drive := '';
- while ((Dir <> '') or (Drive <> '')) and (Canvas.TextWidth(Result) > MaxLen) do begin
- if Dir = '\...\' then begin
- Drive := '';
- Dir := '...\';
- end else if Dir = '' then
- Drive := ''
- else
- CutFirstDirectory(Dir);
- Result := Drive + Dir + Name;
- end;
- end;
- var
- Temp: string;
- AvgChar: integer;
- TLen,
- Index: integer;
- Metrics: TTextMetric;
- begin
- try
- if AsPath then begin
- Result := MinimizeName(Text, Canvas, MaxWidth);
- end else begin
- Temp := Text;
- if (Temp <> '') and (Canvas.TextWidth(Temp) > MaxWidth) then begin
- GetTextMetrics(Canvas.Handle, Metrics);
- AvgChar := Metrics.tmAveCharWidth;
- if (AvgChar * 3) < MaxWidth then begin
- Index := (MaxWidth div AvgChar) - 1;
- Temp := Copy(Text, 1, Index);
- if Canvas.TextWidth(Temp + '...') > MaxWidth then begin
- repeat
- dec(Index);
- SetLength(Temp, Index);
- until (Canvas.TextWidth(Temp + '...') < MaxWidth) or (Index < 1);
- { delete chars }
- end else begin
- TLen := Length(Text);
- repeat
- inc(Index);
- Temp := Copy(Text, 1, Index);
- until (Canvas.TextWidth(Temp + '...') > MaxWidth) or (Index >= TLen);
- SetLength(Temp, Index-1);
- end;
- Temp := Temp + '...';
- end else
- Temp := '.';
- end;
- Result := Temp;
- end;
- except
- Result := '';
- end;
- {$ENDIF}
- end;
-
-
- constructor TdfsEllipsisPanel.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FAutoHintOptions := DEF_AUTOHINTOPTIONS;
- ShowHint := TRUE;
- FIsPath := FALSE;
- FCaption := '';
- FSaveHint := '';
- end;
-
- procedure TdfsEllipsisPanel.Loaded;
- begin
- inherited Loaded;
- FSaveHint := Hint;
- end;
-
- procedure TdfsEllipsisPanel.UpdatePanelText;
- begin
- if HandleAllocated then begin
- { Make sure the right font has been selected. }
- Canvas.Font.Assign(Font);
- inherited Caption := EllipsifyText(FIsPath, FCaption, Canvas,
- ClientWidth-(BevelWidth*2)-BorderWidth*2);
- UpdateHintText;
- end;
- end;
-
- procedure TdfsEllipsisPanel.UpdateHintText;
- function LastChar(const Str: string): char;
- begin
- if Length(Str) > 0 then
- Result := Str[Length(Str)]
- else
- Result := #0;
- end;
- begin
- if ahEnabled in FAutoHintOptions then begin
- if ahOnEllipsis in FAutoHintOptions then begin
- if (Length(inherited Caption) > 2) and
- (Copy(inherited Caption, Length(inherited Caption)-2, 3) = '...') then
- Hint := FCaption
- else
- Hint := FSaveHint;
- end else
- Hint := FCaption;
-
- {.$DEFINE WANT-TO-SEE-A-DELPHI-2-BUG}
- {$IFDEF WANT-TO-SEE-A-DELPHI-2-BUG}
- if ahWindowOnly in FAutoHintOptions then begin
- (* This code causes internal error c3254! It is the second part of the "if" statement,
- but only if there is some code inside the begin...end.
- vvvvvvvvvvvvvvvvvvvvvvvvvvv *)
- if (Length(Hint) > 0) and (Hint[Length(Hint)] <> '|') then
- Hint := Hint + '|';
- end else begin
- if (Length(Hint) > 0) and (Hint[Length(Hint)] = '|') then
- Hint := Copy(Hint, 1, Length(Hint)-1);
- end;
- {$ELSE}
- if ahWindowOnly in FAutoHintOptions then begin
- if LastChar(Hint) <> '|' then
- Hint := Hint + '|';
- end else begin
- if LastChar(Hint) = '|' then
- Hint := Copy(Hint, 1, Length(Hint)-1);
- end;
- {$ENDIF}
-
- end else begin
- Hint := FSaveHint;
- end;
- end; { This is where you will see the C3254 error message. Caused on line 290 }
-
- procedure TdfsEllipsisPanel.SetAutoHintOptions(Val: TAutoHintOptions);
- begin
- if FAutoHintOptions <> Val then begin
- FAutoHintOptions := Val;
- UpdateHintText;
- end;
- end;
-
- procedure TdfsEllipsisPanel.SetIsPath(Val: boolean);
- begin
- if Val = FIsPath then exit;
- FIsPath := Val;
- UpdatePanelText;
- end;
-
- procedure TdfsEllipsisPanel.SetCaption(const Val: string);
- begin
- if Val = FCaption then exit;
- FCaption := Val;
- UpdatePanelText;
- end;
-
- function TdfsEllipsisPanel.GetCaption: string;
- begin
- Result := FCaption;
- end;
-
- procedure TdfsEllipsisPanel.WMSize(var Msg: TWMSize);
- begin
- inherited;
- UpdatePanelText;
- end;
-
- procedure TdfsEllipsisPanel.CMFontChanged(var Msg: TMessage);
- begin
- inherited;
- Refresh;
- UpdatePanelText;
- end;
-
- function TdfsEllipsisPanel.GetVersion: string;
- begin
- Result := DFS_COMPONENT_VERSION;
- end;
-
- procedure TdfsEllipsisPanel.SetVersion(const Val: string);
- begin
- { empty write method, just needed to get it to show up in Object Inspector }
- end;
-
- end.
-
-