WinForm失去焦点到另一个应用程序需要两次点击工具栏按钮 [英] WinForm lost focus to another application requires two clicks on toolstrip button

查看:101
本文介绍了WinForm失去焦点到另一个应用程序需要两次点击工具栏按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我的应用程序失去对另一个应用程序的关注,然后当用户回到我的应用程序并且他们的第一个操作是单击工具条按钮然后必须单击它两次时,我遇到了一个问题:一次激活表单然后第二个执行按钮的事件。



如果我先去另一个控件并设置焦点(激活表单)然后我可以去工具条按钮和按钮的点击事件触发。



我想知道是否有其他人遇到过这个问题?已知错误?解决方法?此时它对用户来说很烦人。



这种情况​​发生在XP(用户)或我的开发中。 Win7 x64的环境。目标.Net Framework 3.5或4.0。

I've run into an issue when my application loses focus to another application and then when the user comes back to my application and their first action is to click on a toolstrip button then have to click it twice: once to activate the form and then second to execute the button's event.

If I go to another control first and that sets the focus (activates the form) then I can go to the toolstrip button and the button's click event fires.

I was wondering if anyone else has run into this issue? Known bug? Workaround? At this point it is annoying to the users.

This happens in XP (users) or in my dev. environment of Win7 x64. targetting .Net Framework 3.5 or 4.0.

推荐答案

使用ToolStrips将其包含在您的表单中...(;





Include this in your Form with ToolStrips... (;


private bool handleFirstClickOnActivated = false;

/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Form.Activated" /> event.
/// Handle WinForms bug for first click during activation
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
protected override void OnActivated(EventArgs e)
{
    base.OnActivated(e);
    if (this.handleFirstClickOnActivated)
    {
        var cursorPosition = Cursor.Position;
        var clientPoint = this.PointToClient(cursorPosition);
        var child = this.GetChildAtPoint(clientPoint);
        while (this.handleFirstClickOnActivated && child != null)
        {
            var toolStrip = child as ToolStrip;
            if (toolStrip != null)
            {
                this.handleFirstClickOnActivated = false;
                clientPoint = toolStrip.PointToClient(cursorPosition);
                foreach (var item in toolStrip.Items)
                {
                    var toolStripItem = item as ToolStripItem;
                    if (toolStripItem != null && toolStripItem.Bounds.Contains(clientPoint))
                    {
                        var tsMenuItem = item as ToolStripMenuItem;
                        if (tsMenuItem != null)
                        {
                            tsMenuItem.ShowDropDown();
                        }
                        else
                        {
                            toolStripItem.PerformClick();
                        }
                        break;
                    }
                }
            }
            else
            {
                child = child.GetChildAtPoint(clientPoint);
            }
        }
        this.handleFirstClickOnActivated = false;
    }
}


/// <summary>
/// Handle WndProc
/// </summary>
/// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message" /> to process.</param>
protected override void WndProc(ref Message m)
{
    const int WM_ACTIVATE = 0x0006;
    const int WA_CLICKACTIVE = 0x0002;
    if (m.Msg == WM_ACTIVATE && Low16(m.WParam) == WA_CLICKACTIVE)
    {
        handleFirstClickOnActivated = true;
    }
    base.WndProc(ref m);
}

private static int GetIntUnchecked(IntPtr value)
{
    return IntPtr.Size == 8 ? unchecked((int)value.ToInt64()) : value.ToInt32();
}

private static int Low16(IntPtr value)
{
    return unchecked((short)GetIntUnchecked(value));
}

private static int High16(IntPtr value)
{
    return unchecked((short)(((uint)GetIntUnchecked(value)) >> 16));
}


这是因为您需要获得焦点(第一次点击),然后点击按钮(第二次点击)。所有应用程序都这样做。



您可以在表单上处理焦点事件,并将鼠标单击事件反映到工具栏,或者以其他方式评估它的位置工具栏并手动执行必要的操作。
That's because you need to get focus back (the 1st click) and then click the button (the 2nd click). All apps do this.

You could handle the focus event on the form, and reflect the mouse click event to the toolbar, or otherwise evaluate it's position in relation tot he toolbar and take the necessary actions manually.


这是标准行为。您可以在父窗体中处理焦点事件,并将单击传递给子控件(在本例中为工具条按钮)。有点hacky,因为你可能还需要弄清楚点击发生时鼠标下面有什么控件。



一个潜在的问题是如果用户切换焦点对于使用键盘的表格,那么找出表单是否因为点击而获得焦点或者是否因为焦点而获得焦点是有点棘手的。
It's standard behavior. You could handle the focus event in the parent form and pass the click onto the child control (in this case, the toolstrip button). It's kinda hacky, since you may also have to figure out what control is underneath the mouse when the click occurs.

One potential problem with this is if the user switches focus to the form using the keyboard, then it'd be kinda tricky to figure out if the form gained focus due to a click or if it got focus otherwise.


这篇关于WinForm失去焦点到另一个应用程序需要两次点击工具栏按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