I have the following procedure in Delphi 6:
procedure TfrmUserCRUD.ShowErrorWithFocus(Message: string; FocusedField: TWinControl);
begin
try
raise Exception.Create(Message);
except
on E : Exception do
begin
ShowMessage(E.Message);
FocusedField.SetFocus;
Abort;
end;
end;
end;
This is how I'm calling the function:
procedure TfrmUserCRUD.ValidateFields();
begin
if not(chkListProducts.Checked) and (chkUsesProductValue.Checked) then
ShowErrorWithFocus('You need to use the product list if you wanna use the product value.', chkListProducts);
if (chkUsesProductValue.Checked) and (edtProductValue.KeyValue = nil) then
ShowErrorWithFocus('The field "value of product" needs to be filled', edtProductValue);
end;
The objective of this procedure is to receive an error message and one of the fields from the form (CheckBox, Grid, Edit, etc) and whenever the function is called, it's supposed to show the message on screen with the error, then focus the field that it received like the system was highlighting it, like in those pictures:
I've been trying to use different methods so it could focus on the field, but if I use raise, the program loses the field variable, if I use Abort, the program doesn't do anything. I've also tried different ways of focusing the TField, like using Perform() and event updates, but it didn't worked as intended.
Any ideas of what I could do to resolve this problem?


It makes absolutely no sense to raise an exception just to immediately catch it. You don't need the
try..exceptat all:That being said, depending on the context in which
ShowErrorWithFocus()is being called (which you did not show), it may not be valid/prudent to set focus right away (the OS/VCL can be really finicky about focus changes done out of order), so you may need to delay the focus until after the message queue has settled down first.PostMessage()will work fine for that, ie you could post a message to the Form, where you pass theFocusedFieldpointer in the message'slParam, and then the message handler can callSetFocus()on that object, eg:UPDATE:
You didn't show where you are calling
ValidateFields()from, exactly. CallingSetFocus()while input focus is already in progress of being changed can cause UI problems. But since you mentioned in a comment that you are calling it in a ButtonOnClickevent, then in that context you can simplySetFocus()the desired control first and thenraise(and not catch!) the error message. Let the VCL display the error message to the user for you, and then the focused control will regain input focus after the error dialog is dismissed, eg: