unit popWindow;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Graphics, Controls, ExtCtrls;
type
{ TPopNotifier }
TPopNotifier = class(TForm)
private
FMargin: integer;
FTimer: TTimer;
FTimeout: integer;
FTimeoutStarted: boolean;
FStrArray: array of string;
FLineHeight: integer;
FMaxHite: integer;
FTimerStart: QWord;
FDrawStrings: boolean;
procedure popShow(Sender: TObject);
procedure timerOnTimer(Sender: TObject);
public
constructor {%H-}Create(aStrings: array of const; aMargin: integer=20; aTimeout: integer=100);
procedure popKeydown(Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState);
procedure popMouseEnter(Sender: TObject);
procedure popPaint(Sender: TObject);
end;
procedure WindowPopup(aStrings: array of const; aBackColor: TColor=clSkyBlue;
aMargin: integer=20; aTimeout: integer=100);
implementation
procedure WindowPopup(aStrings: array of const; aBackColor: TColor;
aMargin: integer; aTimeout: integer);
var
dlg: TPopNotifier;
begin
Assert(High(aStrings) > -1,'WindowPopup() has no data');
dlg:=TPopNotifier.Create(aStrings, aMargin, aTimeout);
try
dlg.Color:=aBackColor;
dlg.ShowModal;
finally
dlg.Free;
end;
end;
{ TPopNotifier }
procedure TPopNotifier.popShow(Sender: TObject);
var
i, len, lenMax, incr, maxIdx, doubleMargin, tp, lf, wd: integer;
begin
lenMax:=0;
maxIdx:=High(FStrArray);
for i:=0 to maxIdx do begin
len:=Canvas.TextWidth(FStrArray[i]);
if (len > lenMax) then
lenMax:=len;
end;
doubleMargin:=FMargin shl 1;
incr:=doubleMargin + FMargin;
Inc(lenMax, incr);
FLineHeight:=Canvas.TextHeight(FStrArray[0]);
FMaxHite:=FLineHeight*Length(FStrArray) + doubleMargin;
tp:=Screen.Height - FMargin;
wd:=lenMax-FMargin;
lf:=Screen.Width - lenMax;
SetBounds(lf, tp, wd, 0);
FTimer.Enabled:=True;
FTimerStart:=GetTickCount64;
end;
procedure TPopNotifier.timerOnTimer(Sender: TObject);
var
d: QWord;
h, t: integer;
begin
d:=(GetTickCount64 - FTimerStart) div 2;
case FTimeoutStarted of
False: begin
h:=Height + d;
t:=Top - d;
if (h < FMaxHite) then
SetBounds(Left, t, Width, h);
FTimer.Enabled:=h < FMaxHite;
if not FTimer.Enabled then begin
FDrawStrings:=True;
Invalidate;
FTimeoutStarted:=True;
FTimer.Enabled:=True;
end;
FTimerStart:=GetTickCount64;
end;
True: begin
Dec(FTimeout);
if (FTimeout < 0) then begin
FTimer.Enabled:=False;
ModalResult:=mrOK;
end;
end;
end;
end;
constructor TPopNotifier.Create(aStrings: array of const; aMargin: integer;
aTimeout: integer);
var
i, maxIdx: integer;
begin
inherited CreateNew(nil);
FTimer:=TTimer.Create(Self);
FTimer.Interval:=20; // optimum value is hardware dependent
FTimer.OnTimer:=@timerOnTimer;
if (aTimeout < 100) then
aTimeout:=100;
FTimeout:=aTimeout;
OnPaint:=@popPaint;
OnKeyDown:=@popKeydown;
OnMouseEnter:=@popMouseEnter;
OnShow:=@popShow;
FMargin:=aMargin;
BorderStyle:=bsNone;
maxIdx:=High(aStrings);
SetLength(FStrArray, maxIdx+1);
for i:=0 to maxIdx do
case aStrings[i].VType of
vtString: FStrArray[i]:=aStrings[i].VString^;
vtAnsiString: FStrArray[i]:=AnsiString(aStrings[i].VAnsiString);
end;
end;
procedure TPopNotifier.popKeydown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
ModalResult:=mrOK;
end;
procedure TPopNotifier.popMouseEnter(Sender: TObject);
begin
ModalResult:=mrOK;
end;
procedure TPopNotifier.popPaint(Sender: TObject);
var
i: integer;
begin
if FDrawStrings then begin
for i:=0 to High(FStrArray) do
Canvas.TextOut(FMargin, i*FLineHeight + FMargin, FStrArray[i]);
end;
end;
end.