Why TButton.enable does not produce the expected result in this case?

delphi, delphi-xe3, firemonkey

Solution

It's not reacting because the reaction is only visible when the button repaints itself. That only happens when the next wm_Paint message is processed, but your code isn't processing messages, so the button, and indeed the entire form, remains unchanged for the duration of that loop.

The immediate fix would be to call `Button4.Repaint`, which will allow the button to update its appearance. That doesn't process all messages, though.

A poor fix would be to occasionally call `Application.ProcessMessages` in your loop, but needing to call that is usually a sign you're doing something wrong.

Finally, the best fix would be to move your long-running task into another thread. Disable the button when you start the task, and enable it whenever the task completes.

Problem

The following occurs in a FireMonkey (Delphi XE3) application. Look at the following code (it’s just a dummy example, to illustrate the issue): ``` procedure TForm1.Button4Click(Sender: TObject); var i: Integer; begin Button4.Enabled:= false; //This should gray-out the button // get busy for some time for I := 0 to 100000000000 do begin end; Button4.Enabled:= true; end; ``` I would expected Button4 to get grayed-out before entering into the busy operation represented by the “for” loop. Nonetheless, it doesn’t. By the end of the OnClick handler execution, the button does not “seem to react” to the Button4.Enabled:= false. Why? How can I workaround it? This works just fine in VCL. Thanks.

Original source