VB.NET: running out of memory in System.Drawing.dll - vb.net

I'm trying to teach myself programming, and I'm making an auto-graphing program that submits data to excel and returns a graph. The code is as follows:
Saving the file and exporting it:
' On program activation, establish an I/O stream for the database and load the graph
Private Sub Form1_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
' Open the database
xlWorkBook = xlApp.Workbooks.Open(DatabasePath + "Database.xlsx")
' Set the relevant worksheet
xlWorkSheet = xlWorkBook.Sheets("Sheet1")
' Set the display status of the database
xlApp.Visible = False
' Clear the picture box before exporting to prevent the compiler from accessing a file already in use
If Not (Graph.Image Is Nothing) Then
Graph.Image.Dispose()
End If
' Export the graph
xlWorkSheet.ChartObjects(1).chart.Export(FileName:=DatabasePath + ("Graph.gif"), FilterName:="gif")
' Load the saved graph image into the userform
Graph.Image = Image.FromFile(DatabasePath + ("Graph.gif"))
End Sub
It won't load the file on form activation though.
The system error comes when I utilize another piece of code, that updates relevant cells in the excel file and changes the data that is graphed. The cells are updated using a textbox change event in the userform:
Private Sub Proposed_Dollars_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Proposed_Dollars.TextChanged
' Export the data values
xlWorkSheet.Range("Q10").Value = Proposed_Dollars.Text()
' Clear the picture box before exporting to prevent the compiler from accessing a file already in use
If Not (Graph.Image Is Nothing) Then
Graph.Image.Dispose()
End If
' Export the graph
xlWorkSheet.ChartObjects(1).chart.Export(FileName:=DatabasePath + ("Graph.gif"), FilterName:="GIF")
' Load the saved graph image into the userform
Graph.Image = Image.FromFile(DatabasePath + ("Graph.gif"))
End Sub
Are there any obvious memory leaks that I'm missing that would cause the program to not load the graph into the userform picturebox?
I appreciate any help that is given.

It is fine to save the data back to the excel file, but force it to paint the graph every char is too much. What you should be doing instead is loading some variables from the excel file, allow the user to change the data, which would change the variables, then you use the Paint event to Draw the entire graph and use the variables to display the lines, rectangles, ellipses, etc... Look into GDI+ it can do everything you need.

Related

VB.Net Print Form to PDF Printer

I am trying (and failing) right now to print a Windows Form as a PDF File in VB.Net
Now I know from doing some research that VB.Net does not have any built in function which could allow me to do this without using a third party application.
My way to get around this, was to attempt to print my Form using a PDF Printer, since logically that should work no? My issue is getting that to work properly.
This is currently my code for attempting to print:
Private Sub SelectPrinterThenPrint()
Dim PrintersDialog As New PrintDialog()
If PrintersDialog.SHowDialog(Me) = System.Forms.DialogResult.OK Then
Try
p_Document = New PrintDocument()
PrintersDialog.Document = p_Document
AddHandler p_Document.PrintPage, AddressOf HandleOnPrintPage
Catch ex As Exception
End Try
End If
End Sub
Private Sub HandleOnPrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs) Handles p_Document.PrintPage
Dim MorePagesPending = False
Dim bmp As New Bitmap(pnlContainer.Width, pnlContainer.Height)
pnlContainer.DrawToBitmap(bmp, pnlContainer.ClientRectangle)
e.Graphics.DrawImage(bmp, New Point(0,0))
If MorePagesPending Then
e.HasMorePages = True
Else
e.HasMorePages = False
End If
End Sub
The SelectPrinterThenPrint() method is called when a button on my Form is clicked. Right now I am having two issues.
1) I don't know how to setup where the file gets saved. The Print Dialog opens, and I get to select my PDF Printer, but it doesn't let me set a filename. So how do I set the filename I want to be printing to?
2) Because I can't tell if the file is actually being saved, I can't tell if I am actually setting up the print properly or not. I am trying to print the entire contents of a panel, which holds all the elements I want on my PDF file. One thing I am unsure about however, is that the form the panel is displayed in, is not the same size as the panel. The Form the panel is in has the same width, but not the same height, with the form being set up for auto scrolling. Will I get the whole Panel to print? Or just the part the is visible in the form at the time of printing?

Controls not populated when form loaded for second time

