我有一个带有大量控件的表单,我想迭代某个面板上的所有控件并启用/禁用它们。
我试过了:
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;
有人请告诉我有更好的方法......
答案 0 :(得分:25)
您正在寻找TWinControl.Controls
数组和随附的ControlCount
属性。那些是控制的直接孩子。要获得孙子等,请使用标准的递归技术。
你真的不想要Components
数组(这是for
- in
循环遍历的那个),因为它通常与父程序无关 - 孩子的关系。组件可以拥有没有子关系的东西,控件可以拥有他们不拥有的子代。
另请注意,禁用控件也会隐式禁用其所有子控件。你不能与残疾人控制的孩子互动;操作系统不会向它们发送输入消息。但是,要使它们看起来已禁用,您需要单独禁用它们。也就是说,要使按钮具有灰色文本,即使该按钮不响应鼠标单击,也不足以禁用其父项。您需要禁用按钮本身,使其“禁用”自己绘制。
答案 1 :(得分: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;
答案 2 :(得分: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;
答案 3 :(得分:1)
简单地
Panel.Enabled := Value;
答案 4 :(得分: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);
获取所有控件。
答案 5 :(得分: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);
}