I want to write a little component which shows me on which control mouse is currently over. When it spot the choosen control it should fire the messaage (for example).
But I don't know what should I do to form to get the position of the mouse all the time. This is what I've got:
TMouseOverControl = class(TComponent)
private
fActive: Boolean;
fControl: TWinControl;
public
constructor Create(AOwner: TComponent); override;
procedure Loaded; override;
procedure SpotIt;
published
property Active: Boolean read fActive write fActive;
property Control开发者_JAVA百科: TWinControl read fControl write fControl; // when mouse is over this control show me the message
end;
constructor TMouseOverControl.Create(AOwner: TComponent);
begin
// nothing interesting here
// don't have control property here - so overrided the loaded method
inherited;
end;
procedure TMouseOverControl.Loaded;
begin
inherited;
// TForm(Owner).Mo.... := SpotIt....
// what should i do to make it work?
end;
procedure TMouseOverControl.SpotIt;
begin
// IsMouseOverControl is easy to implement
// http://delphi.about.com/od/delphitips2010/qt/is-some-delphi-tcontrol-under-the-mouse.htm
if IsMouseOverControl(Control) then
ShowMessage('Yep, U got it!');
end;
Any ideas?
Well you only need to check/update when the mouse moves. So you could track WM_MOUSEMOVE
messages by using TApplicationEvents
.
// Edit: these variables are intended to be private fields of the component class
var
FAppEvents: TApplicationEvents;
FFoundControl: Boolean;
FCurrentControl: TWinControl;
procedure TMyComponent.HandleAppMessage(var Msg: tagMSG; var Handled: Boolean);
var
Control: TWinControl;
begin
if (Msg.message = WM_MOUSEMOVE) and not FFoundControl then
begin
Control:= FindControl(Msg.hwnd);
if Assigned(Control) then
begin
FCurrentControl:= Control;
FFoundControl:= True;
end;
end else
if (Msg.message = WM_MOUSELEAVE) then
FFoundControl:= False;
end;
procedure TMyComponent.FormCreate(Sender: TObject);
begin
FAppEvents:= TApplicationEvents.Create(nil);
FAppEvents.OnMessage:= HandleAppMessage;
end;
This could certainly be optimized, e.g. by also checking for WM_MOUSELEAVE so you don't have to FindControl
on every mouse move. This solution works for TWinControls
and descendants.
Edit: Made use of WM_MOUSELEAVE.
How about something like this:
// rectangle where you are interested to check if the mouse is into..
targetRect := Rect(0, 0, ImageZoom.Width, ImageZoom.Height);
// find out where the mouse is..
mousePosition := Point(0, 0);
GetCursorPos(mousePosition);
// find out if the point.. from screen to client.. is inside that rectangle
isMouseInside := (PtInRect(targetRect, ScreenToClient(mousePosition)));
精彩评论