Componentes.Terceros.jvcl/official/3.39/run/JvScrollText.pas
2010-01-18 16:55:50 +00:00

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.