winforms 突出显示菜单项时的事件

q9rjltbz  于 2023-03-09  发布在  其他
关注(0)|答案(2)|浏览(153)

有没有人想出一个事件,触发每当菜单项是突出显示?
我希望在突出显示菜单命令时,在状态栏中显示它们的说明。我希望无论是使用鼠标还是键盘突出显示菜单命令,都能显示说明。
但经过相当大的努力,我没有看到任何类似的事件。我甚至尝试覆盖WndProc来检测原始菜单消息,但发现没有发送任何消息。显然,WinForms不使用标准的Windows菜单。
似乎知道菜单项何时被点击和何时被选中(突出显示而不被点击)应该是两个最重要的菜单事件,我不知道为什么不支持后者。
有人能搞清楚吗?

    • 更新**

在这里给出的答案的帮助下,我能够提出一个完整的解决方案,我已经将该解决方案作为开源发布在NuGetGitHub上。

yquaqz18

yquaqz181#

除了鼠标事件之外,您还可以通过处理所有者菜单的KeyUp事件来添加键盘按键部分,以获取所选项并在状态栏标签中显示描述。

public YourForm()
{
    InitializeComponent();

    menuStrip1.ShowItemToolTips = false;
    menuStrip1.KeyUp += OnToolStripKeyUp;

    foreach (var item in GetAllToolStripItems(menuStrip1.Items))
    {
        item.AutoToolTip = false;
        item.MouseEnter += OnToolStripItemMouseEnter;
        item.MouseLeave += OnToolStripItemMouseLeave;

        if (item.GetCurrentParent() is ToolStrip dm)
        {
            dm.ShowItemToolTips = false;
            dm.KeyUp -= OnToolStripKeyUp;
            dm.KeyUp += OnToolStripKeyUp;
        }
    }
}

private void OnToolStripItemMouseEnter(object sender, EventArgs e)
{
    sbrLabel.Text = (sender as ToolStripItem).ToolTipText;
}

private void OnToolStripItemMouseLeave(object sender, EventArgs e)
{
    sbrLabel.Text = "Ready";
}

private void OnToolStripKeyUp(object sender, KeyEventArgs e)
{
    var s = sender as ToolStrip;
    var selItem = s.Items.OfType<ToolStripMenuItem>().FirstOrDefault(x => x.Selected);

    sbrLabel.Text = selItem?.ToolTipText;
}

private IEnumerable<ToolStripItem> GetAllToolStripItems(ToolStripItemCollection tsic)
{
    foreach (var tsi in tsic.Cast<ToolStripItem>())
    {
        yield return tsi;

        if (tsi is ToolStripDropDownItem tsddi && tsddi.HasDropDown)
            foreach (var ddi in GetAllToolStripItems(tsddi.DropDownItems))
                yield return ddi;
    }
}

x6h2sr28

x6h2sr282#

在@dr.null的帮助下,我把这个程序运行起来了,这是我的代码版本。

private void InitializeMenuStatus(ToolStrip toolStrip)
{
    toolStrip.ShowItemToolTips = false;
    toolStrip.KeyUp += ToolStrip_KeyUp;
    foreach (ToolStripItem toolStripItem in toolStrip.Items)
    {
        toolStripItem.AutoToolTip = false;
        toolStripItem.MouseEnter += ToolStripItem_MouseEnter;
        toolStripItem.MouseLeave += ToolStripItem_MouseLeave;
        if (toolStripItem is ToolStripDropDownItem dropDownItem)
            InitializeMenuStatus(dropDownItem.DropDown);
    }
}

private ToolStripItem? SelectedMenuItem = null;

private void SetSelectedMenuItem(ToolStripItem? item)
{
    if (!ReferenceEquals(item, SelectedMenuItem))
    {
        SelectedMenuItem = item;
        lblStatus.Text = item?.ToolTipText ?? string.Empty;
    }
}

private void ToolStripItem_MouseEnter(object? sender, EventArgs e)
{
    if (sender is ToolStripMenuItem menuItem && menuItem.Selected)
        SetSelectedMenuItem(menuItem);
}

private void ToolStripItem_MouseLeave(object? sender, EventArgs e)
{
    SetSelectedMenuItem(null);
}

private void ToolStrip_KeyUp(object? sender, KeyEventArgs e)
{
    if (sender is ToolStripDropDownMenu dropDownMenu)
    {
        ToolStripMenuItem? menuItem = dropDownMenu.Items.OfType<ToolStripMenuItem>()
            .Where(m => m.Selected)
            .FirstOrDefault();
        SetSelectedMenuItem(menuItem);
    }
}

为什么Selected事件从来没有被添加到菜单项中,我不知道。我有suggested that it be added。如果你同意,请去显示你的支持,该请求。

  • 如果有人感兴趣的话,我花了一些时间来微调这段代码,最终制作了一个免费组件,现在作为NuGet包发布。

相关问题