在不集中的ToolStripItem上显示工具提示

时间:2020-03-06 14:49:09  来源:igfitidea点击:

将鼠标悬停在ToolStripItems上时,即使它们所在的窗体没有对准焦点,它们也会显示Active高亮。但是,除非表格重点突出,否则它们不会显示其工具提示。我已经看到了ToolStrip的"点击型"黑客。任何人都知道当其父窗体不在焦点上时如何使ToolStripButton显示其工具提示吗?

谢谢!

解决方案

也许这段代码中的两种方法中的一种将使我们朝着正确的方向迈进。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

public Form1()
{
    InitializeComponent();

    tooltip = new ToolTip();
    tooltip.ShowAlways = true;
}

private ToolTip tooltip;
private void toolStripButton_MouseHover(object sender, EventArgs e)
{
    if (!this.Focused)
    {
        ToolStripItem tsi = (ToolStripItem)sender;
        tooltip.SetToolTip(toolStrip1, tsi.AutoToolTip ? tsi.ToolTipText : tsi.Text);
        /*tooltip.Show(tsi.AutoToolTip ? tsi.ToolTipText : tsi.Text, this, 
            new Point(toolStrip1.Left, toolStrip1.Bottom));*/
    }
}

private void toolStripButton_MouseLeave(object sender, EventArgs e)
{
    tooltip.RemoveAll();
}

第一个问题是我们不能将其直接设置为按钮,它不能从Control继承,并且除非我们位于工具条上而不是按钮上,否则不会显示工具提示。

第二个问题(注释方式)根本不显示。不太清楚为什么,但是也许我们可以调试一下。

问题在于ToolStrip的"控件"(如ToolStripButton或者ToolStripDropDownButton)不会从Control继承。现在,我通过在用户将鼠标悬停在按钮上时将ToolStrip对准焦点来解决该问题。按钮的MouseHover事件触发得太晚了-在运行"显示工具提示"代码之后,因此我扩展了ToolStripDropDownButton类并使用了新按钮。此方法适用于从ToolStripItem继承的任何其他类似按钮的类

public class ToolStripDropDownEx : ToolStripDropDownButton
{
    public ToolStripDropDownEx(string text)
    {
    }

    protected override void OnMouseHover(EventArgs e)
    {
        if (this.Parent != null)
            Parent.Focus();
        base.OnMouseHover(e);
    } 
}

我试图做同样的事情,并确定这将是非常具有挑战性的,不值得。原因是在内部,.NET代码专门设计为仅在窗口处于活动状态时才显示工具提示,因为它们正在Win32级别进行检查,因此很难伪造代码。

这是ToolTip.cs中的代码段,该代码段检查" GetActiveWindow()"并返回false。我们可以在代码"工具提示仅在活动的Windows上显示"中看到注释。

顺便说一句,我们可以在Visual Studio 2008中看到.NET BCL的所有源代码,这是我使用的说明:

http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

// refer VsWhidbey 498263: ToolTips should be shown only on active Windows.
private bool IsWindowActive(IWin32Window window)
{ 
    Control windowControl = window as Control;
    // We want to enter in the IF block only if ShowParams does not return SW_SHOWNOACTIVATE. 
    // for ToolStripDropDown ShowParams returns SW_SHOWNOACTIVATE, in which case we DONT want to check IsWindowActive and hence return true. 
    if ((windowControl.ShowParams & 0xF) != NativeMethods.SW_SHOWNOACTIVATE)
    { 
        IntPtr hWnd = UnsafeNativeMethods.GetActiveWindow();
        IntPtr rootHwnd =UnsafeNativeMethods.GetAncestor(new HandleRef(window, window.Handle), NativeMethods.GA_ROOT);
        if (hWnd != rootHwnd)
        { 
            TipInfo tt = (TipInfo)tools[windowControl];
            if (tt != null && (tt.TipType & TipInfo.Type.SemiAbsolute) != 0) 
            { 
                tools.Remove(windowControl);
                DestroyRegion(windowControl); 
            }
            return false;
        }
    } 
    return true;
}