- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在我的代码中,以下代码会使在 Windows 10 专业版上运行的应用程序崩溃。
this.ShowInTaskbar = true;
这已经在 2 台不同的机器上进行了测试。当我在 try/catch block 中包含上述代码行时,没有显示异常。当我订阅 Appdomain.UnhandledException
事件时也不异常(exception)。
事件查看器中有一个应用程序错误,事件 ID 1000
指出 System.Windows.Forms.ni.dll
中发生了错误,但我没有别的可以理解。
在 Windows 10 Professional 上运行的开发机器上也无法重现此问题。
除了 NotifyIcon
之外,表单没有其他控件。经过实验,我发现问题出在以下代码行:
private void onFormResize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized) this.ShowInTaskbar = false;
}
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
try
{
this.ShowInTaskbar = true;
this.WindowState = FormWindowState.Normal;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
如果我先更改 WindowState
,然后在任务栏上显示表单,那么一切正常。此外,如果我从 OnFormResize
中删除代码,应用程序也不会崩溃,无论 notifyIcon1_MouseDoubleClick
中的命令执行顺序如何。
最佳答案
免责声明:其中大部分是非契约(Contract)行为,所以不要把它当作权威 - Windows 和 .NET Framework 的不同版本和配置可能会对正在发生的事情产生微小的影响。
您在任务栏中显示窗口。这需要重新创建窗口,这会导致调整大小。在调整大小事件处理程序中,您将窗口隐藏在任务栏中。这需要重新创建窗口,这会导致调整大小。在调整大小事件处理程序中,您将窗口隐藏在任务栏中 - 但不会重新创建窗口,因为“我是否显示在任务栏中?”字段实际上已经更新。然而,它进入了臭名昭著的“在创建句柄时访问 Control.Handle”无限循环——这可以说是框架中的一个错误(有趣的是,如果表单被最小化或最大化,但不是“正常大小”,就会发生这种情况)。 Control.Handle
调用 Form.RecreateHandleCore
,后者调用 Control.Handle
,您就完成了 :)
为什么这不会发生在所有机器上?因为调整大小并不总是必要的。这可能与许多事情有关——UI 主题、字体大小、显示……但基本错误仍然存在——你导致了无限递归。它只是被跳过了,因为你少了一个 Resize
事件。
为什么不能捕获异常?好吧,StackOverflowException
这种方式可能有点偷偷摸摸。您正处于安全关键代码的中间,可能在 native 调用中,并且出现堆栈溢出。你具体是怎么恢复的?运行时所知道的只是堆栈保护已被击中——就其所知,有人刚刚替换了你程序的一半内存。 OutOfMemoryException
非常相似 - 您不知道如何再次进入安全状态,所以唯一的选择就是快速失败。
在 ShowInTaskbar
之前更改 WindowState
可以通过两种方式解决问题 - 第一,它会更改调整大小处理程序的工作方式 - 这是代码中的错误,并且更改窗口状态阻止该代码 (ShowInTaskbar = false
) 运行。第二个是当窗体重新创建其句柄时 Control.Handle
访问仅在窗口最小化或最大化时发生 - 这是框架部分。不用说,这是非常脆弱的 - 像这样的错误很难找到和修复。
那么,这样做的正确方法是什么?您想在窗口最小化时从任务栏中隐藏该窗口。那只是当窗口状态以前是非最小化的,变成最小化的时候——所以你需要保持旧的窗口状态并检查它。
更好的是,不要乱用 ShowInTaskbar
。看起来你让事情变得不必要的复杂,而你真正想要的只是在窗口最小化时隐藏它! Show
和 Hide
都可以,不需要完全信任,并且不会将表单保留在 Alt+Tab 菜单中。 ShowInTaskbar
适用于具有多个以某种方式连接的窗口的应用程序 - 例如显示在不同窗体之上的模态对话框,具有相同 z 顺序的多窗口界面等。如果您只需要隐藏窗体,请将其隐藏。无需继续创建和销毁所有窗口句柄 :) 我怀疑框架设计者为我们提供 ShowInTaskbar
属性的唯一原因是在设计者中提供体面的支持 - 但你不应该真正改变它在创建表单之后;给定的表单要么显示在任务栏中,要么不显示。没有理由在运行时更改它。
关于c# - 为什么 ShowInTaskbar 会毫无异常(exception)地使我的应用程序崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41823588/
应用程序是为 .NET 2.0 编译的(如果相关)。最初表单是使用 ShowInTaskbar=false 创建的,它不会出现在任务栏中,一切都很酷。但是,当某些操作(在表单上拖动文件并开始文件上传)
我在 WPF 中有一个模式窗口,对于此窗口,ShowInTaskbar 设置为 true,但对于此模型窗口,应用程序图标不会每次都显示在任务栏中。有时图标会出现在任务栏中,有时不会。但要求是当此模态窗
我不是要举办事件。我在问如何询问(使用 C#,而不是 WinAPI)“窗口是否已最小化?”。 WindowState 不够好。当 ShowInTaskbar="False" 时,在 Win+D 后这将
当应用程序的主要 Form - 传递给 Application.Run() 的那个 - 有 this.ShowInTaskBar = false; 然后,表示该应用程序的 Process 实例具有 0
我创建了一个具有以下属性的自定义分层 WPF 窗口: AllowsTransparency = True ShowInTaskbar = 假 背景 = 透明 最顶层 = 正确 Icon = "Icon
我们只想在任何时候运行我们应用程序的一个实例。因此在启动时它会查看应用程序是否正在运行,如果正在运行,它会在主窗口上调用 SetForegroundWindow。 这一切都很好......大部分...
我在基于 PRISM 的 WPF 应用程序中使用 AvalonDock。我的文档 Pane 能够 float (CanFloat =“true”)。但任务栏中不显示 float 窗口。有什么方法可以让
我有一个程序,我希望能够处理所有三种状态: 不显示在任务栏中,就像 Windows 声音、网络程序等小部件一样 显示在任务栏中 - 但不是最顶层。该窗口仍会显示通知区域图标,并且仍应以与 #1 相同的
在我的代码中,以下代码会使在 Windows 10 专业版上运行的应用程序崩溃。 this.ShowInTaskbar = true; 这已经在 2 台不同的机器上进行了测试。当我在 try/catc
我有一个应用程序 (mainApp) 打开模式对话框 (collector) 以询问登录详细信息。该对话框在右上角有一个取消按钮和一个标准关闭按钮,并且有 FormBorderStyle = Fixe
如果您在具有 2 个表单的全新 winform 应用程序中运行这段代码(将其放在 form1 中) private void Form1_Load(object sender, EventAr
在我的应用程序中,我有主窗体和子窗体。我想将子窗体的 ShowIntaskBar 设置为 false,但问题是当我通过菜单打开它时,它会快速出现和消失,然后当我再次打开它时,它会变得可见。所以我不想打
我正在尝试使用热键和任务栏托盘中的启动选项制作应用程序。 现在的问题是,使用 this.Hide()在加载事件中,不会有任何影响。我可以加this.ShowInTaskbar = false ,但在我
我正在使用配置为 FixedToolWindow 的 WinForm。我已将 ShowInTaskbar 设置为 False - 我正在使用 NotifyIcon 来管理窗口最小化后的恢复。 当我最小
我是一名优秀的程序员,十分优秀!