Как написать глобальную процедуру обработки событий, которая делает элементы управления видимыми / включенными

#delphi

#delphi

Вопрос:

Я сохраняю свойства элементов управления ‘visible’ и ‘enabled’ в таблице БД. В зависимости от роли пользователя я делаю некоторые элементы управления невидимыми / включенными.

поля таблицы БД «Элементы управления»: id, role_id, form (varchar), comp_name (varchar), visible (логическое значение), enable (логическое значение)

запрос qControls: select * from controls where form=:form

вызов этой процедуры из OnShow основной формы:

  application.CreateForm(TForm1, Form1);
 FORM := 'Form1';
 Form1.showModal;
 

Вызываемая процедура:

 procedure RightsOnControls();
    var i:integer;
    
    begin
      fMain.qControls.Close;
      fMain.qControls.Params[0].AsString:= FORM; //FORM is global variable:  FORM:='Form1' 
      fMain.qControls.Open;
      if fMain.qControls.RecordCount>0 then begin
        while not fMain.Controls.Eof do begin
          for I := 0 to form1.ControlCount - 1 do
            if uppercase(form1.Controls[i].Name)= uppercase(fMain.qControlsComp_name.AsString) then
               begin
                form1.Controls[i].Visible:=fmain.qControlsVisible.AsBoolean;
                form1.Controls[i].Enabled:=fmain.qControlsEnable.AsBoolean;
               end;
        fMain.qControls.next;
        end;
      end;
    end;
 

Мои вопросы:

  1. как сделать процедуру общим обработчиком событий, а не только для Form1?
  2. Он находит только элементы управления, расположенные в форме, а не элементы управления, расположенные на панели / элементе управления страницей (tabsheet). Как это изменить?

Ответ №1:

Вызовите эту процедуру с формой для обработки (например, form1) и запросом (fMain.qControls):

 procedure RightsOnControls(AForm: TForm; AQuery: TFDQuery);

  function FindChildControl(Parent: TWinControl; const ControlName: string): TControl;
  var
    I: Integer;
  begin
    for I := 0 to Parent.ControlCount - 1 do begin
      Result := Parent.Controls[I];
      if SameText(Result.Name, ControlName) then Exit;

      if Result is TWinControl then begin
        Result := FindChildControl(TWinControl(Result), ControlName);
        if Result <> nil then Exit;
      end;
    end;
    Result := nil;
  end;

var
  ctl: TControl;
begin
  AQuery.Close;
  AQuery.Params[0].AsString := AForm.Name;
  AQuery.Open;
  while not AQuery.Eof do begin
    ctl := FindChildControl(AForm, AQuery.FieldByName('Comp_name').AsString);
    if ctl <> nil then begin
      ctl.Visible := AQuery.FieldByName('Visible').AsBoolean;
      ctl.Enabled := AQuery.FieldByName('Enable').AsBoolean;
    end;
    AQuery.next;
  end;
end;
 

Если вы не используете FireDAC, измените тип запроса на любой подходящий.

Комментарии:

1. Уве Раабе, спасибо, что потратил время и усилия на написание этого кода Ваш код частично решил мою проблему — он работает для любой формы, но FindChildControl не находит элементы управления, которые расположены на панели / pagecontrol (tabsheets).

2. Я добавил рекурсивную реализацию FindChildControl .

3. Уве Раабе, результат := FindChildControl(результат, ИмяконтРоля) вызывает ошибку: «Несовместимые типы WinControl и TControl», поскольку результатом является TControl, а не TWinnControl.

4. Уве Раабе, отличная работа!!! Ты лучший. Это работает без каких-либо исключений. У меня есть pagecontrol, на котором расположены другие элементы управления страницами, которые содержат таблицы, а на таблицах расположена панель, а на ней находятся элементы управления (кнопки, редактирование и т. Д.). Он находит все эти элементы управления! Большое вам спасибо.