65.9K
CodeProject 正在变化。 阅读更多。
Home

菜单项和窗体控件的状态栏文本提供程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.54/5 (12投票s)

2005 年 11 月 11 日

CPOL

17分钟阅读

viewsIcon

104727

downloadIcon

2026

为 Windows Forms 应用程序中的菜单项和窗体控件提供状态栏文本,类似于 MFC 和 Microsoft Access 应用程序中的功能。

引言

在 MFC 应用程序中,菜单项的状态栏文本是一项内置功能。在菜单资源编辑器中,您可以指定文本,然后在运行时,当您从一个菜单项移动到另一个菜单项时,每个菜单项的说明都会显示在状态栏中。默认情况下,.NET Windows Forms 应用程序缺少此功能。但是,通过使用实现 IExtenderProvider 接口的组件,可以非常轻松地添加此功能,并附带设计时支持,并且只需要手动编写一两行实际代码。此外,您还可以使用它为窗体上的任何控件添加状态栏文本,类似于 Microsoft Access 中控件的 StatusBarText 属性。

状态栏文本提供程序功能

StatusBarTextProvider 是一个 IExtenderProvider 组件,允许您为菜单项和窗体控件添加状态栏文本。当针对 .NET 2.0 构建使用时,它还支持菜单栏、工具栏和状态栏项上的状态文本。它提供以下功能:

  • 当组件被放入窗体时,MenuItem 组件、所有 Control 类型项和 ToolStripItem 组件将在其属性窗口中扩展一个额外的 StatusBar 类别,其中包含 StatusBarTextShowAsBlank 属性。以下项未扩展:FormLabelPictureBoxProgressBarScrollBarSplitterStatusBarToolBarToolStrip 以及从它们派生的控件。Form 包含控件,而其他控件无法获得显示文本所需的焦点,因此为它们设置状态栏文本没有意义。上述规则的例外是 LinkLabel,它可以获得焦点,因此可以进行扩展。
  • StatusBarText 属性用于在项获得焦点时设置要在状态栏中显示文本。
  • ShowAsBlank 属性可用于使项在获得焦点时显示空白状态栏。此属性是必需的,因为 Visual Studio .NET 设计器会将空格字符串转换为空字符串,因此不会将空白字符串序列化到代码中。将此属性设置为 true 可实现为该项设置空白状态栏文本的预期结果。
  • 提供程序可以使用应用程序主窗体的通用状态栏(即 MDI 容器),也可以使用包含它的窗体本地的状态栏(即对话框)。
  • 提供程序可以配置为在状态栏中定义的任何面板中显示状态栏文本。如果状态栏未定义面板,则它将使用状态栏的 Text 属性而不是。
  • 当针对 .NET 2.0 构建使用时,您可以将任何 ToolStripStatusLabel 组件指定为显示文本的位置。请注意,由于状态标签也可以出现在工具栏中,因此您不仅限于在应用程序状态栏中显示项的文本。
  • 该提供程序可用于单文档界面 (SDI) 和多文档界面 (MDI) 应用程序中的模态和非模态窗体。
  • 离开控件、关闭窗体、在窗体之间切换以及进入或退出菜单时,状态栏文本会正确恢复到其先前的值。
  • 可以为容器控件(如 GroupBoxPanel)以及从 UserControl 派生的类设置状态栏文本,以为它们内部没有为自己指定状态栏文本的控件提供状态栏文本。
  • UserControl 对象可以提供自己的状态栏文本提供程序,以定义它们所包含控件的状态栏文本。
  • 当针对 .NET 2.0 构建使用时,会提供两个额外的静态属性(StatusLabelProgressBar),可用于访问应用程序主状态栏上的状态标签和进度条,从而从应用程序的任何位置提供长时间运行进程的进度反馈。为了更轻松地使用它们,还提供了三个重载方法:
    • InitializeProgressBar - 用于初始化状态标签和进度条(六个重载)。
    • UpdateProgress - 用于在操作过程中更新状态标签和进度条(四个重载)。
    • ResetProgressBar - 用于在完成后重置状态标签和进度条(两个重载)。

