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

发布于 2024-08-06 03:37:10 字数 696 浏览 5 评论 0原文

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

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

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

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

ShowWithoutActivation 的文档中写道:“如果您的非激活窗口需要使用 UI 控件,则应考虑使用 ToolStrip 控件,例如 ToolStripDropDown。这些控件是无窗口的,并且在选择它们时不会导致窗口激活。”这看起来正是我需要的东西,但我想使用自定义控件和滚动条。

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

谢谢。

I'm trying to implement code-completion popup window in my project. The window is derived from Form. It contains two controls: custom list derived from UserControl (it shows completion possibilities with icons) and a VScrollBar.

When the popup appears, it doesn't steal focus from the editor (form's ShowWithoutActivation is overriden to return true) and the editor sends certain keystrokes to the popup so the user can interact with it using keyboard. So far it works like a charm.

The problem is, I want to allow the user to use mouse as well. But, when the user clicks into the popup window, its form activates and steals focus from the editor. I can react to this by giving the focus back to the editor, I have even set up a Timer to do this regularly, but apart from being a poor solution, the title bar of the editor always flickers when this happens (when the popup is clicked).

Is there any way to interact with the popup form (using mouse) that doesn't make the form activate?

The ShowWithoutActivation's documentation reads: "If your non-activated window needs to use UI controls, you should consider using the ToolStrip controls, such as ToolStripDropDown. These controls are windowless, and will not cause a window to activate when they are selected." This seems exactly like the thing I need, but I want to use a custom control and a scroll bar.

The same problem would be with a tooltip that shows these two arrows to switch method overloads (known from VS) - the whole form would use no controls at all (only render the text and the arrows), but when clicked, it should not activate. The problem could be summarized up to "How to create a form that would never activate, but allow the user to interact with certail controls inside?".

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

死开点丶别碍眼 2024-08-13 03:37:10

只需覆盖 onFocus 事件...

public partial class myListBox:ListBox
{
    protected override void OnGotFocus(EventArgs e)
    {
    }
}

Just override the onFocus event...

public partial class myListBox:ListBox
{
    protected override void OnGotFocus(EventArgs e)
    {
    }
}
南笙 2024-08-13 03:37:10

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

The issue is that you're using a Form for this rather than building some custom control that doesn't run in its' own UI thread like a Form does.
The flashing and highlighting is handled by windows whenever a Form activates/focuses. The only thing I cay think of is to make your Form borderless and create/draw/handle your own title bar that doesn't flash when focused.

衣神在巴黎 2024-08-13 03:37:10

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

  • 从 Control 而不是 UserControl 派生控件
  • 覆盖 OnMouseDown 方法而不是调用 base.OnMouseDown 使
  • 控件的 CanFocus 属性返回 false,但这似乎不可能,因为这意味着使控件要么不可见或未启用,这都是不可取的

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

OK, I may have found a solution. The key seems to be WM_MOUSEACTIVATE message, which the popup form must intercept and respond with MA_NOACTIVATE. But there's a catch - the control derived from UserControl still grabs focus when clicked (the scrollbar luckily doesn't anymore). The problem seems to be in the UserControl.OnMouseDown method, which internally puts focus on the control. There are some ways to fix this:

  • derive the control from Control instead of UserControl
  • override the OnMouseDown method and not call base.OnMouseDown there
  • make the control's CanFocus property return false, but this seems not possible, because that means to make the control either not visible or not enabled, which is both undesirable

The last case when the popup form steals focus seems to be when its resizing (using mouse) ends. But it is safe here to call Owner.Activate() as a result to Activated event...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文