在不激活表单的情况下与表单交互

Posted

技术标签:

【中文标题】在不激活表单的情况下与表单交互【英文标题】:Interacting with a form without it activating 【发布时间】:2010-12-01 20:03:07 【问题描述】:

我正在尝试在我的项目中实现代码完成弹出窗口。窗口是从窗体派生的。它包含两个控件:从 UserControl 派生的自定义列表(通过图标显示完成的可能性)和一个 VScrollBar。

当弹出窗口出现时,它不会从编辑器中窃取焦点(表单的 ShowWithoutActivation 被覆盖以返回 true)并且编辑器向弹出窗口发送某些击键,以便用户可以使用键盘与其交互。到目前为止,它就像一个魅力。

问题是,我想让用户也可以使用鼠标。但是,当用户点击弹出窗口时,它的表单会激活并从编辑器中窃取焦点。我可以通过将焦点返回给编辑器来对此做出反应,我什至设置了一个计时器来定期执行此操作,但除了是一个糟糕的解决方案之外,编辑器的标题栏在发生这种情况时总是闪烁(当弹出窗口是点击)。

有什么方法可以与不会激活表单的弹出表单(使用鼠标)进行交互?

ShowWithoutActivation 的文档是这样写的:“如果你的非激活窗口需要使用 UI 控件,你应该考虑使用 ToolStrip 控件,比如 ToolStripDropDown。这些控件是无窗口的,当它们被选中时不会导致窗口激活。”这似乎正是我需要的东西,但我想使用自定义控件和滚动条。

同样的问题是显示这两个箭头来切换方法重载的工具提示(从 VS 已知) - 整个表单根本不使用任何控件(仅呈现文本和箭头),但是当单击时,它不应该激活。问题可以总结为“如何创建一个永远不会激活的表单,但允许用户与里面的某些控件进行交互?”。

谢谢。

【问题讨论】:

您需要将其设为单独的表单吗?如果您将其实现为浮动在表单上所有其他控件之上的 UserControl,您将不会遇到此问题。当然,您可能希望此弹出窗口能够出现在表单边缘之外。 @MusiGenesis:是的,我将弹出窗口设置为单独的表单的主要原因是它可以出现在边缘。闪烁只是一个“美容”问题,但话说回来,它不会发生在VS和类似的应用程序中,所以必须有办法...... 我有点困惑。您希望用户在浮动窗口上与鼠标进行交互但不想给它焦点?我建议不要使用表单,而只编写一个仍绑定到其父级的浮动控件。 【参考方案1】:

只需覆盖 onFocus 事件...

public partial class myListBox:ListBox

    protected override void OnGotFocus(EventArgs e)
    
    

【讨论】:

谢谢,但这不起作用,我以前试过。如果我调用“_editor.Focus()”作为对 GotFocus 或 Activated 事件的反应,我将无法再单击弹出表单 - 它没有响应。而且闪烁还在。但是,如果我调用“_editor.Focus()”作为对 MouseDown 事件的反应,它会起作用,但是当这种情况发生时,编辑器的标题栏仍然会闪烁。【参考方案2】:

问题在于您为此使用了表单,而不是构建一些自定义控件,该控件不像表单那样在其自己的 UI 线程中运行。 每当表单激活/聚焦时,窗口都会处理闪烁和突出显示。我唯一能想到的就是让您的表单无边框并创建/绘制/处理您自己的标题栏,该标题栏在聚焦时不会闪烁。

【讨论】:

【参考方案3】:

好的,我可能已经找到了解决方案。关键似乎是WM_MOUSEACTIVATE 消息,弹出表单必须拦截并以MA_NOACTIVATE 响应。但是有一个问题 - 派生自 UserControl 的控件在单击时仍会获得焦点(幸运的是滚动条不再存在)。问题似乎出在 UserControl.OnMouseDown 方法中,该方法在内部将焦点放在控件上。有一些方法可以解决这个问题:

从 Control 而不是 UserControl 派生控件 重写 OnMouseDown 方法,而不是在那里调用 base.OnMouseDown 使控件的 CanFocus 属性返回 false,但这似乎是不可能的,因为这意味着使控件不可见或不启用,这都是不可取的

弹出窗体窃取焦点的最后一种情况似乎是在其大小调整(使用鼠标)结束时。但是在这里调用 Owner.Activate() 作为 Activated 事件的结果是安全的......

【讨论】:

以上是关于在不激活表单的情况下与表单交互的主要内容,如果未能解决你的问题,请参考以下文章

如何在不创建新的表单实例的情况下在表单之间切换?

如何在不创建其他字段的情况下生成一个列表的嵌套 formik 表单或表单字段?

如何获取将在不提交的情况下提交的所有表单值[重复]

在不提交表单的情况下触发 Google 脚本

如何在不知道表单内控件名称的情况下获取表单中的 GET/POST 元素

AJAX:在不刷新页面的情况下发布表单详细信息[重复]