【问题标题】:How do I know when a control can be focused?我如何知道控件何时可以聚焦?
【发布时间】: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) 那么
  • @Keith - 事实并非如此。
  • @Blobby - 不客气。 IsWindowVisible 反映了控件的 api 级别窗口的实际可见性,而不是 VCL 的 visible 声明的 intention。例如,您可以在隐藏的父级中拥有visible 控件,当然您看不到。这与 Keith 提到的 CanFocus 大致相同,当表单本身为 visible 但不实际上可见时(OnCreate 中的情况就是这种情况),这将无济于事。 Showing 更符合实际可见性,但如果您感兴趣的是 api 对可见性的看法,询问 api 是最安全的选择。

标签: delphi delphi-xe


【解决方案1】:

我不会回答你提出的问题,因为我认为你做错了。

控件不应在自身上调用SetFocus。我无法想象这是正确行为的场景。形式或应用程序或框架应确定重点。不是控制。

想象一下当您有一个包含两个这样的控件的表单时会发生什么?想象一下使用键盘聚焦一个按钮,然后用 SPACE 栏按下该按钮。如果附加到按钮的操作调用了控件的方法,然后更改了焦点,那么您就违反了平台 UI 准则。现在,您的控制会给任何尝试使用它的应用程序带来沉重的负担。

【讨论】:

  • 好的,我现在意识到这是一个错误。正如我之前评论的那样,我只使用我的一个控件实例进行测试,因此从未想到拥有多个控件的场景。既然您已经引起了我的注意,我可以看到我正在尝试做的事情是错误的和不好的。所以我同意不回答我提出的问题,因为它现在基本上是无效的,并且只会试图解决一个原本不应该存在的问题。话虽如此,解决方案是删除SetFocus 行,如果用户需要突出显示节点,他们可以自己设置焦点。
  • 还有一点值得注意的是HideSelection属性,设置为False至少表示当前选中的是哪个节点。
猜你喜欢
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
相关资源
最近更新 更多