PictureBox 在选项卡按键时抛出“参数无效”ArgumentException

Posted

技术标签:

【中文标题】PictureBox 在选项卡按键时抛出“参数无效”ArgumentException【英文标题】:PictureBox throws "Parameter is not valid" ArgumentException upon tab keypress 【发布时间】:2012-12-04 10:38:00 【问题描述】:

我有一个表单,用户可以先扫描到位图。扫描完成并加载位图后,我有 4 个文本框被启用。在每个文本框旁边,我有一个名为“从图像剪切”的按钮。当用户单击按钮时,他们可以在位图中单击并拖动以使用 MODI 获取选定的文本。

除了一个烦人的错误外,这很完美:当我单击“从图像剪切”按钮并拖动一个正方形时,它会将信息很好地发送到文本框。然后,如果我单击下一个文本框,它会非常顺利,但是如果我使用 Tab 键离开该字段,我会得到一个“参数无效”ArgumentException 并且它没有显示任何帮助发生崩溃的代码。我可以毫无问题地在表单中切换,但是一旦扫描了位图,当我使用 Tab 键时,它会像 10 次中的 9 次一样崩溃。

我尝试使用以下方法覆盖 tab 键(仅用于调试):

Protected Overrides Function ProcessTabKey(ByVal forward As Boolean) As Boolean
    MsgBox("TAB is currently disabled!")
    Return False 'Tried True as well, just in case
End Function

...但它仍然崩溃。

有什么建议吗?因为我不知道从哪里开始调试,所以我不知道要显示什么代码。

编辑 1

这是被抛出的ArgumentException 的堆栈跟踪:

在 System.Drawing.Image.get_Width() 处 在 System.Drawing.Image.get_Size() 在 System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode 模式) 在 System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe) 在 System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 层) 在 System.Windows.Forms.Control.WmPaint(Message& m) 在 System.Windows.Forms.Control.WndProc(Message& m) 在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 原因,ApplicationContext 上下文) 在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 原因,ApplicationContext 上下文) 在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() 在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() 在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine) 在 ORC_Testing.My.MyApplication.Main(String[] Args) 在 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81 在 System.AppDomain._nExecuteAssembly(RuntimeAssembly 程序集,String[] args) 在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在 System.Threading.ThreadHelper.ThreadStart_Context(对象状态) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在 System.Threading.ThreadHelper.ThreadStart()

编辑 2

这是我扫描/加载图像的方式:

Dim filename As Collection
filename = TwainHandler.ScanImages("c:\scan\", "tif")
Dim ScannedFile As Image = Image.FromFile(filename(1))
PictureBox1.Image = ScannedFile
PictureBox1.Width = ScannedFile.Width
' etc.

【问题讨论】:

你有异常的调用栈吗?你知道它在代码中的哪一行失败了吗?你能展示那部分代码吗? 是的,但由于我并不真正进入 VS,所以我不知道从哪里真正开始。消息:“参数无效”。来源:“System.Drawing”。你想要“StackTrace”吗? 哦,不。我真的看不出它在代码中的哪个位置失败了。 您是否使用调试器运行应用程序?如果是这样,应该有一种方法可以显示异常的详细信息并显示堆栈跟踪。至少,堆栈跟踪会显示它发生在哪个方法中。 尝试删除您在任何Image 对象上调用Dispose 的任何地方,看看错误是否消失。 【参考方案1】:

您的问题很可能是,在某个时候,您正在对您的Image 对象之一调用Dispose 方法。当您调用Image.Dispose 时,它会从内存中删除底层图像数据,因此Image 对象仍然存在,但由于它不再包含实际图像而无效。当您将PictureBox.Image 属性设置为加载的Image 对象时,PictureBox 控件假定Image 对象将保持有效,以便以后在控件需要将自身重新绘制到屏幕上时可以重用它。例如:

Dim myImage As Image = Image.FromFile("file path")
PictureBox1.Image = myImage
PictureBox1.Refresh() ' This works
myImage.Dispose()
PictureBox1.Refresh() ' This throws an exception because it tries to access the disposed Image object

PictureBox控件会在图片被dispose的时候自动为你dispose,所以你不用担心自己dispose。唯一应该处理图像的时间是当您不将它们提供给任何其他对象以供以后使用时。

【讨论】:

非常感谢!很好的解释! 仍然很有趣,它使用鼠标来完成所有这些并创建和处理实例,然后当我使用选项卡在字段之间移动时它崩溃了。但现在他们两个都工作了。 :) 是的,这有点奇怪,但并不完全出乎意料。使用键盘时,无论出于何种原因,Windows 都认为您的 PictureBox 需要重新绘制,但使用鼠标时,它却没有。我确信这是有充分理由的。使用鼠标和键盘时,传递的窗口消息是不同的。最后,这并不重要,因为迟早会因为某些其他原因(例如调整窗口大小或其他原因)而需要重新粉刷。【参考方案2】:

这是我的解决方案,有人可以使用它,即使问题很旧。

Dim myImage As Image = Image.FromFile("file path")
PictureBox1.Image = myImage.clone // Use clone to give a new copy not a reference of image
PictureBox1.Refresh() // This works
myImage.Dispose()
PictureBox1.Refresh()  // This works also because we've a copy not reference 

【讨论】:

【参考方案3】:

PictureBox1.Image = myImage.Clone 这样您就可以使用图像的副本,因此原始图像会发生什么并不重要

【讨论】:

以上是关于PictureBox 在选项卡按键时抛出“参数无效”ArgumentException的主要内容,如果未能解决你的问题,请参考以下文章

将PictureBox添加到TabControl时“参数无效”

如果输入参数在Django模板中无效,如何抛出异常

C#中,已知图片内存的首地址(System.IntPtr类),想通过pictureBox显示于窗口,但提示“参数无效”

按键打开未聚焦的选项卡

选项卡上的按键事件行为

NoSuchMethodError 被抛出构建选项卡(脏,状态:_TabsState#fefcf):方法 '[]' 在 null 上被调用