I've got a program which calls a second form. This second form has a combo box populated from the contents of an external file, and the user needs to select an option in the combo box from the presented options. This selection is then passed back to the main form where a lot of work is done.
This all works nicely the first time it is done. However, the second time this second form is called, the drop-down is blank. I've confirmed via some debugging that the correct code is being run and that entries are being added via "SecondForm.ComboBox1.Items.Add" (I can clear the combobox, check it's zero, read the data and then check the items in the list again, it increases correctly) but they're just not being displayed on the form. I can't figure out why or how to fix it.
And so the pertinent parts of the code....
At the form level I have this line to set up the second form, I believe I need the WithEvents to pass the selected data back as far as I can tell:
Public Class Form1 Friend WithEvents SecondForm As New Form2
Public Sub OpenStripformatstxtToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenStripformatstxtToolStripMenuItem.Click
Dim fd As OpenFileDialog = New OpenFileDialog()
Dim pos1 As Integer
Dim pos2 As Integer
' Select the file to open
fd.Title = "Open File Dialog"
fd.InitialDirectory = "C:\BEST\Data"
fd.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
fd.FilterIndex = 1
fd.RestoreDirectory = True
' Put the filename selected in strfilename2
If fd.ShowDialog() = DialogResult.OK Then
strFileName2 = fd.FileName
Else : Return
End If
If SecondForm.IsDisposed Then
Dim secondform As New Form2
I suspect this line above is the problem, I'm creating the form a second time but WITHOUT the WithEvents paramater. However I can't use that from within this part of the code, I get an error "'WithEvents' is not a valid local variable declaration". I've read that closing and reopening forms is not good coding and that I should be hiding / showing them
secondform.Show()
InitializeComponent()
Else
SecondForm.Show()
End If
' Copy the file contents to a string called sfcontents (Strip Format Contents)
sfcontents = My.Computer.FileSystem.ReadAllText(fd.FileName)
' Define some points in the string, starting at the beginning
pos1 = 1
pos2 = 1
' Loop from the start to the end of the string
For pos1 = 1 To Len(sfcontents)
' Look for FO, the strip name header, do the following if you find it
If Mid(sfcontents, pos1, 3) = "FO " Then
pos1 = pos1 + 3
pos2 = pos1 + 1
'Find the space after "FO " so we've captured the whole next word, that's the strip name
Do Until Mid(sfcontents, pos2, 1) = " "
pos2 = pos2 + 1
Loop
' Add that strip name to the combobox for selecting by user
SecondForm.ComboBox1.Items.Add(Mid(sfcontents, pos1, pos2 - pos1))
It is this line above which is populating the ComboBox, but that data is NOT being displayed on the form which is shown to the user after the first instance of the form is shown
End If
' Next step in the string
Next pos1
End Sub
Private Sub secondform_formclosing(sender As Object, e As FormClosingEventArgs) Handles SecondForm.FormClosing
There's a few hundred lines of code in here which then work with the data passed from the form closing, ie the selected value of the ComboBox. This all works fine for the first running of the code, but as the ComboBox is empty on subsequent runs, it doesn't work after that. Happy to post that code if anyone thinks it'll help, but I think it'll just muddy the issue at this stage as that code seems fine. However, see the bit below about event handlers...
End Sub
The code on Form2.vb is as follows:
Public Class Form2
Public selectedstrip As String '= ComboBox1.SelectedItem
Public stripfunction As Integer
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If RadioButton1.Checked Then stripfunction = 1
If RadioButton2.Checked Then stripfunction = 2
If RadioButton3.Checked Then stripfunction = 3
selectedstrip = ComboBox1.SelectedItem
Me.Close()
End Sub
End Class
I've read a bit online that says closing and reopening forms is not, excuse the pun, good form. However I'd then need event handlers for form.hide and I can't seem to work out how to use them or even what they are. If hiding the form is a better alternative solution, if someone could point me in the right direction for how to do that and what handlers to use instead, then I'd be grateful.
I'm probably doing something incredibly stupid, because everything I'm doing is self-taught from googling and I probably lack a greater understanding of WHY I need to do certain things, so apologies for any ignorance on my part. With that in mind, if I'm doing anything a completely silly way I'm open to rewriting it in a way that helps, but I may need some hand-holding to do that!
Thanks in advance for any help anyone can give.
The main problem appears to he here:
If SecondForm.IsDisposed Then
Dim secondform As New Form2
You are declaring a new local variable there and assigning the new Form2 object to that rather than the member variable, so when you later refer to the member variable to populate the ComboBox, you're not referring to the Form2 instance you just created.
Your code is rather weird anyway. Here's my advice.
Firstly, get rid of the code form Form1 that populates the ComboBox in Form2. Forms should populate their own controls. Put the code to populate the ComboBox in the Load event handler of Form2. You're then guaranteed that any time you call Show on a new instance of Form2, the code to populate the ComboBox will be executed. That's how a form should work.
As an alternative, given that you're reading from a file and that data probably won't change over the course of a session, read the data and put it into an array in Load event handler of Form1 and then pass that array to the constructor of Form2. You would have to write that constructor yourself and, in it, you would populate the ComboBox with the array data. That way, you're not reading and processing the same data file over and over but you're still populating Form2's controls in Form2.
Secondly, change this code:
If SecondForm.IsDisposed Then
Dim secondform As New Form2
secondform.Show()
InitializeComponent()
Else
SecondForm.Show()
End If
to this:
If SecondForm.IsDisposed Then
'Create and display a new instance.
Secondform = New Form2
Secondform.Show()
Else
'Focus the existing instance.
SecondForm.Activate()
End If
Note that there is no local variable, so the new instance is assigned to the member variable.
There is also no call to InitializeComponent. That method is what creates and configures the controls on a form based on the actions in the designer. The ONLY place that gets called is in a constructor.
Finally, if an instance of Form2 is already displayed, its Activate method is called to make sure that it has focus.