提供的演示包含程序集、帮助文件和演示应用程序。提供了 .NET 1.1 和 .NET 2.0 的版本。请参阅帮助文件,了解将程序集安装到 Visual Studio .NET 工具箱中的详细信息。您还可以提取 StatusBarTextProvider.cs 源文件,用于您自己的项目或控件库。

在您的项目中使用的程序集

类位于程序集 EWSoftware.StatusBarText.dll 中。要使用这些类,请在您的项目中添加对它的引用。如果您需要,帮助文件包含有关如何执行此操作的详细信息。在使用来自 EWSoftware.StatusBarText 命名空间中的类的代码模块中,您将需要为 EWSoftware.StatusBarText 命名空间添加一个 using 语句(VB.NET 中的 Imports)。

当然,您必须将一个状态栏控件(.NET 1.1)或一个包含至少一个状态标签的状态栏控件(.NET 2.0)添加到您的窗体中。

.NET 1.1 设置

要定义所有 StatusBarTextProvider 实例使用的通用应用程序状态栏,以及可选的显示面板,请在主窗体的构造函数中添加类似以下的代码,以设置静态 ApplicationStatusBarApplicationDisplayPanel 属性:

// Define the default status bar to use in
// the main form's constructor
public MainForm()
{
    InitializeComponent();

    // Tell the StatusBarTextProvider component the status bar to use
    StatusBarTextProvider.ApplicationStatusBar = sbStatusBar;

    // You can also use any panel you like. The default is zero
    // (the left-most panel). For the demo, we'll use the one
    // in the middle.
    StatusBarTextProvider.ApplicationDisplayPanel = 1;
}

如果您的状态栏控件不包含面板,则可以省略设置 ApplicationDisplayPanel 属性,提供程序将使用状态栏的 Text 属性来显示文本。

.NET 2.0 设置

虽然没有正式弃用,但标准的 MainMenuToolBarStatusBar 控件已被 MenuStripToolStripStatusStrip 控件取代。事实上,旧控件默认情况下不会出现在工具箱中。当您有时间时,最好更新任何现有应用程序以使用较新控件,因为它们提供了一些新功能,例如能够将文本框、组合框或进度条控件直接放入工具栏和状态栏,并在菜单项上显示图像。

使用状态栏时,您将指定所有 StatusBarTextProvider 实例使用的状态标签工具栏项,而不是状态栏组件。在主窗体的构造函数中添加类似以下的代码,以设置静态 ApplicationStatusBar 属性。如果您的状态栏还包含一个标签和/或进度条工具栏项,您还可以设置静态 StatusLabelProgressBar 属性,为应用程序中的所有窗体提供便捷的访问,并如前所述利用提供程序上的状态方法。

// Define the default status strip label to use in
// the main form's constructor.
public MainForm()
{
    InitializeComponent();

    // Tell the StatusBarTextProvider component the component
    // to use to display the text. When using a tool strip
    // component, the ApplicationDisplayPanel property is ignored.
    StatusBarTextProvider.ApplicationStatusBar = tslStatusText;

    // Define the status label and progress bar too. This allows
    // easy access to those items from anywhere within the
    // application.
    StatusBarTextProvider.StatusLabel = tslProgressNote;
    StatusBarTextProvider.ProgressBar = tspbProgressBar;
}

由于在这种情况下使用的是工具栏项,因此始终会忽略 ApplicationDisplayPanel 属性。

实例状态栏

可以选择在代码中使用 InstanceStatusBarInstanceDisplayPanel 属性,以在逐个窗体的基础上覆盖应用程序级状态栏和显示面板设置。下面的示例代码来自演示,用于在子窗体的状态栏和主窗体的状态栏之间切换。sbMessage 是子窗体的状态栏文本提供程序,而 ucDemo.StatusBarTextProvider 用于访问出现在子窗体上的用户控件的状态栏文本提供程序。

