{ *************************************************************************** * * * This source is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This code is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * A copy of the GNU General Public License is available on the World * * Wide Web at . You can also * * obtain it by writing to the Free Software Foundation, * * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * *************************************************************************** } unit ScrollingText; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls, LCLIntf,AboutScrolltextunit; const C_TEXTFILENAME = 'scrolling.txt'; C_TEXTRESOURCENAME = 'scrolltext'; //Note: LResouces unit needed C_VERSION = '1.0.0.0'; type TTextSource = (stStringlist, stTextfile, stResource); TScrollingText = class(TAboutScrollText) private FActive: boolean; FActiveLine: integer; //the line over which the mouse hovers FBuffer: TBitmap; FEndLine: integer; FLineHeight: integer; FLines: TStrings; FNumLines: integer; FOffset: integer; FStartLine: integer; FStepSize: integer; FTimer: TTimer; FFont: TFont; FBackColor: TColor; fTextFileName: string; fResourceName: string; fVersionString: string; fTextSource: TTextSource; function ActiveLineIsURL: boolean; procedure DoTimer(Sender: TObject); procedure SetActive(const AValue: boolean); procedure Init; procedure DrawScrollingText(Sender: TObject); procedure SetLines(AValue: TStrings); procedure SetFont(AValue: TFont); protected procedure DoOnChangeBounds; override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override; procedure MouseMove(Shift: TShiftState; X, Y: integer); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published // Can be set in design mode. Note URL links are inactive in design mode property Active: boolean read FActive write SetActive; // Inherited property property Align; // Inherited property property Anchors; // Inherited property property BiDiMode; // Inherited property property Constraints; // Inherited property property Enabled; // Inherited property property Borderspacing; // Can be set in design or runtime mode. (TextSource=stStringlist) property Lines: TStrings read FLines write SetLines; // Sets the background color of the window property BackColor: TColor read fBackColor write fBackColor default clWindow; // Sets the font properties of the scrolling text property Font: TFont read fFont write SetFont; // Source of the text to display. // If TextSource=stTextfile 'scrolling.txt' should be in the deployed app folder // if TextSource=stResource be sure to add LResources to your uses clause property TextSource: TTextSource read fTextSource write fTextSource default stStringlist; // Read-only property to remind you of the correct file name property TextFileName: string read fTextFileName; // Read-only property to remind you of the correct resource name property TextResourceName: string read fResourceName; // Version number of this component property Version: string read fVersionString; end; procedure Register; implementation procedure Register; begin {$I scrollingtext_icon.lrs} RegisterComponents('Additional', [TScrollingText]); end; procedure TScrollingText.SetFont(AValue: TFont); begin fFont.Assign(AValue); end; procedure TScrollingText.SetLines(AValue: TStrings); begin fLines.Assign(AValue); end; procedure TScrollingText.SetActive(const AValue: boolean); begin FActive := AValue; if FActive then begin Init; FOffset := FBuffer.Height; // Start at the bottom of the window end; FTimer.Enabled := Active; end; procedure TScrollingText.Init; var r: TLResource; begin FBuffer.Width := Width; FBuffer.Height := Height; FLineHeight := FBuffer.Canvas.TextHeight('X'); FNumLines := FBuffer.Height div FLineHeight; if FOffset = -1 then FOffset := FBuffer.Height; with FBuffer.Canvas do begin Brush.Color := fBackColor; Brush.Style := bsSolid; FillRect(0, 0, Width, Height); end; if (fTextSource = stTextfile) then if FileExists('scrolling.txt') then begin fLines.Clear; fLines.LoadFromFile('scrolling.txt'); end else begin fLines.Clear; fLines.Add('The file ''' + C_TEXTFILENAME + ''' is missing.'); fLines.Add('It should be in the same folder as your application'); end; if (fTextSource = stResource) then // Load text from resource string begin r := LazarusResources.Find(fResourceName); if r = nil then raise Exception.CreateFmt('Resource ''%s'' is missing',[fResourceName]) else begin fLines.Clear; fLines.Add(r.Value); end; end; // Are there any lines in the Stringlist? if (fLines.Count = 0) then begin fLines.Add('This is the ScrollingText scrolling window.'); fLines.Add(' '); fLines.Add('This default text is showing because you either:'); fLines.Add(' '); fLines.Add('1) Haven''t set any text in the Lines property. or'); fLines.Add('2) TextSource is set to stTextfile and the file'); fLines.Add('''' + C_TEXTFILENAME + ''' is empty.'); fLines.Add(' '); fLines.Add('Note that URL links such as'); fLines.Add('http://wiki.lazarus.freepascal.org/Main_Page'); fLines.Add('mailto:bill_gates@microsoft.com'); fLines.Add('are clickable by the user'); fLines.Add(' '); fLines.Add('TScrollingText is released under the GPL license (See About)'); fLines.Add('Code is modified from the Lazarus ''AboutFrm'' code'); fLines.Add(' '); fLines.Add('The standalone visual component TScrollingText is available at:'); fLines.Add('http://www.charcodelvalle.com/scrollingtext/scrollingtext_component.zip'); fLines.Add(' '); fLines.Add('June 2014'); end; end; procedure TScrollingText.DrawScrollingText(Sender: TObject); begin if Active then Canvas.Draw(0,0, FBuffer); end; procedure TScrollingText.DoTimer(Sender: TObject); var w: integer; s: string; i: integer; begin if not Active then Exit; Dec(FOffset, FStepSize); if FOffSet < 0 then FStartLine := -FOffset div FLineHeight else FStartLine := 0; FEndLine := FStartLine + FNumLines + 1; if FEndLine > FLines.Count - 1 then FEndLine := FLines.Count - 1; FBuffer.Canvas.FillRect(Rect(0, 0, FBuffer.Width, FBuffer.Height)); for i := FEndLine downto FStartLine do begin s := Trim(FLines[i]); //reset buffer font FBuffer.Canvas.Font := fFont; FBuffer.Canvas.Font.Style := []; FBuffer.Canvas.Font.Color := clBlack; //skip empty lines if Length(s) > 0 then begin //check for bold format token if s[1] = '#' then begin s := copy(s, 2, Length(s) - 1); FBuffer.Canvas.Font.Style := [fsBold]; end else begin //check for url if (Pos('http://', s) = 1) OR (Pos('mailto:', s) = 1) then begin if i = FActiveLine then begin FBuffer.Canvas.Font.Style := [fsUnderline]; FBuffer.Canvas.Font.Color := clRed; end else FBuffer.Canvas.Font.Color := clBlue; end; end; w := FBuffer.Canvas.TextWidth(s); FBuffer.Canvas.TextOut((FBuffer.Width - w) div 2, FOffset + i * FLineHeight, s); end; end; //start showing the list from the start if FStartLine > FLines.Count - 1 then FOffset := FBuffer.Height; Invalidate; end; function TScrollingText.ActiveLineIsURL: boolean; begin if (FActiveLine > 0) and (FActiveLine < FLines.Count) then Result := (Pos('http://', FLines[FActiveLine]) = 1) OR (Pos('mailto:', FLines[FActiveLine]) = 1) else Result := False; end; procedure TScrollingText.DoOnChangeBounds; begin inherited DoOnChangeBounds; Init; end; procedure TScrollingText.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer); begin inherited MouseDown(Button, Shift, X, Y); if ActiveLineIsURL then OpenURL(FLines[FActiveLine]); end; procedure TScrollingText.MouseMove(Shift: TShiftState; X, Y: integer); begin inherited MouseMove(Shift, X, Y); //calculate what line is clicked from the mouse position FActiveLine := (Y - FOffset) div FLineHeight; Cursor := crDefault; if (FActiveLine >= 0) and (FActiveLine < FLines.Count) and ActiveLineIsURL then Cursor := crHandPoint; end; constructor TScrollingText.Create(AOwner: TComponent); begin inherited Create(AOwner); ControlStyle := ControlStyle + [csOpaque]; OnPaint := @DrawScrollingText; FLines := TStringList.Create; FTimer := TTimer.Create(nil); FTimer.OnTimer := @DoTimer; FTimer.Interval := 30; FBuffer := TBitmap.Create; FFont := TFont.Create; FFont.Size := 10; fBackColor := clWindow; FStepSize := 1; FStartLine := 0; FOffset := -1; Width := 100; Height := 100; fTextFileName := C_TEXTFILENAME; fResourceName := C_TEXTRESOURCENAME; fVersionString := C_VERSION; fTextSource := stStringlist; SendToBack; // About dialog AboutBoxComponentName:='ScrollingText component'; AboutBoxWidth:=400; // AboutBoxHeight (integer) AboutBoxDescription:='Component that shows a scrolling window.' + LineEnding + 'Use Lines property to set text and Active=True' + LineEnding + 'to use the component'; AboutBoxBackgroundColor:=clWindow; AboutBoxFontName:='Arial'; AboutBoxFontSize:=10; AboutBoxVersion:=C_VERSION; AboutBoxAuthorname:='Gordon Bamber'; AboutBoxOrganisation:='Public Domain'; AboutBoxAuthorEmail:='minesadorada@charcodelvalle.com'; AboutBoxLicenseType:='LGPL'; end; destructor TScrollingText.Destroy; begin FLines.Free; FTimer.Free; FBuffer.Free; FFont.Free; inherited Destroy; end; end.