问题
I am trying to track and log what a user does in my app. One way to help is to have a list of what buttons and menu etc they click as they use the program. Then if the program crashes for any reason I have a log of the exact steps they took to try and reproduce the issue.
So I drop an ApplicationEvents component on the main form and then under OnMessage I use...
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;var Handled: Boolean);
var Target: TControl;
Point: TPoint;
begin
Handled := FALSE;
if (Msg.Message = WM_LBUTTONDOWN) then
begin
GetCursorPos(Point);
Target := FindDragTarget(Point,True);
if Assigned(Target) then
begin
AddLogText('CLICKED '+(Target).owner.name+'.'+(Target).name);
end;
end;
end;
This does seem to work and I can log all clicks but there is a nasty side effect. Sometimes and without a reporducable set of steps the above code seems to eat a mouse click. This means at seemingly random times a toolbar button won't click and need a double-click. Or a dialog button needs a double-click. Needless to say this is annoying as hell and made me question my mouse before I realised it was only happening in my app.
If I remark the above code the issue is gone.
So does anyone have a reliable way to log all clicks across all forms/objects in my Delphi program without causing bad side effects? I want to intercept and log all clicks but not have any of the messages mysteriously eaten.
Edit: after the helpful comments below, this is the current working code.
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;var Handled: Boolean);
var Target: TControl;
Point: TPoint;
begin
Handled := FALSE;
if (Msg.Message = WM_LBUTTONDOWN) then
begin
Point.X := Msg.pt.X;
Point.Y := Msg.pt.Y;
Target := FindDragTarget(Point,True);
if Assigned(Target) and Assigned(Target.Owner) then
begin
//use (Target).owner.name and (Target).name for logging here
end;
end;
end;
来源:https://stackoverflow.com/questions/47843847/logging-application-wide-mouse-clicks-in-delphi