Windows 表单中菜单项的上下文相关帮助

Context-sensitive help for menu items in Windows Forms

我正在为 Visual Studio .NET 中内置的现有 WinForms 应用程序实施上下文相关帮助。我在表单中添加了一个 HelpProvider 并将 HelpNamespace 属性 设置为一个很棒的 .chm ,它涵盖了表单上的每个控件和菜单项。我已经在派生自 Control 的所有控件上设置了必要的 HelpKeyword,到目前为止一切都很好:F1 完美运行。

我的问题是我不知道如何为菜单项执行此操作。这些使用 ToolStripMenuItem class,它不是从 Control 派生的,因此没有 HelpKeyword 属性。我应该如何为单个菜单项提供上下文相关的帮助? Google 先生不太热情。

使用 F1 不是为菜单项提供帮助的常用方法。菜单项通常使用 ToolTip,或者在 StatusBar 中显示一些帮助文本,或者通常它们的综合帮助带有 主页的帮助内容.

我更喜欢使用上述解决方案之一,但出于学习目的,我将展示您可以使用表单的 HelpRequested 事件做什么。

要处理表单和控件的帮助,您可以依赖表单和控件的 HelpRequested 事件。

这里可以依靠Form事件来解决问题。由于您在表单上有一个 HelpProvider,您应该知道 HelpProvider 在内部处理所有控件的 HelpRequested 事件,并且对于 ShowHelp 设置为 true 的控件,它将 Handled 设置为 true 并防止事件冒泡,因此如果 ShowHelptrue,您将无法使用自定义代码来处理帮助事件。因此,您应该将控件的 ShowHelp 设置为 false 并仅使用 HelpProvider 作为帮助密钥持有者。

要解决使用表单的 HelpRequested 事件的问题,您应该按照以下步骤操作:

  1. 对于 ToolStripMenuItems,使用 Tag 属性 作为帮助密钥持有者。
  2. 对于其他控件,如果使用HelpProvider分配HelpKey,不要忘记将ShowHelp设置为false
  3. 处理表单的 HelpRequested 事件。
  4. 在事件处理程序的主体中,检查您的表单上是否有活动菜单项,然后使用活动项目的 Tag 属性 显示帮助。如果没有任何活动菜单,请使用表格的 ActiveControl 属性 显示帮助。

例子

这是一个逐步示例,说明如何使用 F1 键显示菜单项的帮助。为此,请按照下列步骤操作:

  1. 创建窗体、菜单和控件 - 创建一个 Form 并在窗体上放置一些控件和一个具有一些菜单和子菜单的 MenuStrip
  2. 配置 HelpProvider - 在表单上放置一个 HelpProvider 控件,并为每个控件分配合适的键到 HelpKeyword 属性 控件。同时将每个控件的 ShowHelp 设置为 false。我们将在代码中处理帮助。
  3. 为菜单配置帮助 - 对于 ToolStripMenuItem 使用其 Tag 属性 来存储帮助关键字。
  4. 创建辅助方法以查找菜单的后代 - 添加一个 class 到具有以下代码的应用程序。在下面的代码中,我引入了一种扩展方法来获取 MenuStrip:

    的所有子 ToolStripMenuItem
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    public static class ToolStripMenuItemExtensions
    {
        public static List<ToolStripMenuItem> Descendants(this MenuStrip menu)
        {
            var items = menu.Items.OfType<ToolStripMenuItem>().ToList();
            return items.SelectMany(x => Descendants(x)).Concat(items).ToList();
        }
        public static List<ToolStripMenuItem> Descendants(this ToolStripMenuItem item)
        {
            var items = item.DropDownItems.OfType<ToolStripMenuItem>().ToList();
            return items.SelectMany(x => Descendants(x)).Concat(items).ToList();
        }
    }
    
  5. Handling the Helprequested event to show help - 处理表单的 HelpRequested 事件并使用以下方法实现我在上面描述的算法代码:

    private void Form1_HelpRequested(object sender, HelpEventArgs hlpevent)
    {
        string keyword = "";
    
        var selectedMenuItem = this.menuStrip1.Descendants()
            .Where(x => x.Selected).FirstOrDefault();
        if (selectedMenuItem != null)
            keyword = selectedMenuItem.Tag?.ToString();
        else if (ActiveControl != null)
            keyword = helpProvider1.GetHelpKeyword(ActiveControl);
    
        if (!string.IsNullOrEmpty(keyword))
            Help.ShowHelp(this, "Help.chm", HelpNavigator.Index, keyword);
    }
    

注意

  • 为了测试解决方案,您不需要具有索引等的 chm 文件。您可以简单地以 Text 属性 形式显示帮助关键字。这意味着解决方案正在运行,之后您可以创建合适的 chm 文件。
  • 您可以根据需要使用 Help class 的 ShowHelp 方法的其他重载之一。
  • 控件有HelpKeywordHelpString扩展属性,注意你用的是哪一个,在HelpRequested事件中获取相同的。
  • 不要忘记将 ShowHelp 设置为 false。如果您忘记了这一步,事件将在 Helpprovider.
  • 内部处理
  • 不要忘记为 Tag 属性 个菜单项分配帮助关键字。为了使其对未来更友好,您可以简单地创建一个扩展程序提供程序,将帮助关键字 属性 添加到菜单项。