给你组件源码
unit Wolfhint;
interface
uses
SysUtils, Windows, Messages, Classes, Graphics, Controls,
Forms, Dialogs;
type
THintDirection=(hdUpRight,hdUpLeft,hdDownRight,hdDownLeft);
TOnSelectHintDirection=procedure(HintControl:TControl;var HintDirection:THintDirection) of object;
TWolfHint = class(TComponent)
private
{ Private declarations }
FHintDirection:THintDirection;
FHintColor:TColor;
FHintShadowColor:TColor;
FHintFont:TFont;
FHintPauseTime:Integer;
FOnSelectHintDirection:TOnSelectHintDirection;
procedure SetHintDirection(Value:THintDirection);
procedure SetHintColor(Value:TColor);
procedure SetHintShadowColor(Value:TColor);
procedure SetHintFont(Value:TFont);
procedure CMFontChanged(var Message:TMessage); message CM_FONTCHANGED;
procedure SetHintPauseTime(Value:Integer);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
procedure Loaded;override;
procedure SetNewHintFont;
published
{ Published declarations }
property HintDirection:THintDirection read FHintDirection write SetHintDirection default hdUpRight;
property HintColor:TColor read FHintColor write SetHintColor default clYellow;
property HintShadowColor:TColor read FHintShadowColor write SetHintShadowColor default clPurple;
property HintFont:TFont read FHintFont write SetHintFont;
property HintPauseTime:Integer read FHintPauseTime write SetHintPauseTime default 600;
property OnSelectHintDirection:TOnSelectHintDirection read FOnSelectHintDirection write FOnSelectHintDirection;
end;
TNewHint = class(THintWindow)
private
{ Private declarations }
FDanHint:TWolfHint;
FHintDirection:THintDirection;
procedure SelectProperHintDirection(ARect:TRect);
procedure CheckUpRight(Spot:TPoint);
procedure CheckUpLeft(Spot:TPoint);
procedure CheckDownRight(Spot:TPoint);
procedure CheckDownLeft(Spot:TPoint);
function FindDanHint:TWolfHint;
//function FindCursorControl:TControl;
protected
{ Protected declarations }
procedure Paint;override;
procedure CreateParams(var Params: TCreateParams);override;
public
{ Public declarations }
constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
procedure ActivateHint(Rect: TRect; const AHint: string);override;
property HintDirection:THintDirection read FHintDirection write FHintDirection default hdUpRight;
published
{ Published declarations }
end;
procedure Register;
implementation
const
SHADOW_WIDTH=6;
N_PIXELS=5;
var
MemBmp:TBitmap;
UpRect,DownRect:TRect;
SelectHintDirection:THintDirection;
ShowPos:TPoint;
procedure Register;
begin
RegisterComponents('WolfCom', [TWolfHint]);
end;
procedure TWolfHint.SetNewHintFont;
var
I:Integer;
begin
for I:=0 to Application.ComponentCount-1 do
if Application.Components is TNewHint then
begin
TNewHint(Application.Components).Canvas.Font.Assign(FHintFont);
Exit;
end;
end;
constructor TWolfHint.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
FHintDirection:=hdUpRight;
FHintColor:=clYellow;
FHintShadowColor:=clPurple;
FHintPauseTime:=600;
Application.HintPause:=FHintPauseTime;
FHintFont:=TFont.Create;
FHintFont.Name:='MS Sans Serif';
FHintFont.Size:=12;
FHintFont.Color:=clBlue;
FHintFont.Pitch:=fpDefault;
FHintFont.Style:=FHintFont.Style+[fsBold,fsItalic];
if not (csDesigning in ComponentState) then
begin
HintWindowClass:=TNewHint;
Application.ShowHint:=not Application.ShowHint;
Application.ShowHint:=not Application.ShowHint;
SetNewHintFont;
end;
end;
destructor TWolfHint.Destroy;
begin
FHintFont.Free;
inherited Destroy;
end;
procedure TWolfHint.Loaded;
begin
//因为HINT窗口在原先的窗口类中是编译期形成的,所以应当在控件加入的组件列表时
//将原来的HINT窗口替换掉,换成新的HINT窗口类
if not (csDesigning in ComponentState) then
begin
inherited Loaded;
HintWindowClass:=TNewHint;
Application.ShowHint:=not Application.ShowHint;
Application.ShowHint:=not Application.ShowHint;
SetNewHintFont;
end;
end;
procedure TWolfHint.SetHintDirection(Value:THintDirection);
begin
FHintDirection:=Value;
end;
procedure TWolfHint.SetHintColor(Value:TColor);
begin
FHintColor:=Value;
end;
procedure TWolfHint.SetHintShadowColor(Value:TColor);
begin
FHintShadowColor:=Value;
end;
procedure TWolfHint.SetHintFont(Value:TFont);
begin
FHintFont.Assign(Value);
Application.ShowHint:=not Application.ShowHint;
Application.ShowHint:=not Application.ShowHint;
SetNewHintFont;
end;
procedure TWolfHint.CMFontChanged(var Message:TMessage);
begin
inherited;
//如果字体改变,重复替换过程
Application.ShowHint:=not Application.ShowHint;
Application.ShowHint:=not Application.ShowHint;
SetNewHintFont;
end;
procedure TWolfHint.SetHintPauseTime(Value:Integer);
begin
if (Value<>FHintPauseTime) then
begin
FHintPauseTime:=Value;
Application.HintPause:=Value;
end;
end;
function TNewHint.FindDanHint:TWolfHint;
var
I:Integer;
begin
Result:=nil;
for I:=0 to Application.MainForm.ComponentCount-1 do
if Application.MainForm.Components is TWolfHint then
begin
Result:=TWolfHint(Application.MainForm.Components);
Exit;
end;
end;
constructor TNewHint.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
ControlStyle:=ControlStyle-[csOpaque];
with Canvas do
begin
Brush.Style:=bsClear;
Brush.Color:=clBackground;
Application.HintColor:=clBackground;
end;
FHintDirection:=hdUpRight;
end;
destructor TNewHint.Destroy;
begin
inherited Destroy;
end;
procedure TNewHint.CreateParams(var Params: TCreateParams);
begin
//修改原提示窗口的窗体风格
inherited CreateParams(Params);
with Params do
begin
Style := Style-WS_BORDER;
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
end;
end;
procedure TNewHint.Paint;
var
R: TRect;
CCaption: array[0..255] of Char;
FillRegion,ShadowRgn:HRgn;
AP:array[0..2] of TPoint;
SP:array[0..2] of TPoint;
X,Y:Integer;
AddNum:Integer;
begin
//开始画提示窗口的样式
R := ClientRect;
Inc(R.Left,5+3);
Inc(R.Top,3);
AddNum:=0;
if FHintDirection>=hdDownRight then AddNum:=15;
Inc(R.Top,AddNum);
case HintDirection of
hdUpRight:begin
AP[0]:=Point(10,Height-15);
AP[1]:=Point(20,Height-15);
AP[2]:=Point(0,Height);
SP[0]:=Point(12,Height-15);
SP[1]:=Point(25,Height-15);
SP[2]:=Point(12,Height);
end;
hdUpLeft:begin
AP[0]:=Point(Width-SHADOW_WIDTH-20,Height-15);
AP[1]:=Point(Width-SHADOW_WIDTH-10,Height-15);
AP[2]:=Point(Width-SHADOW_WIDTH,Height);
SP[0]:=Point(Width-SHADOW_WIDTH-27,Height-15);
SP[1]:=Point(Width-SHADOW_WIDTH-5,Height-15);
SP[2]:=Point(Width-SHADOW_WIDTH,Height);
end;
hdDownRight:begin
AP[0]:=Point(10,15);
AP[1]:=Point(20,15);
AP[2]:=Point(0,0);
SP[0]:=Point(12,Height-15);
SP[1]:=Point(25,Height-15);
SP[2]:=Point(12,Height);
end;
hdDownLeft:begin
AP[0]:=Point(Width-SHADOW_WIDTH-20,15);
AP[1]:=Point(Width-SHADOW_WIDTH-10,15);
AP[2]:=Point(Width-SHADOW_WIDTH,0);
SP[0]:=Point(12,Height-15);
SP[1]:=Point(25,Height-15);
SP[2]:=Point(12,Height);
end;
end;
if (FHintDirection<=hdUpLeft) then
begin
ShadowRgn:=CreateRoundRectRgn(0+10,0+8,Width,Height-9,8,8);
for X:=Width-SHADOW_WIDTH-8 to Width do
for Y:=8 to Height-14 do
begin
if (Odd(X)=Odd(Y)) and PtInRegion(ShadowRgn,X,Y) then
MemBmp.Canvas.Pixels[X,Y]:=FDanHint.HintShadowColor;
end;
for X:=10 to Width do
for Y:=Height-14 to Height-9 do
begin
if (Odd(X)=Odd(Y)) and PtInRegion(ShadowRgn,X,Y) then
MemBmp.Canvas.Pixels[X,Y]:=FDanHint.HintShadowColor;
end;
end
else
begin
ShadowRgn:=CreateRoundRectRgn(0+10,0+8+15,Width,Height-2,8,8);
for X:=Width-SHADOW_WIDTH-8 to Width do
for Y:=23 to Height-8 do
begin
if (Odd(X)=Odd(Y)) and PtInRegion(ShadowRgn,X,Y) then
MemBmp.Canvas.Pixels[X,Y]:=FDanHint.HintShadowColor;
end;
for X:=10 to Width do
for Y:=Height-8 to Height-2 do
begin
if (Odd(X)=Odd(Y)) and PtInRegion(ShadowRgn,X,Y) then
MemBmp.Canvas.Pixels[X,Y]:=FDanHint.HintShadowColor;
end;
end;
DeleteObject(ShadowRgn);
if (HintDirection<=hdUpLeft) then
begin
ShadowRgn:=CreatePolygonRgn(SP,3,WINDING);
for X:=SP[0].X to SP[1].X do
for Y:=SP[0].Y to SP[2].Y do
begin
if (Odd(X)=Odd(Y)) and PtInRegion(ShadowRgn,X,Y) then
MemBmp.Canvas.Pixels[X,Y]:=FDanHint.HintShadowColor;
end;
DeleteObject(ShadowRgn);
end;
MemBmp.Canvas.Pen.Color:=clBlack;
MemBmp.Canvas.Pen.Style:=psSolid;
MemBmp.Canvas.Brush.Color:=FDanHint.HintColor;
MemBmp.Canvas.Brush.Style:=bsSolid;
if (FHintDirection<=hdUpLeft) then
MemBmp.Canvas.RoundRect(0,0,Width-SHADOW_WIDTH,Height-14,9,9)
else
MemBmp.Canvas.RoundRect(0,0+AddNum,Width-SHADOW_WIDTH,Height-14+6,9,9);
MemBmp.Canvas.Pen.Color:=FDanHint.HintColor;
MemBmp.Canvas.MoveTo(AP[0].X,AP[0].Y);
MemBmp.Canvas.LineTo(AP[1].X,AP[1].Y);
MemBmp.Canvas.Pen.Color:=clBlack;
FillRegion:=CreatePolygonRgn(AP,3,WINDING);
FillRgn(MemBmp.Canvas.Handle,FillRegion,MemBmp.Canvas.Brush.Handle);
DeleteObject(FillRegion);
MemBmp.Canvas.LineTo(AP[2].X,AP[2].Y);
MemBmp.Canvas.LineTo(AP[0].X,AP[0].Y);
SetBkMode(MemBmp.Canvas.Handle,TRANSPARENT);
MemBmp.Canvas.Font.Assign(FDanHint.HintFont);
DrawText(MemBmp.Canvas.Handle, StrPCopy(CCaption, Caption), -1, R,
DT_LEFT or DT_NOPREFIX or DT_WORDBREAK);
Canvas.CopyMode:=cmSrcCopy;
Canvas.CopyRect(ClientRect,MemBmp.Canvas,ClientRect);
MemBmp.Free;
end;
procedure TNewHint.CheckUpLeft(Spot:TPoint);
var
Width,Height:Integer;
begin
Dec(Spot.Y,N_PIXELS);
Width:=UpRect.Right-UpRect.Left;
Height:=UpRect.Bottom-UpRect.Top;
SelectHintDirection:=hdUpLeft;
if (Spot.X+SHADOW_WIDTH-Width)<0 then
begin
Inc(Spot.Y,N_PIXELS);
CheckUpRight(Spot);
Exit;
end;
if (Spot.Y-Height)<0 then
begin
Inc(Spot.Y,N_PIXELS);
CheckDownLeft(Spot);
Exit;
end;
ShowPos.X:=Spot.X+SHADOW_WIDTH-Width;
ShowPos.Y:=Spot.Y-Height;
end;
procedure TNewHint.CheckUpRight(Spot:TPoint);
var
Width,Height:Integer;
begin
Dec(Spot.Y,N_PIXELS);
Width:=UpRect.Right-UpRect.Left;
Height:=UpRect.Bottom-UpRect.Top;
SelectHintDirection:=hdUpRight;
if (Spot.X+Width)>Screen.Width then
begin
Inc(Spot.Y,N_PIXELS);
CheckUpLeft(Spot);
Exit;
end;
if (Spot.Y-Height)<0 then
begin
Inc(Spot.Y,N_PIXELS);
CheckDownRight(Spot);
Exit;
end;
ShowPos.X:=Spot.X;
ShowPos.Y:=Spot.Y-Height;
end;
procedure TNewHint.CheckDownRight(Spot:TPoint);
var
Width,Height:Integer;
begin
Inc(Spot.Y,N_PIXELS*3);
Width:=DownRect.Right-DownRect.Left;
Height:=DownRect.Bottom-DownRect.Top;
SelectHintDirection:=hdDownRight;
if (Spot.X+Width)>Screen.Width then
begin
Dec(Spot.Y,N_PIXELS*3);
CheckDownLeft(Spot);
Exit;
end;
if (Spot.Y+Height)>Screen.Height then
begin
Dec(Spot.Y,N_PIXELS*3);
CheckUpRight(Spot);
Exit;
end;
ShowPos.X:=Spot.X;
ShowPos.Y:=Spot.Y;
end;
procedure TNewHint.CheckDownLeft(Spot:TPoint);
var
Width,Height:Integer;
begin
Inc(Spot.Y,N_PIXELS*3);
Width:=DownRect.Right-DownRect.Left;
Height:=DownRect.Bottom-DownRect.Top;
SelectHintDirection:=hdDownLeft;
if (Spot.X+SHADOW_WIDTH-Width)<0 then
begin
Dec(Spot.Y,N_PIXELS*3);
CheckDownRight(Spot);
Exit;
end;
if (Spot.Y+Height)>Screen.Height then
begin
Dec(Spot.Y,N_PIXELS*3);
CheckUpLeft(Spot);
Exit;
end;
ShowPos.X:=Spot.X+SHADOW_WIDTH-Width;
ShowPos.Y:=Spot.Y;
end;
//function TNewHint.FindCursorControl:TControl;
//begin
// {ControlAtPos}
//end;
procedure TNewHint.SelectProperHintDirection(ARect:TRect);
var
Spot:TPoint;
OldHintDirection,SendHintDirection:THintDirection;
HintControl:TControl;
begin
GetCursorPos(Spot);
HintCOntrol:=FindDragTarget(Spot,True);
Inc(ARect.Right,10+SHADOW_WIDTH);
Inc(ARect.Bottom,20);
UpRect:=ARect;
Inc(ARect.Bottom,9);
DownRect:=ARect;
OldHintDirection:=FDanHint.HintDirection;
SendHintDirection:=FDanHint.HintDirection;
if Assigned(FDanHint.FOnSelectHintDirection) then
begin
FDanHint.FOnSelectHintDirection(HintControl,SendHintDirection);
FDanHint.HintDirection:=SendHintDirection;
end;
case FDanHint.HintDirection of
hdUpRight:CheckUpRight(Spot);
hdUpLeft:CheckUpLeft(Spot);
hdDownRight:CheckDownRight(Spot);
hdDownLeft:CheckDownLeft(Spot);
end;
FDanHint.HintDirection:=OldHintDirection;
end;
procedure TNewHint.ActivateHint(Rect: TRect; const AHint: string);
var
ScreenDC:HDC;
LeftTop:TPoint;
tmpWidth,tmpHeight:Integer;
begin
MemBmp:=TBitmap.Create;
Caption := AHint;
FDanHint:=FindDanHint;
SelectProperHintDirection(Rect);
HintDirection:=SelectHintDirection;
Inc(Rect.Right,10+SHADOW_WIDTH);
Inc(Rect.Bottom,20);
if (FHintDirection>=hdDownRight) then Inc(Rect.Bottom,9);
tmpWidth:=Rect.Right-Rect.Left;
tmpHeight:=Rect.Bottom-Rect.Top;
Rect.Left:=ShowPos.X;
Rect.Top:=ShowPos.Y;
Rect.Right:=Rect.Left+tmpWidth;
Rect.Bottom:=Rect.Top+tmpHeight;
BoundsRect := Rect;
MemBmp.Width:=Width;
MemBmp.Height:=Height;
ScreenDC:=CreateDC('DISPLAY',nil,nil,nil);
{此处如果换为ScreenDC:=GetDC(0)可能更好}
LeftTop.X:=0;
LeftTop.Y:=0;
LeftTop:=ClientToScreen(LeftTop);
BitBlt(MemBmp.Canvas.Handle,0,0,Width,Height,ScreenDC,
LeftTop.X,LeftTop.Y,SRCCOPY);
SetWindowPos(Handle, HWND_TOPMOST, ShowPos.X, ShowPos.Y, 0,
0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
BitBlt(Canvas.Handle,0,0,Width,Height,MemBmp.Canvas.Handle,
0,0,SRCCOPY);
DeleteDC(ScreenDC);
end;
initialization
end.