Skip to content

Instantly share code, notes, and snippets.

@idokka
Created April 1, 2023 07:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save idokka/a76dc86e8b590bfc5fdb4c7b51ffae9a to your computer and use it in GitHub Desktop.
Save idokka/a76dc86e8b590bfc5fdb4c7b51ffae9a to your computer and use it in GitHub Desktop.
Almost 20 years ago I already worked deeply in some system functionality of Windows OS, even without the Internet, but still with will to knowledge.
unit CoolHint;
interface
uses
Windows, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, Hook;
type
TCoolHint = class(THintWindow)
bmp: TBitmap;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
public
procedure CreateParams(var Params: TCreateParams); override;
procedure ActivateHint(Rect: TRect; const AHint: string); override;
function CalculateHintRect(Point: TPoint; Hint: string): TRect;
protected
procedure Paint; override;
end;
var ColorArrow: TColor = $0040c0ff;
ColorInformation: TColor = clSkyBlue;
ColorQuestion: TColor = clGreen;
ColorWarning: TColor = clRed;
ColorRadiation: TColor = clGray;
IsFlat: Boolean = false;
function ShowErrorHintAtControl(Expression: boolean;Control: TWinControl;
Hint: String; Duration: Cardinal=3000): boolean;
implementation
uses Types;
var R,ControlRect: TRect;
ContHeight, ContWidth: word;
HintText: string;
Handed: boolean;
C,arrow: char;
cl: TColor;
{$R hint.res}
function ShowErrorHintAtControl(Expression: boolean;Control: TWinControl;
Hint: String; Duration: Cardinal=3000): boolean;
var HintWindow: TCoolHint;
Ticks: Cardinal;
begin
Result:=Expression;
if not Expression
then Exit;
HintWindow:=TCoolHint.Create(Control);
ControlRect:=Control.ClientRect;
Handed:=true;
ControlRect.TopLeft:=Control.ClientToScreen(ControlRect.TopLeft);
ControlRect.BottomRight:=Control.ClientToScreen(ControlRect.BottomRight);
HintWindow.ActivateHint(HintWindow.CalculateHintRect(
Point(ControlRect.Left,ControlRect.Bottom),Hint),Hint);
Handed:=false;
Ticks:=GetTickCount;
while GetTickCount<Ticks+Duration do
Application.ProcessMessages;
HintWindow.Free;
end;
procedure TCoolHint.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style and not ws_Border or CS_DROPSHADOW;
end;
function TCoolHint.CalculateHintRect(Point: TPoint; Hint: string): TRect;
var dr: TRect;
begin
dr:=rect(0,0,Self.Canvas.TextWidth(Hint),0);
DrawText(Self.Canvas.Handle, PChar(Hint),-1, dr, DT_CALCRECT or DT_LEFT or
DT_WORDBREAK or DT_NOPREFIX or DT_RTLREADING);
Inc(dr.Right, 4);
Inc(dr.Bottom, 2);
result:=dr;
end;
constructor TCoolHint.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
with Canvas.Font do
begin
Name := 'Arial';
Style := Style + [fsBold];
Color := clBlack;
end;
bmp := TBitmap.Create;
bmp.Transparent:=true;
Canvas.Brush.Style := bsClear;
end;
destructor TCoolHint.Destroy;
begin
inherited destroy;
bmp.Free;
end;
procedure TCoolHint.Paint;
begin
R:=ClientRect;
with Canvas do
begin
Pen.Color := clBlack;
Brush.Color := clWhite;
Rectangle(0, 0, r.Right, R.Bottom);
case c of
'?': cl:=ColorQuestion;
'!': cl:=ColorWarning;
'i': cl:=ColorInformation;
'r': cl:=ColorRadiation;
else
if IsFlat
then cl:=clBtnFace
else cl:=ColorArrow;
end;
Brush.Color := cl;
Pen.Color := cl;
if (c<>'?') and (c<>'!') and (c<>'i') and (c<>'Ё') and (c<>'ш') and (c<>'r')
then case arrow of
'1','2','3','4': begin
Rectangle(1, 1, 17, R.Bottom-1);
R.Left:=20;
R.Top:=1;
Draw(3, 2+(R.Bottom-16)*
byte((Height>18) and ((arrow='2') or (arrow='4'))), bmp);
end;
'5','6': begin
Rectangle(R.Right-17, 1, R.Right-1, R.Bottom-1);
R.Left:=4;
R.Top:=1;
Draw(R.Right-15, 2+(R.Bottom-16)*
byte((Height>18) and (arrow='5')), bmp);
end;
end else begin
Rectangle(1+(R.Right-18)*byte((arrow='5') or (arrow='6')), 1,
17+(R.Right-18)*byte((arrow='5') or (arrow='6')), R.Bottom-1);
R.Left:=20-17*byte((arrow='5') or (arrow='6'));
R.Top:=1;
Draw(3+(R.Right-17)*byte((arrow='5') or (arrow='6')),
2+(R.Bottom-16)*byte((Height>18) and ((arrow='2')
or (arrow='4') or (arrow='5'))), bmp);
end;
end;
Canvas.Brush.Color := clWhite;
DrawText(Canvas.Handle, PChar(HintText), -1, R, DT_LEFT or DT_NOPREFIX or
DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly);
end;
procedure TCoolHint.ActivateHint(Rect: TRect; const AHint: string);
var cont: TControl;
begin
C:=AHint[1];
arrow:='1';
case c of
'?': bmp.LoadFromResourceName(HInstance,'QUESTION');
'!': bmp.LoadFromResourceName(HInstance,'WARNING');
'i','ш': bmp.LoadFromResourceName(HInstance,'INFORMATION');
'r','Ё': bmp.LoadFromResourceName(HInstance,'RADIATION');
end;
if (c<>'?') and (c<>'!') and (c<>'i') and (c<>'Ё') and (c<>'ш') and (c<>'r')
then HintText:=AHint
else HintText:=copy(AHint,2,255);
Rect.Right:=Rect.Right+17;
if not Handed
then begin
cont:=FindDragTarget(Mouse.CursorPos,true);
ControlRect:=cont.ClientRect;
ControlRect.TopLeft:=cont.ClientToScreen(ControlRect.TopLeft);
ControlRect.BottomRight:=cont.ClientToScreen(ControlRect.BottomRight);
end;
ContHeight:=ControlRect.Bottom - (ControlRect.Top)*byte(not (ControlRect.Top<0));
ContWidth:=ControlRect.Right - (ControlRect.Left)*byte(not (ControlRect.Left<0));
UpdateBoundsRect(Rect);
Rect.Top:=ControlRect.Bottom+2;
Rect.Left:=ControlRect.Left;
Rect.Right:=Rect.Left+Width;
Rect.Bottom:=Rect.Top+Height;
if (Rect.Bottom > Screen.ActiveForm.Height+Screen.ActiveForm.Top)
and (Height<Screen.ActiveForm.Height) then begin
Rect.Top := Rect.Top - Height - ContHeight -3;
arrow:='2';
end;
if ((Rect.Right > Screen.ActiveForm.Left+Screen.ActiveForm.Width)
and (Rect.Left-Width-2>Screen.ActiveForm.Left)
and (Width<Screen.ActiveForm.Width))
or (Rect.Right>Screen.Width) then begin
Rect.Left := Rect.Left - Width -2;
if arrow='1' then arrow:='6';
if arrow='2' then arrow:='5';
end;
if Width < ContWidth then begin
if arrow='2' then arrow:='4';
if arrow='1' then arrow:='3';
end;
if (c<>'?') and (c<>'!') and (c<>'i') and (c<>'Ё') and (c<>'ш') and (c<>'r')
then bmp.LoadFromResourceName(HInstance,'ARROW'+arrow);
SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, Width, Height,
SWP_SHOWWINDOW or SWP_NOACTIVATE);
Repaint;
Invalidate;
end;
initialization
HintWindowClass := TCoolHint;
Handed:=false;
// Application.HintPause:=1500;
// Application.HintHidePause:=3000;
// Application.HintShortPause:=100;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment