如何编写使控件成为全局事件处理程序 visible/enabled

How to write global event handler procedure that makes controls visible/enabled

我将控件 'visible' 和 'enabled' 属性 存储在数据库 table 中。根据用户的角色,我做了一些不 visible/enabled.

的控件

数据库的字段Table“控件”:id,role_id,表单(varchar),comp_name(varchar),可见(布尔值),启用(布尔值)

查询 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. 它只找到位于窗体上的控件,而不是位于 panel/Page 控件(选项卡)上的控件。怎么改?

使用要处理的表单 (f.i.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,请将查询类型更改为合适的类型。