当添加多个子菜单项时,防止Windows窗体上的MainMenu闪烁(重绘)?

时间:2012-01-06 23:19:17

标签: c# winforms menu

在我的应用程序中,我有一个表单,对于其中一个顶级菜单项,子菜单项是动态创建的。所以目标是我总是有一个名为“Actions”的顶级菜单项,但子项是动态生成的。我遇到的问题是,对于每个子项,我添加了整个MainMenu重绘和闪烁。由于我猜测更多的绘画调用,所以添加的子菜单项越多,问题就越明显,例如,如果我只添加一个子菜单项,它不经常闪烁,但如果我添加15(其中这是我的应用程序的典型特征)它几乎每次都很明显。请注意,这是使用MenuItems而不是MenuStrip,我们开发了支持MenuItems的自定义控件,但尚未转换为使用MenuStrip。

我创建了一个简单的示例来演示这一点,我点击了一个按钮,为每个顶级菜单项添加了15个子项(我的演示“文件”和“编辑”中有两个),你会看到它调用“DrawMenuBar”30次。以下是按钮单击时代码的作用:

private void CreateSubMenus()
{
    foreach (MenuItem menu in this.Menu.MenuItems)
    {
        for (int i = 1; i <= 15; i++)
        {
                MenuItem newSubMenu = new MenuItem();
                newSubMenu.Text = "TestSub" + i;
                menu.MenuItems.Add(newSubMenu);
        }
     }
}

无法将图片嵌入为新用户,但此处是指向性能分析显示的链接Profiling Adding Sub Menus

所以DrawMenuBar被调用了30次。

我尝试过使用类似的东西:

this.Menu.MenuItems[0].AddRange(

但最终导致相同数量的绘制调用。我能想到的最好的方法是从MainMenu中删除顶级菜单项,然后进行所需的更改,然后重新链接它,但这看起来也不是很好,因为菜单项消失而不是重新出现。理想情况下,顶级菜单栏的可见性不会闪烁或有任何变化,因为我没有更改任何内容,而是更改子菜单项。

基本上,查看是否有相同的方法来执行暂停/恢复布局,但是对于MainMenu对象。

2 个答案:

答案 0 :(得分:0)

尝试使用SuspendLayout() -> ResumeLayout()方法调用。在它们中间写下添加代码的菜单项。顺便说一句,请点击链接查看MSDN上的具体代码示例。

答案 1 :(得分:0)

我明白了。你需要找到一个丑陋的反思黑客来解决这个问题。这很有用,至少可以使用您的示例代码:

        var pi = typeof(MainMenu).GetField("form", BindingFlags.NonPublic | BindingFlags.Instance);
        object form = pi.GetValue(this.Menu);
        pi.SetValue(this.Menu, null); 
        // etc..
        pi.SetValue(this.Menu, form);

时间开始支持MenuStrip。