Validations and setFocus pain... lazarus / 16-Databases ---------------------------------------------------------------------- eara · 2014-04-20 19:15 In my project a painfull & time consuming process is the ".setFocus" in case a validation fails. I will  try to explain what i mean... All the time i write validations (usually on BeforePost) that may fire a MessageDlg or raise an exception, and in case of validation failure i want to focus to the related control, where user can edit it's value and retry... The validations are performed usually with TFields from TSQLQuery instead of the db controls (yes i use db controls). Now when a validation fails, and before throwing in the user's face the corresponding error message i try to call the setFocus of the related control (if any exists). One problem that arrises is to ensure that the control can be focused (is it enabled? or worst ... is it visible ?) and the complexity of this depends on the form's design. And my case is suffering little from this. All my forms have 2 PageControls with mutliple tabSheets, so i need also to check page controls and tabsheet if they are visible, enabled in order to select them etc etc... What i did for this till now... I wrote a general focusField(f:TField) virtual method in a base form class and i use it all the time.... Now in every descedant form, i must override this and for every field in my form i try to find the related control and set the focus on it. take an example of what i mean... Code: [Select]procedure TfrmTranTypes.focusField(f: TField); begin   if pgc.Enabled and pgc.Visible   and tabRecord.Enabled  and tabRecord.tabVisible then begin     pgc.ActivePage:=tabRecord;     if (edt_tran_type.Field=f)     and edt_tran_type.Enabled     and edt_tran_type.Visible then       edt_tran_type.SetFocus     else if (edt_tran_type_label.Field=f)     and edt_tran_type_label.Enabled     and edt_tran_type_label.Visible then       edt_tran_type_label.SetFocus     else if (edt_tran_type_desc.Field=f)     and edt_tran_type_desc.Enabled     and edt_tran_type_desc.Visible     and pgcDetails.Enabled     and pgcDetails.Visible     and tab_tran_type_desc.Enabled     and tab_tran_type_desc.tabVisible then begin       pgcDetails.ActivePage:=tab_tran_type_desc;       edt_tran_type_desc.SetFocus     end else if (chk_tran_type_hardcoded.Field=f)     and chk_tran_type_hardcoded.Enabled     and chk_tran_type_hardcoded.Visible then       chk_tran_type_hardcoded.SetFocus     else if (chk_tran_type_media.Field=f)     and chk_tran_type_media.Enabled     and chk_tran_type_media.Visible then       chk_tran_type_media.SetFocus     else if (chk_tran_type_member.Field=f)     and chk_tran_type_member.Enabled     and chk_tran_type_member.Visible then       chk_tran_type_member.SetFocus   end; end; One thing that would help this (not sure, only speculate) is to have in TFields a property where i can set the related control in design time or in runtime.... One other is a recursive routine where you give the control and tries to check if it is focus able, or should i just simple call setFocus in a try except ? currently i must leave with this for my project (time pressure), but i would like to hear also other thoughts ... ---------------------------------------------------------------------- Blaazen · 2014-04-20 19:23 Did you tryCode: [Select]CanFocusmethod? BTW, what platform do you have? ---------------------------------------------------------------------- eara · 2014-04-20 19:44 @Blaazen  what have you said right now !!!!   No i didn't .... but quick thinking... again in case .CanFocus returns false again i must write the same !@#!@#! for selecting the right tabsheet ... (lazarus 1.2.0) thank you... ---------------------------------------------------------------------- taazz · 2014-04-20 22:29 something along the lines of Code: [Select]function IsDBAware(const aControl:TControl):Boolean; begin   Result := aControl.InheritsFrom(TCustomDBListBox) or             aControl.InheritsFrom(TDBRadioGroup) or             aControl.InheritsFrom(TDBCheckBox) or             aControl.InheritsFrom(TCustomDBComboBox) or             aControl.InheritsFrom(TDBMemo) or             aControl.InheritsFrom(TDBGroupBox) or             aControl.InheritsFrom(TDBImage) or             aControl.InheritsFrom(TDBCalendar) or             aControl.InheritsFrom(TDBEdit) or             aControl.InheritsFrom(TDBText) or             aControl.InheritsFrom(TDBLookup); end; function IsFieldEditor(const aControl:TControl; const aField:TField):Boolean; begin   Result := False;   if IsDBAware(aControl) then begin     if (aControl is TDBEdit)          then Result := TDBEdit(aControl).Field = aField;     if (aControl is TCustomDBListBox) then Result := TCustomDBListBox(aControl).Field = aField;     if (aControl is TDBRadioGroup)    then Result := TDBRadioGroup(aControl).Field = aField;     if (aControl is TDBCheckBox)      then Result := TDBCheckBox(aControl).Field = aField;     if (aControl is TDBMemo)          then Result := TDBMemo(aControl).Field = aField;     if (aControl is TDBGroupBox)      then Result := TDBGroupBox(aControl).Field = aField;     if (aControl is TDBImage)         then Result := TDBImage(aControl).Field = aField;     if (aControl is TDBCalendar)      then Result := TDBCalendar(aControl).Field = aField;     if (aControl is TDBEdit)          then Result := TDBEdit(aControl).Field = aField;     if (aControl is TDBText)          then Result := TDBText(aControl).Field = aField;     if (aControl is TDBLookup)        then Result := TDBLookup(aControl).KeyField = aField;   end; end; function ControlTabSheet(aControl:TWinControl):TTabSheet; begin   Result := aControl;   while not (Result is TTAbSheet) do result := Result.Parent; end; procedure ActivateTabSheet(const aTabSheet:TTabSheet); begin   if not Assigned(aTabSheet) then exit;   aTabSheet.PageControl.ActivePage := aTabSheet;   ActivateTabSheet(ControlTabSheet(aTabSheet); end; function ShowForm(const aForm : TForm; const aModal : Boolean):Integer; begin   if Assigned(aForm) and (not aForm.Visible) then begin     Result := 0;     if aModal then Result := aForm.ShowModal else aForm.Show;   end; end; procedure ActivateControl(aControl:TWinControl); begin   If not aControl.CanFocus then begin     ActivateTabSheet(ControlTabSheet(aControl));     ShowForm(GetParentForm(aControl), False);   end;   aControl.SetFocus; end; function TForm1.FocusField(aField: TField): Boolean; var   CompCount: Integer; begin   for CompCount := 0 to ComponentCount -1 do begin     if (Components[CompCount] is TWinControl) and IsFieldEditor(TWinControl(Components[CompCount]), aField) then       ActivateControl(Components[CompCount]);   end; end; This should minimize overriding to exceptions only and probably only if those exceptions should be kept as such and not appended in one of the support procedures. eg tzvDBDateTimePicker is there in my libraries because I use that component too but a Data aware component that is used only in one of my applications in one form and will never be used outside that application and form will never find its way in the routines which I try to keep its external dependencies as minimal as possible. ---------------------------------------------------------------------- eara · 2014-04-22 09:34 thank you man, i ll check this