如何防止控件窃取焦点?

4
我们的C# WinForms应用程序中加载了一个第三方控件。
当我们调用这个第三方ActiveX控件的方法时,它会异步地窃取焦点。例如:
// This call causes 3rd party to spawn a thread and steal focus 
// milliseconds later.
foo3rdParty.DoSomething();

有没有办法防止控件窃取焦点?

你可能需要使用消息钩子来拦截并取消焦点的改变。这是控件非常粗鲁的行为 - 我想没有完全删除它的机会。 - MusiGenesis
别开玩笑了,这真的是很粗鲁的行为。我们问开发人员如何防止/解决这种行为,他告诉我们:“使用Win32 API重新获取焦点。”问题是,没有通知线程何时完成窃取焦点,所以我们有点束手无策。我们向开发人员解释了这一点,但从未收到回复。 - Judah Gabriel Himango
1
他解释了为什么他的控件首先需要窃取焦点吗?如果有任何合理的原因,那可能是一个欺骗性修复,掩盖了更深层次的问题。我希望这不像太空船生命支持维护控制那样严重。 - MusiGenesis
它不是“他”。它是一个非常非常大的公司,其第三方控制遍布互联网。 :-) 他们认为他们的控制非常重要,以至于当您在其上调用DoSomething()时,它应该获得焦点。 - Judah Gabriel Himango
4个回答

3
如果控件有GotFocus()事件(并且每当控件窃取焦点时都正确触发),您可以附加一个处理程序,并将焦点设置回上次拥有焦点的控件(或OK按钮或其他内容)。
如果有人正在文本框中输入,这可能会产生奇怪的现象。我的解决方案是支付一些费用,让愿意帮助我的人花大约15分钟的时间来解决这个问题。

是的,相当粗糙。我尝试过这个方法,但发现控件本身在此期间会窃取焦点2-3次,因此即使使用这种方法也无法完全解决问题。 - Judah Gabriel Himango

3
如果这个恶意的小控件不打算可见,你可以将它放在一个不可见的表单上,并在那里调用DoSomething()。然后,谁关心它是否抓住了焦点?

很抱歉,它必须在我们的表格上。嗯。 - Judah Gabriel Himango

2
您可以尝试以下粗略的方法:
  1. 在调用之前找到当前具有焦点的控件,例如使用Form.ActiveControl
  2. 将处理程序附加到活动控件,当其失去焦点时会调用该处理程序。
  3. 调用第三方控件的方法。
  4. 如果一切按预期进行,第三方控件将获得焦点,之前具有焦点的控件将失去焦点,并且将调用处理程序。
  5. 在处理程序中,要么将焦点设置回先前的控件,要么安排一些代码在稍后运行以执行此操作。

谢谢,我试过了。结果发现,这个第三方 activex 控件在调用 DoSomething() 后会多次偷取焦点,通常是 2 到 3 次。这使得上面的 hackish 解决方案变得更加复杂。无论如何还是感谢。 - Judah Gabriel Himango

2

嗯,你可能已经想到了,但是在控件尝试获取焦点的期间(或猜测的时间)是否可以禁用控件窗口,而不影响用户体验?


可能可以。我会尝试并回复你。 - Judah Gabriel Himango
我尝试了一下,似乎可以工作。虽然这是一个hack,但并不太丑陋,并且相当稳定。感谢您的建议,我将其标记为已接受的答案。 - Judah Gabriel Himango
你是怎么做到的,因为这正是我正在遇到的问题。 - Andrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接