Trouble saving ALL listbox data

Ok, so i'm trying to make an Injector. To load the DLLs, I used a File Dialog to select the DLL then write the info to a List Box. Now I want to save the data in the list box and reload the past data on the Form Load, but every method I have tried only saves the name of the DLL not the other info such as Location.
I would like to have no external files IF possible. Any solutions?
Cheers.
Edit: Source code for Open File Dialog
Private Sub OpenFileDialog1_FileOk(sender As Object, e As
System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
Dim FileName As String = OpenFileDialog1.FileName.Substring(OpenFileDialog1.FileName.LastIndexOf("\"))
Dim DLLfileName As String = FileName.Replace("\", "")
ListBox1.Items.Add(DLLfileName)
dlls.Add(DLLfileName, OpenFileDialog1.FileName)
End Sub

saving image from picturebox using savefile dialog problem please hep

I have the following code in VB 2010:
'>>>>>CODE FOR SAVING THE CAPTURED IMAGE<<<<<
Private Sub btnSaveSpecimen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveSpecimen.Click
'Saves the Image Captured
Dim Result As DialogResult 'variable declarations
Dim cap_image As Image
'opens a save dialog box for saving the settings
Result = savCaptured.ShowDialog
If Result = DialogResult.OK Then
cap_image = picSpecimen.Image
cap_image.Save(savCaptured.FileName, System.Drawing.Imaging.ImageFormat.Jpeg)
End If
End Sub
When I run the program, the following error occurs
A generic error occurred in GDI+.
How can I resolve this?
please help me TYI
Most of the time when you encounter this error it's either one of two things. These are easy to rule out as the cause so you might want to consider doing that before looking elsewhere.
You attempt to write a file to a directory that you don't have Permission for.
You are trying to write back an image that you still have open.

Printing Photos using VB6 and/or .NET

Does anyone have any code suggestions or samples for printing photos (BMP or TIFF or JPEG), using Visual Basic or .NET framework?
VB6 and .NET handle printing quite differently. These examples are the bare minumum, just to give you an idea of the process.
In VB6 you control the printer step by step:
Private Sub PrintMyPicture()
'Place to store my picture
Dim myPicture As IPictureDisp
'Load the picture into the variable
Set myPicture = LoadPicture("C:\temp\myPictureFile.bmp")
'Draw the picture on the printer, just off the edge of the page
Printer.PaintPicture myPicture, 10, 10
'Done printing!
Printer.EndDoc
End Sub
Lo and behold, your picture will come out of the default printer. the PaintPicture method accepts width, height and a few other parameters to help get the image to fit, and the Printer object gives you all sorts of info about the printer.
In .Net it's kind of the other way around. You start printing, and the printer will raise an event for each page until you tell it to stop. Every page event gives you as graphics object upon which you can draw using all of the standard System.Drawing classes and methods:
'Class variable
Private WithEvents printer As System.Drawing.Printing.PrintDocument
' Kick off the printing process. This will cause the printer_PrintPage event chain to start firing.
Public Sub PrintMyPicture()
'Set up the printer
printer.PrinterSettings.PrinterName = "MyPrinterNameInPrintersAndFaxes"
printer.Print()
End Sub
'This event will keep firing while e.HasMorePages = True.
Private Sub printer_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles printer.PrintPage
'Load the picture
Dim myPicture As System.Drawing.Image = System.Drawing.Image.FromFile("C:\temp\myPictureFile.bmp")
'Print the Image. 'e' is the Print events that the printer provides. In e is a graphics object on hwich you can draw.
'10, 10 is the position to print the picture.
e.Graphics.DrawImage(myPicture, 10, 10)
'Clean up
myPicture.Dispose()
myPicture = Nothing
'Tell the printer that there are no more pages to print. This will cause the document to be finalised and come out of the printer.
e.HasMorePages = False
End Sub
Again, there are a lot more parameters in DrawImage and the PrintDocument objects.