We are having an issue in an application with users double-clicking on almost everything including buttons. In some circumstances that leads to something that was not intended by the user since it will fire the OnClick event on the button twice. One idea to prevent this for the entire application was raised and I want to know if there are any pitfalls with using it.
Add a TApplicationEvents
and implement OnMessage
to set Handled
for WM_LBUTTONDBLCLK
on TButton
to True
.
Something like this:
function GetWindowClassName(Handle: HWND): String;
var
Buffer: array[0..255] of Char;
begin
if GetClassName(Handle, @Buffer, 255) = 0 then
RaiseLastOSError;
Result := Buffer;
end;
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
if Msg.message = WM_LBUTTONDBLCLK then
Handled := (GetWindowClassName(msg.hwnd) = 'TButton');
end;
One obvious drawback is if you have a situation where a user actually wants to click on the same button with some haste. It remains to be investigated if that is the case in this particular application.
To avoid that use a constant in your OnClickEvent:
procedure TMyForm.Button1OnClick(sender:TObject);
const
{$J+}
IsInside:Boolean=False;
{$J-}
begin
if IsInSide then Exit;
IsInside:=True;
try
do your code;
finally
IsInside:=False;
end;
end;
If you have a lot of buttons I suggest to use a TActionList for those buttons and capture de OnActionExecute of ActionList event. Not tested, see TActionList for help. I've used it sometime ago.
procedure TMyForm.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
const
{$J+}
IsInside:Boolean=False;
{$J-}
begin
if IsInSide then Exit;
IsInside:=True;
try
ActionList1.ExecuteAction(Action);
finally
IsInside:=False;
end;
end;