【发布时间】:2014-08-30 10:37:09
【问题描述】:
我有自己的 Treeview 控件,源自 TCustomTreeView。
我在类中添加了一些我自己的过程,例如添加节点。在运行时调用此过程时,我希望选择新添加的节点并聚焦 Treeview,以便突出显示新节点。
摘录如下:
procedure TMyTreeView.AddGroup(AName: string);
var
Node: TTreeNode;
Obj: TGroup;
procedure AddToTree;
begin
Obj := TGroup.Create(AName);
FGroups.Add(Obj);
Node := Items.AddObject(Node, AName, Obj);
with Node do
begin
ImageIndex := 0;
SelectedIndex := 0;
end;
Selected := Node;
SetFocus;
end;
begin
Node := nil;
AddToTree;
end;
上述方法有效,但我在从表单OnCreate 事件调用时遇到常见错误消息:
无法聚焦已禁用或不可见的窗口
我知道您可以使用OnActivate 事件,或者根本不使用OnCreate,这不会导致错误,但是可能使用该组件的其他人可能没有意识到这一点。
所以我想知道是否有办法确定我的 Treeview(或任何控件)是否能够接收焦点,然后我可以添加一些我自己的检查,例如:
if ControlIsFocusable then
begin
Selected := Node;
SetFocus;
end;
我知道您可以覆盖Loaded 过程,它会告诉我们何时加载控件,但那只会在第一次运行时起作用。如果控件在运行时被用户隐藏(或一开始不可见),Cannot focus a disabled or invisible window 错误仍然会出现。
不在调试器中运行时的脏方法是:
try
Selected := Node;
SetFocus;
except
end;
但这违背了目的,我讨厌以这种方式处理错误。
所以基本上我想知道是否有一种方法可以确定控件是否可以接收焦点,以便我们可以将焦点设置给它?
【问题讨论】:
-
我认为你做错了。控件不应在自身上调用
SetFocus。我无法想象这是正确行为的场景。形式或应用程序或框架应确定重点。不是控制。想象一下,当您有一个包含两个这样的控件的表单时会发生什么? -
如果 MyTreeView1.HandleAllocated 和 IsWindowVisible(MyTreeView1.Handle) 那么
-
你需要CanFocus docwiki.embarcadero.com/Libraries/XE5/en/…
-
@Keith - 事实并非如此。
-
@Blobby - 不客气。
IsWindowVisible反映了控件的 api 级别窗口的实际可见性,而不是 VCL 的visible声明的 intention。例如,您可以在隐藏的父级中拥有visible控件,当然您看不到。这与 Keith 提到的CanFocus大致相同,当表单本身为visible但不实际上可见时(OnCreate中的情况就是这种情况),这将无济于事。Showing更符合实际可见性,但如果您感兴趣的是 api 对可见性的看法,询问 api 是最安全的选择。