private void chkUseDialog_CheckedChanged(object sender, System.EventArgs e)
{
    if(chkUseDialog.Checked)
    {
        // Use the dialog box's status bar when checked
        sbMessage.InstanceStatusBar = sbDialog;
        ucDemo.StatusBarTextProvider.InstanceStatusBar = sbDialog;

        // Make the instance default text the same for any nested
        // status bar text providers. If not, they pick up the
        // status bar text of the current control as the default.
        ucDemo.StatusBarTextProvider.InstanceDefaultText =
            sbMessage.InstanceDefaultText;
    }
    else
    {
        // Go back to using the main form's status bar
        sbMessage.InstanceStatusBar = null;
        ucDemo.StatusBarTextProvider.InstanceStatusBar = null;
    }
}

设计时支持

要使用 StatusBarTextProvider,只需将其从工具箱拖放到窗体上即可。完成后,窗体上的所有 MenuItem 组件、Control 类型对象和 ToolStripItem 组件将在其属性窗口中有一个额外的 StatusBar 类别。使用它,您可以设置 StatusBarTextShowAsBlank 属性。

通常,您只需在 StatusBarText 属性中输入要显示的消息。如上所述,ShowAsBlank 属性的存在是为了在您想要为某个项设置空白状态栏的极少数情况下,您可以将其设置为 true。设计器会将仅包含空格的字符串转换为空字符串。由于这是默认值,因此不会将其序列化到代码中,因此需要此额外属性。

TabControl 和 TabPage 控件上的状态栏文本

TabControlTabPage 控件由于处理焦点的方式不同,其状态栏文本的显示可能不总是可靠。已采取措施允许在这些控件上显示状态栏文本,但存在几个已知问题且无解决方法。

  • 最重要的是,您需要将 ShowAsBlank 属性设置为 true,或者为 TabControl 本身定义一些 StatusBarText,以便为单个选项卡页显示状态栏文本。这指的是当页面上的控件没有状态栏文本时,或当选项卡本身获得焦点时显示的文本。与其他容器控件一样,如果您未为选项卡页定义状态栏文本,则将显示选项卡控件的状态栏文本。
  • 如果使用 Shift+Tab 从选项卡上的第一个控件返回到选项卡本身,或者偶尔在窗体打开时它是第一个获得焦点的控件,则选项卡控件将不会显示状态栏文本。从一个选项卡切换到另一个选项卡,或将焦点移到选项卡控件外部的控件然后再次移回选项卡控件,将再次开始显示选项卡的状态栏文本。

关于设计器的最后一个注意事项:在设置选项卡页的状态栏文本时,请务必实际单击选项卡页的某个部分以确保其被选中。如果您仅单击选项卡控件标题中的选项卡进行选择,则焦点将由选项卡控件在设计器中获得,您可能会无意中修改选项卡控件的状态栏文本,而不是选项卡页的文本。

工具栏项上的状态文本

.NET 2.0 下,可以为菜单栏、工具栏和状态栏项指定状态栏文本。但是,存在一些限制且无解决方法。

  • 对于菜单栏项,仅在鼠标移入和移出菜单项时显示文本。如果使用键盘导航菜单,则不显示状态文本。遗憾的是,菜单栏项不像 .NET 1.1 中的菜单项那样触发选择事件,因此在这种情况下无法为它们显示文本。
  • 对于工具栏和状态栏项,当鼠标悬停在它们上面时会显示状态文本。此外,如果您制表符进入组合框或文本框,状态文本将更新。但是,当制表符进入按钮控件时,不会显示状态文本。与菜单栏项一样,没有可供挂钩以启用它的选择事件。
  • 使用此控件的先前 .NET 1.1 版本时,在从窗体移到菜单再返回到窗体时,始终可以恢复先前文本。然而,在 .NET 2.0 中,考虑到上述限制,我不得不做出妥协并重构原始状态栏文本的恢复方式。这会影响 .NET 1.1 和 .NET 2.0 下的组件。因此,在某些情况下,当从菜单返回到窗体时,当前控件的状态栏文本将不会显示。相反,状态栏中将显示默认文本。制表符移出控件再移入会再次显示正确的文本。

工作原理

