4

I have a form where the user can first scan to a bitmap. When scan is done, and the bitmap is loaded, I have 4 text boxes that are then enabled. Next to each text box, I have a button called "Cut from image". When the user clicks the button, they can click and drag in the bitmap to get the selected text using MODI.

This works perfect except for one annoying bug: When I click a "Cut from image" button and drag a square, it gets the information nicely to the text box. Then, if i click to the next text box, it goes very well, but if I use the tab key to leave the field, I get a "Parameter is not valid" ArgumentException and it does not show any help for where in the code the crash is made. I can tab around in the form with no problems at all, but once the bitmap is scanned, it crashes like 9 out of 10 times when I use the tab key.

I tried to override the tab key (just for debugging) using this:

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

...but it still crashes.

Any suggestions about what's wrong? Since I don't know where to begin debugging I can't tell what code to show.

EDIT 1

Here is the stack trace for the ArgumentException that gets thrown:

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

EDIT 2

Here is how I'm scanning/loading the image:

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.
Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
gubbfett
  • 2,157
  • 6
  • 32
  • 54
  • Do you have the call stack from the exception? Do you know which line in the code it is failing on? Can you show that section of the code? – Steven Doggart Dec 17 '12 at 10:54
  • Yea, but since i'm not really into VS i don't know where to really begin. Message: "Paramter not valid". Source: "System.Drawing". You want the "StackTrace" ? – gubbfett Dec 17 '12 at 11:05
  • Oh, no. I can't really see where in the code it fails. – gubbfett Dec 17 '12 at 11:06
  • Are you running the application with the debugger? If so, there should be a way to show the details of the exception and to show the stack trace. At the very least, the stack trace will show which method it happened in. – Steven Doggart Dec 17 '12 at 11:08
  • Yes i am. I just get a white screen with a blue header with "No source avalible". The StackTrace seems to write the last things at top? in that case: "at System.Drawing.Image.get_Width()" <-- very last at System.Drawing.Image.get_Size()" <-- second last But this occour after that the MODI is done and everything, and is some how realted to the tab-button...? – gubbfett Dec 17 '12 at 11:13
  • Can you paste the entire stack trace into the body of your question? – Steven Doggart Dec 17 '12 at 11:14
  • Ok, so the exception is being thrown by whatever control is displaying the bitmap. It is being asked by the system to paint itself, and in the process of doing so, it's trying to get the width of the image and that's throwing the Parameter is not valid exception. So, the question is, how are you displaying the bitmap? What kind of control is it? – Steven Doggart Dec 17 '12 at 11:27
  • It's a picturebox in a panel. I have a Collection that uses twainhandler, like this: `Dim filename As Collection` and then `filename = TwainHandler.ScanImages("c:\scan\", "tif")` And then a Image as this: `Dim ScannedFile As Image = Image.FromFile(filename(1))` and then the picturebox gets ` .image = ScannedFile`, `.width = ScannedFile.Width` and so on. What i how ever do not understand is why it works when i klick around in the form and then gets the crash when i hit the tab button? – gubbfett Dec 17 '12 at 12:26
  • Could you post the code for the method that loads the image to the body of your question? Is there any chance that you are calling `ScannedFile.Dispose` at any point? – Steven Doggart Dec 17 '12 at 12:42
  • Yes, i use dispose! But not in this image. I do use it when i read the selection made. Then i create another Bitmap wich i save to C:\crop.bmp, i then read this file with modi and then i dispose this selection and delete that file with `File.Delete("C:\crop.bmp")` – gubbfett Dec 17 '12 at 12:48
  • 1
    Try removing any place you call `Dispose` on any `Image` object and see if the error goes away. – Steven Doggart Dec 17 '12 at 12:50
  • You sir just found something. So, yes. I removed the dispose() for the temporary bitmap for reading the modi-stuff and now i don't get any errors. Why is that? – gubbfett Dec 17 '12 at 12:58
  • Yay! Glad to help. I edited your question a bit, now that we know what it was, just to make it more helpful to others having the same problem in the future. – Steven Doggart Dec 17 '12 at 13:29

3 Answers3

12

Your problem is likely that, at some point, you are calling the Dispose method on one of your Image objects. When you call Image.Dispose, it deletes the underlying image data from memory, so the Image object still exists, but is invalid because it no longer contains an actual image. When you set the PictureBox.Image property to a loaded Image object, the PictureBox control assumes that the Image object will remain valid so that it can reuse it later any time the control needs to repaint itself to the screen. For instance:

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

The PictureBox control will automatically dispose of the image for you when it is disposed, so you don't need to worry about disposing it yourself. The only time you should be disposing your images is when you are not giving them to any other objects for later use.

Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • Still funny that it worked to use the mouse to do all this and create and dispose instances, and then it crashed when i moved between the fields with tab. But now both of them works. :) – gubbfett Dec 17 '12 at 13:30
  • 1
    Yes, that's a little strange, but not entirely unexpected. When using the keyboard, for whatever reason, Windows thought your PictureBox needed to be repainted, but when using the mouse, it did not. I'm sure there's some good reason why that is. The window messages that get passed around are different when using the mouse and the keyboard. In the end, it doesn't matter, though, since sooner or later in would have needed to be repainted for some other reason such as the window being resized or something. – Steven Doggart Dec 17 '12 at 13:34
2

Here is my solution, somebody could use it, even though the question is old.

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 
Binarian
  • 12,296
  • 8
  • 53
  • 84
0

PictureBox1.Image = myImage.Clone This way you are using a copy of the image so it does not matter what happens with the original

Andrei
  • 33
  • 9