git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jvcl@19 7f62d464-2af8-f54e-996c-e91b33f51cbe
613 lines
16 KiB
ObjectPascal
613 lines
16 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvScrollText.PAS, released on 2001-02-28.
|
|
|
|
The Initial Developer of the Original Code is Sébastien Buysse [sbuysse att buypin dott com]
|
|
Portions created by Sébastien Buysse are Copyright (C) 2001 Sébastien Buysse.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s): Michael Beck [mbeck att bigfoot dott com]
|
|
Michael Freislich [mikef att korbi dott net]
|
|
Gianpiero Caretti [gpcaretti+delphi att gmail dott com]
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.delphi-jedi.org
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvScrollText.pas 12576 2009-10-25 17:49:40Z ahuser $
|
|
|
|
unit JvScrollText;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
SysUtils, Classes, Windows, Messages, Graphics, Controls, Forms, StdCtrls,
|
|
JvStaticText, JvTypes, JvImageDrawThread, JvComponent;
|
|
|
|
type
|
|
TJvScrollTextDirection = (drFromLeft, drFromRight, drFromTop, drFromBottom); // also in JvMoveableBevel, JvAppearingLabel
|
|
TJvScrollText = class(TJvCustomControl)
|
|
private
|
|
FText: TJvStaticText;
|
|
FTimerTag: Integer;
|
|
FActive: Boolean;
|
|
FDelay: Cardinal;
|
|
FPixel: Integer;
|
|
FCurrPos: Integer;
|
|
FSelectable: Boolean;
|
|
FScrollDirection: TJvScrollTextDirection;
|
|
FScrollSaved: Integer;
|
|
FItems: TStringList;
|
|
FDefaultAppHintPause: Cardinal;
|
|
FScroll: TJvImageDrawThread;
|
|
FFont: TFont;
|
|
FStartY: Integer;
|
|
FDown: Boolean;
|
|
FOldMouseMovePt: TPoint;
|
|
FOnScrollEnd: TNotifyEvent;
|
|
function GetItems: TStrings;
|
|
procedure SetItems(const Value: TStrings);
|
|
procedure OnScroll(Sender: TObject);
|
|
procedure SetActive(const Value: Boolean);
|
|
procedure SetDelay(const Value: Cardinal);
|
|
procedure SetPixel(const Value: Integer);
|
|
procedure SetScrollDirection(const Value: TJvScrollTextDirection);
|
|
procedure CalculateText(Sender: TObject);
|
|
function GetAlignment: TAlignment;
|
|
procedure SetAlignment(const Value: TAlignment);
|
|
function GetColor: TColor;
|
|
procedure SetColor(const Value: TColor);
|
|
procedure FontChange(Sender: TObject);
|
|
procedure SetFont(const Value: TFont);
|
|
procedure TextMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
procedure TextMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
|
procedure TextMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
procedure TextMouseClick(Sender: TObject);
|
|
procedure TextMouseDblClick(Sender: TObject);
|
|
function GetWordWrap: Boolean;
|
|
procedure SetWordWrap(const Value: Boolean);
|
|
procedure DoScrollEnd;
|
|
protected
|
|
procedure Loaded; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
published
|
|
property Alignment: TAlignment read GetAlignment write SetAlignment;
|
|
property Items: TStrings read GetItems write SetItems;
|
|
property Active: Boolean read FActive write SetActive default False;
|
|
property Delay: Cardinal read FDelay write SetDelay default 50;
|
|
property ScrollPixels: Integer read FPixel write SetPixel default 1;
|
|
property ScrollDirection: TJvScrollTextDirection read FScrollDirection write SetScrollDirection default drFromBottom;
|
|
property BackgroundColor: TColor read GetColor write SetColor;
|
|
property Font: TFont read FFont write SetFont;
|
|
procedure Pause;
|
|
procedure Unpause;
|
|
procedure Reset;
|
|
property Align;
|
|
property ShowHint;
|
|
property ParentShowHint;
|
|
property Height default 150;
|
|
property Width default 200;
|
|
{$IFDEF JVCLThemesEnabled}
|
|
property ParentBackground default True;
|
|
{$ENDIF JVCLThemesEnabled}
|
|
property WordWrap: Boolean read GetWordWrap write SetWordWrap;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnClick;
|
|
property OnDblClick;
|
|
|
|
// Triggered when the scroll has reached its end and is about to restart from its source
|
|
property OnScrollEnd: TNotifyEvent read FOnScrollEnd write FOnScrollEnd;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_39/run/JvScrollText.pas $';
|
|
Revision: '$Revision: 12576 $';
|
|
Date: '$Date: 2009-10-25 18:49:40 +0100 (dim., 25 oct. 2009) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
JvJVCLUtils, JvThemes, JvResources;
|
|
|
|
constructor TJvScrollText.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
IncludeThemeStyle(Self, [csParentBackground]);
|
|
Width := 200;
|
|
Height := 150;
|
|
FActive := False;
|
|
FDelay := 50;
|
|
FPixel := 1;
|
|
FCurrPos := 0;
|
|
FSelectable := True;
|
|
FScrollDirection := drFromBottom;
|
|
FItems := TStringList.Create;
|
|
|
|
FText := TJvStaticText.Create(Self);
|
|
FText.Parent := Self;
|
|
FText.Width := Width;
|
|
FText.Height := Height;
|
|
FText.BorderStyle := sbsNone;
|
|
FText.TabStop := False;
|
|
FText.Enabled := FSelectable;
|
|
FText.AutoSize := False;
|
|
FText.OnMouseDown := TextMouseDown;
|
|
FText.OnMouseMove := TextMouseMove;
|
|
FText.OnMouseUp := TextMouseUp;
|
|
FText.OnClick := TextMouseClick;
|
|
FText.OnDblClick := TextMouseDblClick;
|
|
|
|
FFont := TFont.Create;
|
|
FFont.Assign(FText.Font);
|
|
FFont.OnChange := FontChange;
|
|
|
|
FTimerTag := 0;
|
|
FDown := False;
|
|
FDefaultAppHintPause := Application.HintPause;
|
|
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
FScroll := TJvImageDrawThread.Create(True);
|
|
FScroll.FreeOnTerminate := False;
|
|
FScroll.Delay := FDelay;
|
|
FScroll.OnDraw := OnScroll;
|
|
end;
|
|
end;
|
|
|
|
destructor TJvScrollText.Destroy;
|
|
begin
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
FScroll.OnDraw := nil;
|
|
FScroll.Free;
|
|
end;
|
|
Application.HintPause := FDefaultAppHintPause;
|
|
FItems.Free;
|
|
FText.Free;
|
|
FFont.OnChange := nil;
|
|
FFont.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvScrollText.DoScrollEnd;
|
|
begin
|
|
if Assigned(OnScrollEnd) then
|
|
OnScrollEnd(Self);
|
|
end;
|
|
|
|
procedure TJvScrollText.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
if csDesigning in ComponentState then
|
|
SetItems(FItems);
|
|
end;
|
|
|
|
procedure TJvScrollText.SetFont(const Value: TFont);
|
|
var
|
|
Al: TAlignment;
|
|
begin
|
|
FFont.Assign(Value);
|
|
FText.Font.Assign(FFont);
|
|
CalculateText(Self);
|
|
Al := FText.Alignment;
|
|
if FText.Alignment = taCenter then
|
|
FText.Alignment := taLeftJustify
|
|
else
|
|
FText.Alignment := taCenter;
|
|
FText.Alignment := Al;
|
|
end;
|
|
|
|
procedure TJvScrollText.TextMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
P.X := X;
|
|
P.Y := Y;
|
|
P := FText.ClientToScreen(P);
|
|
|
|
if ScrollDirection in [drFromTop, drFromBottom] then
|
|
FStartY := P.Y
|
|
else
|
|
FStartY := P.X;
|
|
if not (csDesigning in ComponentState) then
|
|
FScroll.OnDraw := nil;
|
|
FDown := True;
|
|
|
|
if Assigned(OnMouseDown) then
|
|
begin
|
|
P := ScreenToClient(P);
|
|
OnMouseDown(Self, Button, Shift, P.X, P.Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvScrollText.TextMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
NewY: Integer;
|
|
P: TPoint;
|
|
begin
|
|
P.X := X;
|
|
P.Y := Y;
|
|
P := FText.ClientToScreen(P);
|
|
|
|
if FDown then
|
|
begin
|
|
//if NewY>0, going up, NewY<0, going down
|
|
|
|
if ScrollDirection in [drFromTop, drFromBottom] then
|
|
begin
|
|
NewY := FStartY - P.Y;
|
|
FStartY := P.Y;
|
|
FCurrPos := FCurrPos - NewY;
|
|
|
|
if FCurrPos < -FText.Height then
|
|
FCurrPos := Height
|
|
else
|
|
if FCurrPos > Height then
|
|
FCurrPos := -FText.Height;
|
|
|
|
FText.Top := FCurrPos;
|
|
end
|
|
else
|
|
begin
|
|
NewY := FStartY - P.X;
|
|
FStartY := P.X;
|
|
FCurrPos := FCurrPos - NewY;
|
|
|
|
if FCurrPos < -FText.Width then
|
|
FCurrPos := Width
|
|
else
|
|
if FCurrPos > Width then
|
|
FCurrPos := -FText.Width;
|
|
|
|
FText.Left := FCurrPos;
|
|
end;
|
|
end;
|
|
|
|
if Assigned(OnMouseMove) then
|
|
begin
|
|
P := ScreenToClient(P);
|
|
if (P.X <> FOldMouseMovePt.X) or (P.Y <> FOldMouseMovePt.Y) then
|
|
begin
|
|
FOldMouseMovePt := P;
|
|
OnMouseMove(Self, Shift, P.X, P.Y);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvScrollText.TextMouseUp(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
if not (csDesigning in ComponentState) then
|
|
FScroll.OnDraw := OnScroll;
|
|
FDown := False;
|
|
|
|
if Assigned(OnMouseUp) then
|
|
begin
|
|
P.X := X;
|
|
P.Y := Y;
|
|
P := Self.ScreenToClient( FText.ClientToScreen(P) );
|
|
OnMouseUp(Self, Button, Shift, P.X, P.Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvScrollText.TextMouseClick(Sender: TObject);
|
|
begin
|
|
// forward the event of the inner FText to the same event of the scroller
|
|
if Assigned(OnClick) then
|
|
OnClick(Self);
|
|
end;
|
|
|
|
procedure TJvScrollText.TextMouseDblClick(Sender: TObject);
|
|
begin
|
|
// forward the double click event of the inner FText to the same event of the scroller
|
|
if Assigned(OnDblClick) then
|
|
OnDblClick(Self);
|
|
end;
|
|
|
|
procedure TJvScrollText.OnScroll(Sender: TObject);
|
|
var
|
|
Offset: Integer;
|
|
ScrollEnd: Boolean;
|
|
begin
|
|
// Must exit because we are "Synchronized" and our parent is already
|
|
// partly destroyed. If we did not exit, we would get an AV.
|
|
if csDestroying in ComponentState then
|
|
Exit;
|
|
|
|
//tag=1 pause
|
|
if FTimerTag = 1 then
|
|
begin
|
|
if FScrollSaved <= 0 then
|
|
begin
|
|
SetActive(False);
|
|
FTimerTag := 0;
|
|
Exit;
|
|
end
|
|
else
|
|
begin
|
|
Offset := FScrollSaved;
|
|
Dec(FScrollSaved);
|
|
end;
|
|
end
|
|
else
|
|
if FTimerTag = 2 then
|
|
begin
|
|
if FScrollSaved >= FPixel then
|
|
begin
|
|
FTimerTag := 0;
|
|
Offset := FPixel;
|
|
end
|
|
else
|
|
begin
|
|
Offset := FScrollSaved;
|
|
Inc(FScrollSaved);
|
|
end;
|
|
end
|
|
else
|
|
Offset := FPixel;
|
|
|
|
//tag=2 unpause
|
|
//FScrollDirection
|
|
|
|
ScrollEnd := False;
|
|
case ScrollDirection of
|
|
drFromTop:
|
|
begin
|
|
if FCurrPos > Height then
|
|
begin
|
|
FCurrPos := -FText.Height;
|
|
ScrollEnd := True;
|
|
end
|
|
else
|
|
FCurrPos := FCurrPos + Offset;
|
|
FText.Top := FCurrPos;
|
|
end;
|
|
drFromRight:
|
|
begin
|
|
if - FCurrPos > FText.Width then
|
|
begin
|
|
FCurrPos := Width;
|
|
ScrollEnd := True;
|
|
end
|
|
else
|
|
FCurrPos := FCurrPos - Offset;
|
|
FText.Left := FCurrPos;
|
|
end;
|
|
drFromLeft:
|
|
begin
|
|
if FCurrPos > Width then
|
|
begin
|
|
FCurrPos := -FText.Width;
|
|
ScrollEnd := True;
|
|
end
|
|
else
|
|
FCurrPos := FCurrPos + Offset;
|
|
FText.Left := FCurrPos;
|
|
end;
|
|
drFromBottom:
|
|
begin
|
|
if - FCurrPos > FText.Height then
|
|
begin
|
|
FCurrPos := Height;
|
|
ScrollEnd := True;
|
|
end
|
|
else
|
|
FCurrPos := FCurrPos - Offset;
|
|
FText.Top := FCurrPos;
|
|
end;
|
|
end;
|
|
|
|
// As OnScroll is called from the draw thread's context, we
|
|
// must synchronize the event call
|
|
if ScrollEnd then
|
|
FScroll.Synchronize(DoScrollEnd);
|
|
end;
|
|
|
|
procedure TJvScrollText.Pause;
|
|
begin
|
|
if FActive then
|
|
begin
|
|
FScrollSaved := FPixel;
|
|
FTimerTag := 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetActive(const Value: Boolean);
|
|
begin
|
|
SetItems(FItems);
|
|
FActive := Value;
|
|
if not (csDesigning in ComponentState) then
|
|
FScroll.Paused := not Value;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetDelay(const Value: Cardinal);
|
|
begin
|
|
if Value > FDefaultAppHintPause then
|
|
Application.HintPause := FDefaultAppHintPause
|
|
else
|
|
if Value > 10 then
|
|
Application.HintPause := Value - 10
|
|
else
|
|
Application.HintPause := Abs(Value - 1);
|
|
FDelay := Value;
|
|
if not (csDesigning in ComponentState) then
|
|
FScroll.Delay := Value;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetScrollDirection(const Value: TJvScrollTextDirection);
|
|
begin
|
|
FScrollDirection := Value;
|
|
FText.Left := 0;
|
|
FText.Top := 0;
|
|
Reset;
|
|
end;
|
|
|
|
procedure TJvScrollText.CalculateText(Sender: TObject);
|
|
var
|
|
I, J, K, W: Integer;
|
|
Ts: TStringList;
|
|
DesktopCanvas: TCanvas;
|
|
begin
|
|
// calculate the Size of the memo (vertically)
|
|
DesktopCanvas := TCanvas.Create;
|
|
try
|
|
DesktopCanvas.Handle := GetDC(HWND_DESKTOP);
|
|
DesktopCanvas.Font.Assign(FText.Font);
|
|
J := 0;
|
|
K := 0;
|
|
Ts := TStringList.Create;
|
|
try
|
|
Ts.Text := FText.Caption;
|
|
for I := 0 to Ts.Count - 1 do
|
|
try
|
|
W := DesktopCanvas.TextWidth(Ts[I]);
|
|
if K < W then
|
|
K := W;
|
|
if Ts[I] <> '' then
|
|
J := J + DesktopCanvas.TextHeight(Ts[I]) * ((W div Width) + 1)
|
|
else
|
|
J := J + CanvasMaxTextHeight(DesktopCanvas);
|
|
except
|
|
end;
|
|
if J <= 0 then
|
|
J := Height;
|
|
FText.Height := J;
|
|
if K <= 0 then
|
|
K := Width;
|
|
FText.Width := K;
|
|
DesktopCanvas.Handle := 0;
|
|
ReleaseDC(HWND_DESKTOP, Handle);
|
|
finally
|
|
Ts.Free;
|
|
end;
|
|
finally
|
|
DesktopCanvas.Free;
|
|
end;
|
|
Reset;
|
|
end;
|
|
|
|
function TJvScrollText.GetItems: TStrings;
|
|
begin
|
|
Result := FItems;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetItems(const Value: TStrings);
|
|
begin
|
|
FItems.Text := Value.Text;
|
|
FText.Caption := Value.Text;
|
|
CalculateText(Self);
|
|
end;
|
|
|
|
function TJvScrollText.GetColor: TColor;
|
|
begin
|
|
Result := FText.Color;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetColor(const Value: TColor);
|
|
begin
|
|
FText.Color := Value;
|
|
Color := Value;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TJvScrollText.FontChange(Sender: TObject);
|
|
var
|
|
Al: TAlignment;
|
|
begin
|
|
FText.Font.Assign(FFont);
|
|
CalculateText(Self);
|
|
Al := FText.Alignment;
|
|
if FText.Alignment = taCenter then
|
|
FText.Alignment := taLeftJustify
|
|
else
|
|
FText.Alignment := taCenter;
|
|
FText.Alignment := Al;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetPixel(const Value: Integer);
|
|
begin
|
|
FPixel := Value;
|
|
end;
|
|
|
|
procedure TJvScrollText.Reset;
|
|
begin
|
|
case ScrollDirection of
|
|
drFromTop:
|
|
FCurrPos := -FText.Height;
|
|
drFromLeft:
|
|
FCurrPos := -FText.Width;
|
|
drFromRight:
|
|
FCurrPos := Width;
|
|
drFromBottom:
|
|
FCurrPos := Height;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvScrollText.Unpause;
|
|
begin
|
|
if not FActive then
|
|
begin
|
|
FScrollSaved := 0;
|
|
FTimerTag := 2;
|
|
SetActive(True);
|
|
end;
|
|
end;
|
|
|
|
function TJvScrollText.GetAlignment: TAlignment;
|
|
begin
|
|
Result := FText.Alignment;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetAlignment(const Value: TAlignment);
|
|
begin
|
|
FText.Alignment := Value;
|
|
end;
|
|
|
|
function TJvScrollText.GetWordWrap: Boolean;
|
|
begin
|
|
Result := FText.WordWrap;
|
|
end;
|
|
|
|
procedure TJvScrollText.SetWordWrap(const Value: Boolean);
|
|
begin
|
|
FText.WordWrap := Value;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|