在不激活表单的情况下与表单交互
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 方法中,该方法在内部将焦点放在控件上。有一些方法可以解决这个问题:
弹出窗体窃取焦点的最后一种情况似乎是在其大小调整(使用鼠标)结束时。但是在这里调用 Owner.Activate() 作为 Activated 事件的结果是安全的......
【讨论】:
以上是关于在不激活表单的情况下与表单交互的主要内容,如果未能解决你的问题,请参考以下文章
如何在不创建其他字段的情况下生成一个列表的嵌套 formik 表单或表单字段?