Created
April 1, 2023 07:34
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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