要创建扩展提供程序,您需要从 Component 派生一个类并实现 IExtenderProvider 接口。该接口包含一个方法(CanExtend),该方法根据是否可以向其作为参数接收的对象提供其属性,返回 truefalse。在这种情况下,我们检查传入对象的类型,以确定它是否是我们能够扩展的对象。

在以下代码中,DOTNET_20 定义用于条件编译与支持 .NET 2.0 组件所需的修改相关的代码。它定义在文件顶部。注释掉它以在 .NET 1.1 下构建代码。

public class StatusBarTextProvider : Component, IExtenderProvider
{
    /// <summary>
    /// Default constructor
    /// </summary>
    public StatusBarTextProvider()
    {
        htOptions = new Hashtable(25);
    }

    /// <summary>
    /// Constructor. This one takes a reference to a container.
    /// </summary>
    /// <param name="container">The container for the
    /// component</param>
    public StatusBarTextProvider(IContainer container) : this()
    {
        if(container != null)
            container.Add(this);
    }

    /// <summary>
    /// This is implemented to determine if the component can be
    /// extended with the extra properties.
    /// </summary>
    /// <param name="extendee">The object to check</param>
    public bool CanExtend(object extendee)
    {
        // MenuItem is a Component. LinkLabel derives from Label but
        // it can gain the focus and thus can be extended. For .NET 2.0,
        // we also support the ToolStripItem component.
#if !DOTNET_20
        if(extendee is MenuItem || extendee is LinkLabel)
#else
        if(extendee is MenuItem || extendee is LinkLabel ||
          extendee is ToolStripItem)
#endif
            return true;

        // Non-Control types, Form, and these specific controls can't be
        // extended as it doesn't make sense for them as they don't gain
        // the focus needed to display the text.
        if(!(extendee is Control) || extendee is Form ||
          extendee is Label || extendee is PictureBox ||
          extendee is ProgressBar || extendee is ScrollBar ||
          extendee is Splitter || extendee is StatusBar ||
#if !DOTNET_20
          extendee is ToolBar)
#else
          extendee is ToolBar || extendee is ToolStrip)
#endif
            return false;

        // All other Control types can be extended
        return true;
    }
}

此外,您需要为将提供的每个扩展属性指定类上的 ProvideProperty 属性。该属性采用属性的名称和它适用的类型。在 StatusBarTextProvider 的情况下,我选择将 Component 指定为类型,以便它可以通用地应用于菜单项、控件和工具栏项。

[ProvideProperty("StatusBarText", typeof(Component)),
 ProvideProperty("ShowAsBlank", typeof(Component))]
public class StatusBarTextProvider : Component, IExtenderProvider
{
    ... class code ...
}

下一步是实际实现提供的属性代码。虽然它们在设计器中表现得像属性,但实际上您需要创建两个方法(一个 GetXXX 方法和一个 SetXXX 方法,其中 XXX 是属性的名称)。Get 方法接收对正在扩展的对象的引用。Set 方法接收对正在扩展的对象的引用以及扩展属性的值。对象类型应与属性中指定的类型匹配。Set 方法接收的值参数的类型可以是您需要的任何类型。在内部,您可以自由地按自己的意愿跟踪和存储值。最简单的方法是创建一个哈希表,并使用对象作为键,使用值参数作为哈希表条目的值。如果您提供多个属性(如 StatusBarTextProvider 的情况),则创建单独的类来存储属性并将其用作哈希表项会很有价值。

/// <summary>
/// This class contains the options for the items that need status
/// bar text.
/// </summary>
private sealed class PropertyOptions
{
    //============================================================
    // Private data member

    private string message;
    private bool showAsBlank;

    //============================================================
    // Properties

    /// <summary>
    /// Set or get the message text
    /// </summary>
    public string Message
    {
        get { return message; }
        set { message = value; }
    }

    /// <summary>
    /// The "show as blank" flag
    /// </summary>
    public bool ShowAsBlank
    {
        get { return showAsBlank; }
        set { showAsBlank = value; }
    }

    //============================================================
    // Methods, etc.

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="msg">The message text to display</param>
    /// <overloads>There are two overloads for the
    /// constructor</overloads>
    public PropertyOptions(string msg)
    {
        message = msg;
    }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="showBlank">The "show as blank"
    /// flag</param>
    public PropertyOptions(bool showBlank)
    {
        showAsBlank = showBlank;
    }
}

