- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我们最近升级到 VS 2012,同时升级到 .NET Framework 4.5。这引入了一个与 WinForms MenuStrip 控件相关的奇怪且讨厌的错误。同样的错误也发生在以 .NET Framework 4.0 为目标的应用程序中,因为 4.5 的安装程序显然也会更新 4.0 的部分内容。因此,一个完美工作的代码模式现在仅仅因为框架升级就被打破了。
问题描述:
我有一个带有 MenuStrip 的 Form1。对于其中一个下拉项,事件处理程序打开另一个 Form2(不一定是子级,只是另一个 Form)。如果用户右键单击新的 Form2 或其子控件之一,这会触发 ContextMenuStrip 的 Show(),则原始 Form1 会再次弹出到前台。
这独立于 Form2 中所有先前的其他 UI 操作。可以调整大小、移动、最小化、最大化 Form2、在控件之间切换、输入文本等。不知何故,Form1 的 MenuStrip 似乎记得它导致了 Form2 的打开,并在第一次右键单击时捕获了焦点。
我正在尝试不同的方法,但到目前为止无法找到解决方法。该星座并不少见,可能会影响周围的许多 WinForms 应用程序。因此,我决定将其张贴在这里,因为可行的解决方案可能会受到普遍关注。如果有人知道解决方法或至少对我有一些线索,我将非常高兴。
我能够在以下代码中提炼出它的本质。它应该可以在任何安装了 .NET 4.5 的机器上重现,并且在分别针对 4.0 和 4.5 时发生 - 但不是在 3.5 或更低版本上。
using System;
using System.Windows.Forms;
namespace RightClickProblem {
static class Program {
[STAThread]
static void Main() {
// Construct a MenuStrip with one item "Menu" with one dropdown-item "Popup"
var mainMenu = new MenuStrip();
var mainItem = new ToolStripMenuItem("Menu");
mainItem.DropDownItems.Add(new ToolStripMenuItem("Popup", null, Popup));
mainMenu.Items.Add(mainItem);
// Create form with MenuStrip and Show
var form1 = new Form();
form1.Controls.Add(mainMenu);
Application.Run(form1);
}
private static void Popup(object sender, EventArgs e) {
// Create a form with a right click handler and show
var form2 = new Form();
var contextMenu = new ContextMenuStrip();
contextMenu.Items.Add("Just an item...");
form2.ContextMenuStrip = contextMenu;
form2.Show();
// Problem: contextMenu.Show() will give focus to form1
}
}
}
编辑: 我花了一些时间单步调试 .NET Framework 源代码,发现根本原因很可能在 System.Windows.Forms.ToolStripManager 中。在那里,微软正在使用消息过滤器来跟踪窗口激活,这在某种程度上是错误地为 MenuStrip 实现的。
与此同时,我还发现 Microsoft 已经在修补程序中解决了这个问题(请参阅 http://support.microsoft.com/kb/2769674),希望这会在 .NET Framework 4.5 的 future 更新中找到解决方法。
不幸的是,很难在所有客户端计算机上强制应用此修补程序。因此,仍然会非常感谢可行的解决方法。到目前为止,我自己一直无法找到切实可行的解决方案......
EDIT#2: 最初的 KB 编号是针对 Win8 的,但在 KB 2756203 下有适用于 Win7 和 Vista 的类似修补程序。如果有人可以使用它,请在此处找到可供下载的修补程序:http://thehotfixshare.net/board/index.php?autocom=downloads&showfile=15569 .我们对其进行了测试,它确实解决了问题。如果我们很快发现肯定没有解决方法,我们将使用修补程序。
编辑#3:对 spajce 提出的已接受解决方案的评论
显然,在任何 ContextMenu 上调用 Show() 将说服原始 MenuStrip 忘记其对焦点的声明。这可以通过某种方式完成,这样虚拟的 ContextMenu 甚至不会显示在屏幕上。我找到了在任何 Form 的构造函数中插入以下代码片段的最短且最容易实现的方法:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
using (var dummyMenu = new ContextMenuStrip()) {
dummyMenu.Items.Add(new ToolStripMenuItem());
dummyMenu.Show(Point.Empty);
}
}
}
因此,每个打开的窗体都会清除 ToolStripMenu 系统的损坏状态。不妨将此代码放在 FormHelper.FixToolStripState() 之类的静态方法中,或者将其放在模板 Form 的 OnCreateControl(...) 中并从中继承所有 Forms(无论如何我们幸运地做了什么)。
最佳答案
这是我的解决方案:)
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// Construct a MenuStrip with one item "Menu" with one dropdown-item "Popup"
var mainMenu = new MenuStrip();
var mainItem = new ToolStripMenuItem("Menu");
mainItem.DropDownItems.Add(new ToolStripMenuItem("Popup", null, Popup));
mainMenu.Items.Add(mainItem);
// Create form with MenuStrip and Show
var form1 = new Form();
form1.Controls.Add(mainMenu);
Application.Run(form1);
}
private static void Popup(object sender, EventArgs e)
{
// Create a form with a right click handler and show
var form2 = new Form();
var contextMenu = new ContextMenuStrip();
contextMenu.Items.Add("Just an item...");
var loc = form2.Location; //<---- get the location
var p2 = new Point(loc.X, loc.Y); //<---- get the point of form
form2.ContextMenuStrip = contextMenu;
form2.ContextMenuStrip.Show(form2, p2); //<---- just add this code.
form2.Show();
// Problem: contextMenu.Show() will give focus to form1
}
}
关于c# - .NET 4.0/4.5 WinForms MenuStrip 窃取焦点的奇怪错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14058222/
我正在使用 Visual Studio 2019 并创建了一个 windows 窗体应用程序项目。在我放下 MenuStrip 时的表单中,它没有向我显示用于创建菜单的 Type 框。我搜索了互联网,
有没有一种简单的方法可以增加 WinForms MenuStrip 中菜单项文本与其快捷键之间的间距?如下图,即使是 VS 生成的默认模板看起来也很糟糕,文本“打印预览”超出了其他项目的快捷键: 我正
我正在创建一个带有选项卡的网络浏览器。要输入 URL,我尝试将 MenuStrip 及其 ToolStripMenuItem 设置为文本框。我正在动态创建所有控件,我有 2 个问题。 1).如何从代码
根据此处关于 SO 的许多问题,使表单背景透明的最佳方法是将其设置为相当未使用的颜色(如洋红色),然后将表单的 TransparencyKey 设置为那种颜色。 this.BackColor = Co
我有一个已添加到表单的 MenuStrip,在其中的一个下拉菜单中,我有一个文本框。当我在文本框上按下回车键时,我想要运行一个函数,然后关闭下拉菜单。我知道如何完成输入部分,但我不知道如何关闭 Men
好的,我有一个名为 Form1.menuStrip1 的 MenuStrip。 Form1.menuStrip1 有两个水平项目,分别称为“菜单”和“列表”。我想要做的是向列表菜单添加一个新的子菜单项
我想在 menustrip 和 menuStrip 右边的窗体之间留一个空隙。我使用了 autosize= false 和新的尺寸属性,menustrip 的高度改变了但宽度没有改变。 Menustr
我想在 menustrip 和 menuStrip 右边的窗体之间留一个空隙。我使用了 autosize= false 和新的尺寸属性,menustrip 的高度改变了但宽度没有改变。 Menustr
当我从 Menu-strip 控件的下拉列表中选择任何选项时,其 Click 事件中的代码被触发并且下拉列表折叠。但我希望下拉菜单必须保持打开状态。 请帮忙 如果我在单击此菜单中的项目时打开一个对话框
我需要从子窗口更改主窗口(mdi 容器)的 menuStrip 项目文本, 像这样: File -Login 到 File -Logout 最佳答案 在主窗口添加这些: public static M
当主窗体的 isMidContaine = true 时,如何禁用 MenuStrip 的 MaximizeBox。当我在某些解决方案中阅读时,我希望禁用它以不隐藏表单的 ControlBox。
是否可以在不通过表单添加实例的情况下动态创建 MenuStrip? 我已经完成了.. //Create menu MenuStrip menu = new MenuStrip(); menu.name
例如我有这个菜单点击事件: private void testToolStripMenuItem_Click(object sender, EventArgs e) {
我需要检测何时打开和关闭 MenuStrip(不是上下文菜单)。 Enter 和 Leave 事件似乎不起作用。 为什么我需要它:我使用带有"file"、“编辑”、“关于”等选项的 MenuStrip
我正在开发一个 VB Winforms 项目(尽管我对 C# 解决方案也很满意)并进行了以下设置: 我在窗体上有一个 ContextMenuStrip,msCreateReports 我在表单顶部有一
我想获取我的 MenuStrip 的所有 SubItems,因此我可以一次更改它们。 我正在尝试以下操作,但它们不起作用: foreach (ToolStripMenuItem toolItem in
这个问题在这里已经有了答案: How to change menu hover color (4 个答案) 关闭 9 年前。 我在我的应用程序中添加了一个 MenuStrip,并在 Render M
我阅读了一些关于人们如何自定义 MenuStrip 的颜色和渐变的其他文章。 我想要做的是删除渐变,使 MenuStrip 与表单的其余部分颜色相同,对我来说,这是创建新 WinForms 项目时使用
你知道如何去除 MenuStri 中子菜单的边距(可能是图像和左右复选框的边距)吗?在 MSDN article解释了如何从上下文菜单中删除它。据记载,我应该在 MenuStrip 中以相同的方式执行
我似乎找不到在 MenuStrip 中添加水平分隔符的方法。 Visual Studio 提示无法将 ToolStropSeparator 添加到 MenuStrip。 知道我该怎么做吗? 最佳答案
我是一名优秀的程序员,十分优秀!