C# 当添加多个子菜单项时,是否防止Windows窗体上的主菜单闪烁(重画)?
在我的应用程序中,我有一个表单,其中一个顶级菜单项的子菜单项是动态创建的。因此,我的目标是始终有一个名为“Actions”的顶级菜单项,但子项是动态生成的。我遇到的问题是,对于每个子项,我都会添加整个主菜单重绘和闪烁。问题更为明显的是,由于我猜测的更多绘制调用而添加的子菜单项越多,例如,如果我只添加一个子菜单项,它不会经常闪烁,但如果我添加15个(这对于我的应用程序来说是典型的),它几乎每次都很明显。请注意,这是使用MenuItems而不是MenuStrip,我们开发了自定义控件来支持MenuItems,但尚未转换为使用MenuStrip 我创建了一个简单的例子来演示这一点,我点击一个按钮,在每个顶级菜单项中添加15个子项(我的演示中有两个“文件”和“编辑”),您将看到它调用“DrawMenuBar”30次。下面是代码在单击按钮时所做的操作:C# 当添加多个子菜单项时,是否防止Windows窗体上的主菜单闪烁(重画)?,c#,winforms,menu,C#,Winforms,Menu,在我的应用程序中,我有一个表单,其中一个顶级菜单项的子菜单项是动态创建的。因此,我的目标是始终有一个名为“Actions”的顶级菜单项,但子项是动态生成的。我遇到的问题是,对于每个子项,我都会添加整个主菜单重绘和闪烁。问题更为明显的是,由于我猜测的更多绘制调用而添加的子菜单项越多,例如,如果我只添加一个子菜单项,它不会经常闪烁,但如果我添加15个(这对于我的应用程序来说是典型的),它几乎每次都很明显。请注意,这是使用MenuItems而不是MenuStrip,我们开发了自定义控件来支持MenuI
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);
}
}
}
但这最终会导致相同数量的draw调用。我能想到的最好办法是从主菜单中删除顶级菜单项,然后进行所需的更改,然后重新链接,但这看起来也不太好,因为菜单项消失后又重新出现。理想情况下,顶层菜单栏的可见性不会出现闪烁或任何更改,因为我不会在那里更改任何内容,而是更改子菜单项
基本上,看看除了MainMenu对象之外,是否有一种等效的方法来执行挂起/恢复布局。尝试使用方法调用。在中间写上你的菜单项添加代码。顺便说一下,按照链接查看
MSDN
上的具体代码示例 我看到了。你需要一个丑陋的反射黑客来解决这个问题。至少在您的示例代码中是这样:
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了。对不起,我忘了在我的帖子中澄清这一点。基本上是寻找与挂起/恢复布局等效的布局,但它不适用于MainMenu或MenuItem类。这正是我所希望的,能够在每次都不触发更改事件的情况下进行批量更改。@RyanR:您应该在
表单
对象上调用该函数,而不是在菜单
上。在表单对象上调用挂起/恢复布局时仍会重新绘制。谢谢,这确实有效(在我的实际项目中也尝试过)我同意,是时候转到MenuStrip了,但我想知道我是否只是错过了一些关于如何消除闪烁的东西。
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);