这是一个 StatusBarText 属性的 Get 方法示例。在进行一些检查以确保传入的组件有效且受支持后,它只是检查哈希表是否包含该组件。如果包含,它会将哈希表中的值强制转换为我们上面的属性选项类,并从中返回消息文本。如果哈希表尚不包含该组件,它将返回 null。另请注意,您可以在 Get 方法上提供设计时属性,如 CategoryDefaultValue 等,以提供更好的设计器支持的扩展提供程序。

/// <summary>
/// This is used to retrieve the status bar text for a component.
/// </summary>
/// <param name="comp">The component for which to get the
/// status bar text</param>
/// <returns>The message string if found or null if not
/// found</returns>
[Category("StatusBar"), Localizable(true), DefaultValue(null),
  Description("The status bar text for the item")]
public string GetStatusBarText(Component comp)
{
    if(comp == null)
        throw new ArgumentException("Component cannot be null");

#if !DOTNET_20
    if(!(comp is MenuItem) && !(comp is Control))
#else
    if(!(comp is MenuItem) && !(comp is Control) &&
      !(comp is ToolStripItem))
#endif
        throw new ArgumentException(
            "Component must be a MenuItem, ToolStripItem, " +
                "or a Control");

    if(htOptions.Contains(comp))
        return ((PropertyOptions)htOptions[comp]).Message;

    return null;
}

Set 方法的工作方式类似。如果哈希表不包含该组件,则创建属性类的实例,将其值存储在其中,并将其添加到哈希表中。如果组件已在哈希表中,则只需检索现有设置并用新值更新它们。

StatusBarTextProvider 的情况下,事情会变得更复杂一些。除了存储属性值外,我们还需要挂钩几个事件,以便在各种控件和菜单项获得和失去焦点时调整状态栏文本。第一部分相当简单。我们检查以确保对象有效,并创建一些辅助变量,这些变量将使我们能够确定对象的类型,以便我们可以挂钩或断开适当的事件。

