同时激活表单和处理按钮点击?

8

我正在使用C#中的Windows Forms。

我有一个主窗体,其中包含一些包含toolStripButton的工具栏。在与包含数据的另一个窗体一起工作后,主窗体失去焦点,单击toolStripButton不会触发OnClick事件:第一次单击会激活主窗体,只有第二次单击才会实际按下按钮。我需要用户仅单击一次即可触发Click事件,您有任何想法吗?谢谢。

注:

  • 我曾经使用MDI,单击父窗体按钮时没有问题。但现在最重要的是使窗体自由浮动跨越多个显示器。
  • 工作窗体将主窗体设置为Owner属性,这样它们就会保持在主窗体的顶部。
  • 当我单击非活动窗体的按钮时,MouseHover、MouseEnter、MouseDown和MouseUp都不会触发。只有主窗体的Activate事件会触发。
  • 主窗体上有一个treeView(位于tabControl内,位于splitContainer内,位于面板内)。即使主窗体处于非活动状态,其项目也会在第一次鼠标单击时被选中。我猜并非所有控件都是相等的!
2个回答

10

你需要做的是创建一个继承ToolStrip并处理WndProc的类。这是一种方法,还有其他方法。

private class MyToolStrip : ToolStrip
{
    private const uint WM_LBUTTONDOWN = 0x201;
    private const uint WM_LBUTTONUP   = 0x202;

    private static bool down = false;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_LBUTTONUP && !down)
        {
            m.Msg = (int)WM_LBUTTONDOWN;
            base.WndProc(ref m);
            m.Msg = (int)WM_LBUTTONUP;
        }

        if (m.Msg == WM_LBUTTONDOWN) down = true;
        if (m.Msg == WM_LBUTTONUP)   down = false;
        base.WndProc(ref m);
    }
}

我也看过这个解决方案:

protected override void WndProc(ref Message m)
{
    // WM_MOUSEACTIVATE = 0x21
    if (m.Msg == WM_MOUSEACTIVATE && this.CanFocus && !this.Focused)
        this.Focus();
    base.WndProc(ref m);
}

我在上一个工作场所遇到过这个问题,我认为我想出的解决方案更像后者,但我无法访问我使用过的确切代码。


只是一个提醒,应该是 base.WndProc(ref m); - Amadeusz Wieczorek
抱歉,我将其从VB自动转换,我会修复它。 - dwidel
1
第一种方法通过模拟另一个鼠标单击的方式让人感到非常尴尬。我建议采用第二种解决方案,先将焦点集中在窗口上,然后再处理该点击事件。 - Ray

-4
如果您的窗体没有边框,那么这个逻辑已经为您内置了 :)
form.FormBorderStyle = FormBorderStyle.None

4
你的回答似乎与问题无关。 - LarsTech

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