14

我有一个带有一堆控件的表单,我想遍历某个面板上的所有控件并启用/禁用它们。

我试过这个:

var component: TComponent;
begin
  for component in myPanel do
    (component as TControl).Enabled := Value;
end;

但这无济于事。原来所有组件都在表单的组件集合中,而不是它们的父对象。那么有谁知道是否有任何方法可以将所有控件放入控件中?(除了像这样丑陋的解决方法,这是我最终不得不做的):

var component: TComponent;
begin
  for component in myPanel do
    if (component is TControl) and (TControl(component).parent = myPanel) then
      TControl(component).Enabled := Value;
end;

有人请告诉我有更好的方法...

4

6 回答 6

26

您正在寻找TWinControl.Controls数组和随附的ControlCount属性。这些是针对控件的直系子级的。要获得孙子等,请使用标准递归技术。

您并不真正想要Components数组(这是for-in循环迭代的内容),因为它通常与父子关系无关。组件可以拥有没有子关系的事物,而控件可以拥有不属于它们的子项。

另请注意,禁用控件也会隐式禁用其所有子项。您不能与禁用控件的子级交互;操作系统不会向他们发送输入消息。但是,要使它们看起来被禁用,您需要单独禁用它们。也就是说,要使按钮具有灰色文本,仅禁用其父级是不够的,即使该按钮不会响应鼠标单击。您需要禁用按钮本身以使其“禁用”自己绘制。

于 2009-01-05T23:41:09.277 回答
13

如果禁用面板,则其上的所有控件也会被禁用。

使用匿名方法的递归解决方案:

type
  TControlProc = reference to procedure (const AControl: TControl);

procedure TForm6.ModifyControl(const AControl: TControl; 
  const ARef: TControlProc);
var
  i : Integer;
begin
  if AControl=nil then
    Exit;
  if AControl is TWinControl then begin
    for i := 0 to TWinControl(AControl).ControlCount-1 do
      ModifyControl(TWinControl(AControl).Controls[i], ARef);
  end;
   ARef(AControl);
end;

procedure TForm6.Button1Click(Sender: TObject);
begin
  ModifyControl(Panel1,
    procedure (const AControl: TControl)
    begin
      AControl.Enabled := not Panel1.Enabled;
    end
  );
end;
于 2009-01-05T23:44:29.957 回答
2

这是Delphi 2007的方式:

procedure TForm6.ModifyControl(const AControl: TControl; const value: Boolean);
var
  i: Integer;
begin
  if AControl=nil then Exit;
  if AControl is TWinControl then begin
    for i := 0 to TWinControl(AControl).ControlCount-1 do
      ModifyControl(TWinControl(AControl).Controls[i], value);
  end;
  Acontrol.Enabled := value;
end;

procedure TForm6.Button1Click(Sender: TObject); 
begin 
  ModifyControl(Panel1, true);  // true or false
end;
于 2012-03-24T18:46:28.713 回答
1

简单地

Panel.Enabled := Value;
于 2009-01-06T01:36:48.920 回答
1

这个找到所有控件,也嵌套在框架等中,并通过列表指向它们。请注意之后释放列表。

Function AllControls(form : tForm) : tList<tControl>;
Procedure Add(Control : tControl );
var i : integer;
begin
  if Control is TWinControl then
  with TWinControl(Control) do
  for i := 0 to Controlcount-1 do
    Add(Controls[i]);

    if Control <> form  then
    result.Add(Control);
  end;
 begin
   result := tlist<tControl>.create;
   add(form);
 end;

 var contrls : tlist<tcontrol>;
     c : tcontrol;
 begin
    try
      contrls := AllControls(form1);
      for c in ctrls do Visit(c);  // Do something
    finally
      contrls.free;
    end;
 end;

如果你想要一个通用版本,你可以要求一个特定的控件类型,你可以使用这个:

Procedure TForm1.Addcontrols( control : tcontrol; list : tlist<tcontrol>);
var i : integer;
begin
  if control is twincontrol then
  with twincontrol(control) do
    for i := 0 to controlcount-1 do
    addControl(controls[i], list);
    list.Add(control)
end;

Function TForm1.GetControls<T>(f : tform) : tlist<T>;
var list : tlist<tcontrol>;
    c : tcontrol;
begin
  list := tlist<tcontrol>.Create;
  addControls(f, list);
  result := tlist<t>.create;
  for c in list do
  if c <> f  then
  if c is t then
  result.Add(c);
  list.free;
end;

procedure TForm1.FormCreate(Sender: TObject);
VAR List : TList<TRadioButton>;
begin
  List := GetControls<TRadioButton>(self);
end;

end.

采用

  List := GetControls<TControl>(self);

获得所有控制..

于 2019-09-27T08:37:23.767 回答
0

我知道这篇文章有点旧,但我是基于对相同信息的搜索来到这里的。这是我为任何感兴趣的人编写的一些 C++ 代码。

// DEV-NOTE:  GUIForm flattens the VCL controls
// VCL controls are nested.  I.E. Controls on a
// Panel would have the Panel as a parent and if
// that Panel is on a TForm, TForm's control count
// does not account for the nested controls on the
// Panel.
//
// GUIControl is passed a Form pointer and an index
// value, the index value will walk the controls on the
// form and any child controls counting up to the idx
// value passed in.  In this way, every control has a
// unique index value
//
// You can use this to iterate over every single control
// on a form.  Here is example code:
//
// int count = 0;
// TForm *pTForm = some_form
// TControl *pCtrl = 0;
// do
// {
//      pCtrl = GUIControl(pTForm, count++);
//
// }while(pCtrl);

TControl *GUIControl(TForm *F, int idx)
{
    TControl *rval = 0;
    int RunCount = 0;

    for(int i=0; i<F->ControlCount && !rval; i++)
    {
        TControl *pCtl = F->Controls[i];

        if(RunCount == idx )
            rval = pCtl;
        else
            rval = GUIChildControl( pCtl, RunCount, idx);

        RunCount++;
    }

    return(rval);
}

TControl *GUIChildControl(TControl *C, int &runcount, int idx)
{
    TControl *rval = 0;
    TWinControl *pC = dynamic_cast<TWinControl *>(C);
    if(pC)
    {
        for(int i=0; i<pC->ControlCount && !rval; i++)
        {
            TControl *pCtrl = pC->Controls[i];
            runcount++;

            if( runcount == idx)
                rval = pCtrl;
            else
            {
                TWinControl *pCC = dynamic_cast<TWinControl *>(pCtrl);

                if(pCC)
                {
                    if( pCC->ControlCount )
                        rval = GUIChildControl(pCtrl, runcount, idx);
                }
            }
        }
    }

    return(rval);
}
于 2013-12-04T16:43:44.330 回答