/// <summary>
/// This stores the status bar text for the specified component.
/// </summary>
/// <param name="comp">The component associated with the
/// message</param>
/// <param name="message">The status bar text for the
/// component</param>
public void SetStatusBarText(Component comp, string message)
{
    if(comp == null)
        throw new ArgumentException("Component cannot be null");

    MenuItem mi = comp as MenuItem;
    Control ctl = comp as Control;
    TabControl tc = comp as TabControl;

#if DOTNET_20
    ToolStripItem ti = comp as ToolStripItem;
    ToolStripControlHost tsch = comp as ToolStripControlHost;

    if(mi == null && ti == null && ctl == null)
#else
    if(mi == null && ctl == null)
#endif
        throw new ArgumentException(
            "Component must be a MenuItem, " +
            "ToolStripItem, or a Control");

    if(message != null && message.Length == 0)
        message = null;

如果哈希表尚未包含该对象,我们则创建一个包含消息的新属性对象,并使用该对象作为键将其添加到哈希表中。然后,基于对象类型,我们挂钩一个或多个事件处理程序,这些处理程序将显示适当的状态栏文本。但此步骤在设计时会被跳过。对于 MenuItem 对象,我们挂钩 Select 事件。对于 ToolStripItem 对象,我们挂钩 MouseEnterMouseLeave 事件。如果工具栏项是 ToolStripControlHost(即,它托管组合框或文本框等控件),我们还挂钩 EnterLeave 事件,以便在制表符进入控件时显示状态文本。对于所有其他标准窗体控件,我们挂钩 GotFocusEnterLeave 事件。某些控件(如 Panel)无法获得焦点但会被进入,这就是为什么使用 GotFocusEnter

如果是选项卡控件,我们还必须挂钩 SelectedIndexChanged 事件,以允许显示其及其页面的状态栏文本。由于选项卡控件和选项卡页处理焦点的方式,它们的状态栏文本显示不一定可靠。因此,此事件对于更新文本至关重要。请注意,如果您使用 Shift+Tab 从选项卡上的第一个控件返回到选项卡控件中的选项卡本身,或者当它是第一个获得焦点的控件时,它将不会显示文本。如果您想使选项卡页本身(即当选项卡本身获得焦点时)显示状态栏文本,您还必须在选项卡控件本身上设置 ShowAsBlankStatusBarText

if(!htOptions.Contains(comp))
{
    htOptions.Add(comp, new PropertyOptions(message));

    if(!this.DesignMode && message != null)
        if(mi != null)
            mi.Select += new EventHandler(Menu_Select);
        else
#if DOTNET_20
            if(ti != null)
            {
                ti.MouseEnter += new EventHandler(Control_Enter);
                ti.MouseLeave += new EventHandler(Control_Leave);

                // If it's a control host, hook the enter and
                // leave events too.
                if(tsch != null)
                {
                    tsch.Enter += new EventHandler(Control_Enter);
                    tsch.Leave += new EventHandler(Control_Leave);
                }
            }
            else
#endif
            {
                ctl.GotFocus += new EventHandler(Control_Enter);
                ctl.Enter += new EventHandler(Control_Enter);
                ctl.Leave += new EventHandler(Control_Leave);

                // See article notes above
                if(tc != null)
                    tc.SelectedIndexChanged += new EventHandler(
                        Control_Enter);
            }
}

如果对象已存在于哈希表中,我们需要更新现有属性设置中的值。此外,如果属性被清除(即设置为 null 或空字符串),我们需要断开事件。同样,如果是在设计时完成的,则会跳过此操作。

else
{
    PropertyOptions po = (PropertyOptions)htOptions[comp];
    po.Message = message;

    if(!this.DesignMode && message == null &&
      po.ShowAsBlank == false)
        if(mi != null)
            mi.Select -= new EventHandler(Menu_Select);
        else
#if DOTNET_20
            if(ti != null)
            {
                ti.MouseEnter -= new EventHandler(Control_Enter);
                ti.MouseLeave -= new EventHandler(Control_Leave);

                // If it's a control host, unhook the enter and
                // leave events too.
                if(tsch != null)
                {
                    tsch.Enter -= new EventHandler(Control_Enter);
                    tsch.Leave -= new EventHandler(Control_Leave);
                }
            }
            else
#endif
            {
                ctl.GotFocus -= new EventHandler(Control_Enter);
                ctl.Enter -= new EventHandler(Control_Enter);
                ctl.Leave -= new EventHandler(Control_Leave);

                if(tc != null)
                    tc.SelectedIndexChanged -= new EventHandler(
                        Control_Enter);
            }
}

菜单项事件处理程序

事件处理程序是大部分操作发生的地方。对于菜单项,Menu_Select 事件处理项的状态栏文本设置。此外,首次调用时,它还会挂钩父窗体的 MenuComplete 事件上的事件处理程序,以便它可以恢复在项文本之前状态栏中的文本。StatusBarCurrentStatusBarTextItemTextStatusBarDefaultText 属性用于获取对当前状态栏、其当前文本、项文本和基于当前设置(即,它使用的是应用程序状态栏还是对话框中的实例)的默认状态栏文本的引用。

// This is handled to display status bar text for a MenuItem
// component.
private void Menu_Select(object sender, EventArgs e)
{
    if(this.StatusBar == null || !htOptions.Contains(sender))
        return;

    // Hook the MenuComplete event on first use to restore
    // the existing status bar text.
    if(!hookedMenuEvents)
    {
        Form frm = this.StatusBarParentForm;

        if(frm != null)
        {
            frm.MenuComplete += new EventHandler(
                Form_MenuComplete);
            hookedMenuEvents = true;
        }
    }

    this.CurrentStatusBarText = this.ItemText(sender);
}

// This is handled so that the old status bar text is restored
// when the component status bar text is no longer needed.
private void Form_MenuComplete(object sender, System.EventArgs e)
{
    if(this.StatusBar == null)
        return;

    this.CurrentStatusBarText = this.StatusBarDefaultText;
}

其他控件事件处理程序

对于所有其他控件,使用 Control_EnterControl_Leave 事件。首次使用时,Control_Enter 处理程序会在父窗体的 ActivatedDeactivatedClosed 事件上挂钩事件,以便可以恢复现有状态栏文本。

// This is handled to display status bar text when a control
// is entered or gains the focus.
private void Control_Enter(object sender, EventArgs e)
{
    if(this.StatusBar == null || !htOptions.Contains(sender))
        return;

    // Hook the Closed event to reset the status bar text
    // when the form is closed. When it's modal, it doesn't
    // always get the Leave event to reset the text. The
    // Activated and Deactivated events are also hooked to
    // set and restore the text.
    if(!hookedFormEvent && this.StatusBar != null)
    {
        Control p = sender as Control;

        if(p != null)
            p = p.Parent;
#if DOTNET_20
        else    // It's a control hosted in a tool strip item
            p = ((ToolStripItem)sender).Owner.Parent;
#endif

        while(p != null)
        {
            Form frm = p as Form;

            if(frm != null)
            {
                frm.Activated += new EventHandler(
                    Form_Activated);

                // Same handler as Form.MenuComplete
                frm.Deactivate += new EventHandler(
                    Form_MenuComplete);
                frm.Closed += new EventHandler(
                    Form_MenuComplete);

                hookedFormEvent = true;
                break;
            }

            p = p.Parent;
        }
    }

    this.CurrentStatusBarText = this.ItemText(sender);
}

// This is handled to display status bar text when a control
// is left.
private void Control_Leave(object sender, EventArgs e)
{
    if(this.StatusBar == null || !htOptions.Contains(sender))
        return;

    this.CurrentStatusBarText = this.StatusBarDefaultText;
}

// This is handled to redisplay the status bar text for the
// form's focused control when activated.
private void Form_Activated(object sender, System.EventArgs e)
{
    Form frm = sender as Form;

    if(frm != null && this.StatusBar != null)
    {
        Control ctl = frm.ActiveControl;

        // Nested controls may not have any so walk up
        // the parent chain to see if they do.
        while(ctl != null && !htOptions.Contains(ctl))
            ctl = ctl.Parent;

        if(ctl != null)
            this.CurrentStatusBarText = this.ItemText(ctl);
    }
}

演示应用程序

提供了 C# 和 VB.NET 的 Windows Forms 应用程序,演示了状态栏文本提供程序的基本用法。为 .NET 1.1 和 .NET 2.0 提供了每个版本的版本。 .NET 1.1 版本演示了提供程序在模态和非模态窗体中的菜单项和控件上的使用。 .NET 2.0 版本演示了提供程序在菜单栏、工具栏和状态栏项以及模态和非模态窗体中的标准控件上的使用。它还演示了使用额外的 StatusLabelProgressBar 属性从演示对话框窗体中的应用程序任何位置访问状态标签和进度条。

对于任一版本,请使用 **文件 | 加载** 选项打开演示窗体的非模态实例。使用 **帮助 | 关于** 选项打开演示窗体的模态实例。演示窗体允许您在应用程序的状态栏/状态栏和演示窗体的状态栏之间切换以显示消息。

修订历史

06/26/2006 StatusBarTextProvider 添加了新的重载静态方法,以便更轻松地使用分配给其 StatusLabelProgressBar 属性的控件。
01/28/2006

更新了组件以支持新的 .NET 2.0 菜单栏、工具栏和状态栏控件及其相关的工具栏项组件。

ApplicationStatusBarInstanceStatusBar 属性的数据类型更改为 object,以支持指定状态栏对象或将显示文本的工具栏项。此更改可能会破坏现有代码,如果它依赖于数据类型为 StatusBar(如先前版本)。

由于新的工具栏组件的工作方式,重构了先前文本的恢复方式。现在它利用了新的 ApplicationDefaultTextInstanceDefaultText 属性。

为 .NET 2.0 添加了新的 StatusLabelProgressBar 属性,以便从应用程序的任何位置方便地访问它们所代表的工具栏项。

11/11/2005 首次发布
© . All rights reserved.