2012-12-17 114 views
4

我有一个窗体,用户可以先扫描到位图。扫描完成后,位图被加载,我有4个文本框,然后启用。在每个文本框旁边,我有一个名为“从图像剪切”的按钮。当用户点击按钮时,他们可以点击并拖动位图以使用MODI获取选定的文本。PictureBox抛出“Parameter is not valid”ArgumentException当选项卡按下

除了一个令人讨厌的bug之外,这个工作非常完美:当我点击一个“从图像剪切”按钮并拖动一个正方形时,它可以很好地将文字信息提供给文本框。然后,如果我点击下一个文本框,它会非常好,但如果我使用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 

...但它仍然崩溃。

有什么不对的建议吗?由于我不知道从哪里开始调试,我不知道要显示哪些代码。

EDIT 1

下面是ArgumentException堆栈跟踪获取引发:在System.Drawing.Image.get_Width

  • ()
  • 在System.Drawing.Image对象。 get_Size()
  • at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
  • at System.Win dows.Forms.PictureBox.OnPaint(PaintEventArgs的PE)
  • 在System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs的E,Int16类型层)
  • 在System.Windows.Forms.Control.WmPaint(消息&米)
  • 在System.Windows.Forms.Control.WndProc(消息&米)
  • 在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息&米)
  • 在System.Windows.Forms.Control.ControlNativeWindow .WndProc(消息&米)
  • 在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr的的HWND,MSG的Int32,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原因,的Int32 pvLoopData)
  • 在System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(的Int32原因,ApplicationContext的上下文)
  • at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason,ApplicationContext context)
  • at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase。OnRun()
  • 在Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
  • 在Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(字符串[] COMMANDLINE)
  • 在ORC_Testing.My.MyApplication.Main(字符串[]参数)在17d14f5c-a337-4978-8281-53493378c1071.vb:线81
  • 在System.AppDomain._nExecuteAssembly(RuntimeAssembly组件,字串[] args)
  • 在System.AppDomain.ExecuteAssembly(字符串assemblyFile,证据assemblySecurity,字串[] args)
  • 微软。 VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
  • 在System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
  • 在System.Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回调,对象的状态,布尔ignoreSyncCtx)
  • 在System.Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回调,对象状态)
  • 在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. 
+0

你有没有从异常调用堆栈?你知道代码中的哪一行失败吗?你能展示代码的那一部分吗? –

+0

是的,但因为我不是很喜欢我VS不知道从哪里真正开始。消息:“参数无效”。来源:“System.Drawing”。你想要“StackTrace”? – gubbfett

+0

哦,不。我无法真正看到代码失败的地方。 – gubbfett

回答

9

你的问题可能是,在某些时候,你在呼唤你的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控制将自动为您处理的图像,所以您不必担心自己处置它。你应该设置你的图像的唯一情况是,当你不给他们以供以后使用的任何其他对象。

+0

非常感谢!很好的解释! – gubbfett

+0

仍然有趣的是,它使用鼠标来完成所有这些工作,并创建和处理实例,然后当我在带有选项卡的字段之间移动时,它崩溃了。但现在它们都起作用了。 :) – gubbfett

+1

是的,这有点奇怪,但并不完全出乎意料。在使用键盘时,无论出于何种原因,Windows都认为您的PictureBox需要重新粉刷,但使用鼠标时,它不会。我确信这有一个很好的理由。使用鼠标和键盘时,传递的窗口消息是不同的。然而,最终,这并不重要,因为迟早会需要重新绘制其他原因,例如窗口被调整大小等等。 –

0

PictureBox1.Image = myImage.Clone 您使用的是图像的副本,以便没关系与原

1

这里发生了什么这种方式是我的解决方案,有人可能会使用它,即使问题老了。

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 
相关问题