Adding Progress bar while loading Image list to listbox using vb.net - vb.net

I am trying to add Images using open file dialog and folder browse dialog and populating the image list to listbox.While adding these Images I need to show the progress bar for every image it loads.
I am trying to get that but when the value of the progress bar say something around 25 0r 40 it is stopping at that point but I need to show the progress bar until it completes the 100% and then populates the Image list.
How do I do that?
Here is my code:
Private Sub AddImages_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddImages.Click
If Not Directory.Exists(Application.StartupPath + "\Backup\") = True Then
Directory.CreateDirectory(Application.StartupPath + "\Backup\")
End If
OpenFileDialog1.FileName = "Select a Image"
OpenFileDialog1.Multiselect = True
OpenFileDialog1.InitialDirectory = "C:\Users\Public\Pictures\Sample Pictures"
OpenFileDialog1.Filter = "All Type Of Image Files|*.*|Joint Photographic Experts Group [JPEG]|*.jpg|Bitmap [BMP|*.bmp|Tagged Image File Format [TIFF]|*.tiff|Portable Network Graphics [PNG]|*.png"
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
ProgressBar2.Show()
ProgressBar2.Step = 10
Dim str As String
For Each str In OpenFileDialog1.FileNames
Load.Text = "Loading..."
Dim fso As New FileSystemObject
Dim MyName As String
Dim MyExtension As String
MyName = fso.GetFileName(CStr(str))
MyExtension = fso.GetExtensionName(MyName)
System.IO.File.Copy(str, Application.StartupPath + "\Backup\" + MyName & "." & MyExtension, True)
CheckedListBox1.Items.Add(str, CheckState.Checked)
Thumbcontrol1.AddThumbnail(str)
Thumbcontrol1.BackgroundImage = Nothing
CheckedListBox1.SelectedIndex = 0
ProgressBar2.PerformStep()
Next
SaveProject.Enabled = True
Delete.Enabled = True
Edit.Enabled = True
ClearAll.Enabled = True
CheckAll.Enabled = True
UncheckAll.Enabled = True
Timer1.Stop()
Load.Text = "Loading Completed"
Else
End If
ProgressBar2.Visible = False
Load.Text = Nothing
End Sub

Remove ProgressBar2.Step = 10 line and do this:
Dim str As String
Dim counter As Integer 'new!
For Each str In OpenFileDialog1.FileNames
Load.Text = "Loading..."
Dim fso As New FileSystemObject
Dim MyName As String
Dim MyExtension As String
MyName = fso.GetFileName(CStr(str))
MyExtension = fso.GetExtensionName(MyName)
System.IO.File.Copy(str, Application.StartupPath + "\Backup\" + MyName & "." & MyExtension, True)
CheckedListBox1.Items.Add(str, CheckState.Checked)
Thumbcontrol1.AddThumbnail(str)
Thumbcontrol1.BackgroundImage = Nothing
counter += 1 'new
CheckedListBox1.SelectedIndex = 0
ProgressBar2.Value = (counter * 100) / OpenFileDialog1.FileNames.Length 'new
Next
It does not address the problem of your not using threading, as other answers are correct to point out.

Don´t use the UI for loading. Use Background worker. BackgroundWorker works in another thread, and it can report the progress to bind it to a progressbar.

The progress bar stops moving because Windows thinks there is something seriously wrong with your program. It replaces your main window with the 'ghost' window, you can tell because it says "Not Responding" in the title bar.
It does this to help alert the user that your program is dead to the world and will not respond to any input from the user. Clicking the mouse or banging on the keyboard will not have any effect, all the user can do is watch helplessly while your code goes through the motions.
This does not make a desirable user interface. You solve it by using BackgroundWorker so the heavy lifting is done on a separate thread. Leaving the user interface thread responsive. Be sure to read the MSDN article for it so you know what to do, you'll have to adapt your code.

Related

Passing Parameter to Crystal Reports XI from Visual Studio 2015

I am running into problems with the passing of parameters to an externally created Crystal Reports XI report from the WinForms application I'm building in Visual Studio 2015 Community Edition. No matter what I try to do, the report doesn't seem to get the value unless I manually select it at the prompt (which shouldn't even be popping up) when the report is being displayed. I'm using the same code I've used in a previous application (although that one was built in VS2008), but I've tried a number of "alternate" versions of the code in my attempts to get this working. Here's the code that I'm currently using:
Imports CrystalDecisions.CrystalReports.Engine
Imports CrystalDecisions.Shared
Module modReports
Private WithEvents DocumentToPrint As New Printing.PrintDocument
Private Sub ShowReport(ByVal LID As Integer, ByVal InHouse As Boolean)
Dim Report As New ReportDocument
Dim ReportParameters As ParameterFieldDefinitions = Nothing
Dim Parameter As ParameterFieldDefinition = Nothing
Dim ApplicationValue As ParameterDiscreteValue = Nothing
Dim ReportValues As ParameterValues = Nothing
Dim ReportViewer As New frmReport
Dim Response As DialogResult = DialogResult.Cancel
PrintingReport = True
Report.Load(CRYSTAL_REPORT_FILE_PATH & "ExampleReport.rpt")
Report.Refresh()
Report.VerifyDatabase()
ReportParameters = Report.DataDefinition.ParameterFields
Parameter = ReportParameters.Item("PrintAll")
ReportValues = New ParameterValues
ApplicationValue = New ParameterDiscreteValue
'Parameter.CurrentValues.Clear()
'ReportValues.Clear()
ReportValues = Parameter.CurrentValues
If LID = 7777 Then
ApplicationValue.Value = True
Else
ApplicationValue.Value = False
End If
ReportValues.Add(ApplicationValue)
Parameter.ApplyCurrentValues(ReportValues)
Response = MessageBox.Show("Do you want to send this report directly to the printer?", "SEND TO PRINTER", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
If Response = DialogResult.No Then
With ReportViewer
.rptViewer.ReportSource = Nothing
.rptViewer.ReportSource = Report
.WindowState = FormWindowState.Maximized
.rptViewer.RefreshReport()
' Set zoom level: 1 = Page Width, 2 = Whole Page, 25-100 = zoom %
.rptViewer.Zoom(1)
.rptViewer.Show()
.ShowDialog()
End With
ElseIf Response = DialogResult.Yes Then
Dim SelectPrinter As New PrintDialog
Dim PrinterSelected As DialogResult = DialogResult.Cancel
With SelectPrinter
.Document = DocumentToPrint
.AllowPrintToFile = False
.AllowSelection = False
.AllowCurrentPage = False
.AllowSomePages = False
.PrintToFile = False
End With
PrinterSelected = SelectPrinter.ShowDialog
If PrinterSelected = DialogResult.OK Then
Dim Copies As Integer = DocumentToPrint.PrinterSettings.Copies
Dim PrinterName As String = DocumentToPrint.PrinterSettings.PrinterName
Dim LastPageNumber As Integer = 1
Dim PrintBuffer As String = String.Empty
LastPageNumber = Report.FormatEngine.GetLastPageNumber(New ReportPageRequestContext)
Report.PrintOptions.PrinterName = PrinterName
Report.PrintOptions.PrinterDuplex = DocumentToPrint.PrinterSettings.Duplex
Report.PrintToPrinter(Copies, True, 1, LastPageNumber)
If Copies = 1 Then
PrintBuffer = "Printed " & Copies & " copy of "
Else
PrintBuffer = "Printed " & Copies & " copies of "
End If
If LastPageNumber = 1 Then
PrintBuffer += LastPageNumber.ToString & " page."
Else
PrintBuffer += LastPageNumber.ToString & " pages."
End If
MessageBox.Show("The report was sent to the following printer:" & vbCrLf & " • " & PrinterName & vbCrLf & PrintBuffer, "REPORT PRINTED", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End If
PrintingReport = False
End Sub
End Module
The report itself is built to use an XML file as the data source, which is dynamically created by this application. All of that works normally, and oddly enough, if I send the report directly to the printer, it seems to print correctly without prompting me. It's only a problem when I try to display the report through the CrystalReportViewer object.
Some of the things I've tried without success:
I've tried with and without calling the Clear() methods on the
Parameter.CurrentValues and ReportValues objects.
I've tried moving all of the parameter setting logic to after I set the
ReportSource of the CrystalReportViewer control (rptViewer.ReportSource)
I've tried using alternate Crystal Reports objects (ParameterFields instead of ParameterFieldDefinitions and ParameterField instead of ParameterFieldDefinition).
I've tried removing all of the "complicated" code and just using the SetParameterValue method (i.e., Report.SetParameterValue("PrintAll", True)
I've even tried creating different types of parameter fields in the report itself (String, Boolean, Number) and passing appropriate values for those datatypes.
If I walk through the code, it doesn't appear to error out anywhere, and everything looks like it's working just great until I get to the .rptViewer.RefreshReport() line in the With ReportViewer block. I've verified that all of the parameters and values have only the value I am "selecting" via the application by checking them every step up to that point, and it all looks exactly as I expect it to look.
But the application (via Crystal Reports) continues to prompt me for the value I just passed in the code. If I select the value in that prompt, the report does generate correctly based on the value I select, but no matter what I "pass" in the programming, the prompt always defaults to True.
Does anyone have any suggestions that I may have overlooked for how to get this parameter to correctly pass to the CrystalReportViewer control? Please let me know if you need any additional information or have any questions about what I've set up so far here. Thank you in advance.
Okay, so based on the information I found over on http://www.it-sideways.com/2011/10/how-to-disable-parameter-prompt-for.html, it seems that the RefreshReport method for the CrystalReportViewer control basically wipes out any parameters and/or log on information:
1. ) Do not invoke CrystalReportViewer.RefreshReport Method
This method will refresh the data for the report currently displayed
in the CrystalReportViewer control. The report will prompt for
parameters or logon info is necessary.
So, this method is not needed unless the same
CrystalDecisions.CrystalReports.Engine.ReportDocument object is
reused.
By commenting out that line of the code, I was able to prevent the parameter prompt from being displayed. The only issue I have after making that change is that, even though the zoom level is being set to 1 (page width), and when I run the project the CrystalReportViewer control even shows that it's correctly set in the status bar ('Zoom Factor: Page Width' is displayed), the report itself is not actually zoomed in to the page width.
With the RefreshReport method uncommented, if I manually provided the value for my parameter, it would display the report properly zoomed. If I add the zoom button to the control (.rptViewer.ShowZoomButton = True), I can manually choose the Page Width option, which then correctly "re-zooms" the report to the desired level, but it won't immediately display that way if the RefreshReport method is not called.
Regardless, I can spend some time trying to fight that now, but I finally have it properly setting, passing and displaying the results of my parameter. I hope this helps someone else running into this issue.

How to create .key file with specific text

I've been trying to make a program that is able to create a file with a .key extension, which contains a 5 line text.
It is fundamental to have 5 lines, otherwise it won't work.
I use
Dim filepath As String = TextBox1.Text + "\\rarreg.key"
Dim rarreg As New IO.StreamWriter(filepath, True)
rarreg.Write(String.Join(Environment.NewLine, hiddenTxt))
The hiddenTxt contains all the text needed and it's multilined.
However, when I click on the button to call this functions, it succesfully creates the file, but it comes empty.
Try this
' Add any initialization after the InitializeComponent() call.
Dim filepath As String = ""
Dim dialog As New SaveFileDialog
dialog.DefaultExt = "key"
dialog.FileName = "rarreg.key"
dialog.InitialDirectory = "c:\temp"
Dim results As DialogResult = dialog.ShowDialog()
If results <> Windows.Forms.DialogResult.Cancel Then
filepath = dialog.FileName
End If​

How do I kill a process that doesn't have any windows in VB.net?

I am new to VB.net and I am trying to write a forms app that works with Autodesk Inventor.
Unfortunately, every time I close Inventor, the "Inventor.exe" process still stays. I didn't realize this while debugging and I only realized this when I checked the task manager after the whole system started to lag.
Killing every process with the same name is fairly simple, but the issue is that the end user might have separate documents open in another Inventor window. So I need to write a function that only kills the Inventor processes that don't have a window open.
Public Class Form1
Dim _invApp As Inventor.Application
Dim _started As Boolean = False
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Try
_invApp = Marshal.GetActiveObject("Inventor.Application")
Catch ex As Exception
Try
Dim invAppType As Type = _
GetTypeFromProgID("Inventor.Application")
_invApp = CreateInstance(invAppType)
_invApp.Visible = True
'Note: if you shut down the Inventor session that was started
'this(way) there is still an Inventor.exe running. We will use
'this Boolean to test whether or not the Inventor App will
'need to be shut down.
_started = True
Catch ex2 As Exception
MsgBox(ex2.ToString())
MsgBox("Unable to get or start Inventor")
End Try
End Try
End Sub
Another section where I start a process, which is a specific 3D model file.
Public Sub SaveAs(oTemplate As String)
'define the active document
Dim oPartDoc As PartDocument = _invApp.ActiveDocument
'create a file dialog box
Dim oFileDlg As Inventor.FileDialog = Nothing
Dim oInitialPath As String = System.IO.Path.GetFullPath("TemplatesResources\" & oTemplate)
_invApp.CreateFileDialog(oFileDlg)
'check file type and set dialog filter
If oPartDoc.DocumentType = kPartDocumentObject Then
oFileDlg.Filter = "Autodesk Inventor Part Files (*.ipt)|*.ipt"
ElseIf oPartDoc.DocumentType = kAssemblyDocumentObject Then
oFileDlg.Filter = "Autodesk Inventor Assembly Files (*.iam)|*.iam"
ElseIf oPartDoc.DocumentType = kDrawingDocumentObject Then
oFileDlg.Filter = "Autodesk Inventor Drawing Files (*.idw)|*.idw"
End If
If oPartDoc.DocumentType = kAssemblyDocumentObject Then
oFileDlg.Filter = "Autodesk Inventor Assembly Files (*.iam)|*.iam"
End If
'set the directory to open the dialog at
oFileDlg.InitialDirectory = "C:\Vault WorkSpace\Draft"
'set the file name string to use in the input box
oFileDlg.FileName = "######-AAAA-AAA-##"
'work with an error created by the user backing out of the save
oFileDlg.CancelError = True
On Error Resume Next
'specify the file dialog as a save dialog (rather than a open dialog)
oFileDlg.ShowSave()
'catch an empty string in the imput
If Err.Number <> 0 Then
MessageBox.Show("Any changes made from here will affect the original template file!", "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification)
ElseIf oFileDlg.FileName <> "" Then
Dim MyFile As String = oFileDlg.FileName
'save the file
oPartDoc.SaveAs(MyFile, False)
'open the drawing document
System.Diagnostics.Process.Start(oInitialPath & ".idw")
Dim oFinalPath As String = oPartDoc.FullFileName
MessageBox.Show(oFinalPath, "", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification)
MessageBox.Show("Loaded", "", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification)
Dim oDrawingDoc As DrawingDocument = _invApp.Documents.ItemByName(oInitialPath & ".idw")
'oDrawingDoc.SaveAs()
End If
End Sub
Any help is appreciated.
Thanks
At the end on your form, probably FormClosed, add the following:
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
If (_invApp Is Nothing) Then Return ' if empty, then no action needed
_invApp.Quit()
Marshal.ReleaseComObject(_invApp)
_invApp = Nothing
System.GC.WaitForPendingFinalizers()
System.GC.Collect()
End Sub
This should make .NET release and properly dispose the COM Object for Inventor.
And consider declare the Inventor variable and assign Nothing/null, it's safer (avoid mistakes)
Dim _invApp As Inventor.Application = Nothing

SendMail Help in VB

I developed a sendmail program for support which works great. What I am trying to do now is add a history page, which will show my users what support requests they have sent previously. I plan on use My.Settings to save the each email sent from my program.
Here is my code for the SendMail button which sends me mail:
If TextBox1.Text = "" Then
MsgBox("Please describe the issue you're having Bender, I'm not a mindreader!")
Exit Sub
Else
lblpleasewait.Visible = True
delay(2000)
Dim Recipients As New List(Of String)
Recipients.Add("johndoe#yahoo.com")
Dim FromEmailAddress As String = Recipients(0)
Dim Subject As String = "IT Help!"
Dim Body As String = TextBox1.Text
Dim UserName As String = My.Settings.txtboxUN
Dim Password As String = My.Settings.txtboxPW
Dim Port As Integer = My.Settings.txtboxSMTPPort
Dim Server As String = My.Settings.txtboxSMTP
Dim Attachments As New List(Of String)
MsgBox(SendEmail(Recipients, FromEmailAddress, Subject, Body, UserName, Password, Server, Port, Attachments))
lblpleasewait.Visible = False
TextBox1.Text = ""
TextBox1.Focus()
'This is where the beginning of my code is to send it to the history form.
Dim str(2) As String
Dim itm As ListViewItem
str(0) = Today + " - " + TimeOfDay
str(1) = Body
itm = New ListViewItem(str)
GTSMailHistory.ListView1.Items.Add(itm)
My.Settings.logDate = str(0)
My.Settings.logIssue = str(1)
My.Settings.Save()
End If
As you can from the above code, the last few lines is where I add the Body of the email and the time of day and add it to my listview I have on another form (GTSMailHistory).
My problem is this, that code above sending it over to the other form is saving, but is overwritten with each new email. Its basically not appending new emails to the list, just writing over the first.
The only code I have on the history form is on the LOAD function which is below:
Private Sub GTSMailHistory_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim str(2) As String
Dim itm As ListViewItem
str(0) = My.Settings.logDate
str(1) = My.Settings.logIssue
itm = New ListViewItem(str)
ListView1.Items.Add(itm)
End Sub
I can't leave comments yet so if someone could move this it'd help.
Are you recreating your GTSMailHistory object each pass instead of just once at startup?
Also when saving the date/body to My.Settings you are overwriting the existing values, do you not want these to be lists instead?
In response to your comment:
Joiner, i do want it to be a list. Can i save a listview to my.settings so it remains persistent upon next program launch?
You can use My.Settings to store variables of different types including lists.
In Visual Studio go to:
Project -> Properties -> Settings (Tab) -> Add a setting and its type (browse for more).
See here for an example.
Found sort of an answer. Not really want i want but will suffice right now. I can write this to a textfile and use streamreader to load it to listview.
The below code adds the body and date to listview:
Static i As Integer = 0
Dim newItem As New ListViewItem(Today + " - " + TimeOfDay) '// add text Item.
newItem.SubItems.Add(TextBox2.Text) '// add SubItem.
history.ListView1.Items.Add(newItem) '// add Item to ListView.
i += 1
The below code loads the saved textfile
ListView1.View = View.Details : ListView1.Columns.Add("Date") : ListView1.Columns.Add("Issue")
If IO.File.Exists(myCoolFile) Then '// check if file exists.
Dim myCoolFileLines() As String = IO.File.ReadAllLines(myCoolFile) '// load your file as a string array.
For Each line As String In myCoolFileLines '// loop thru array list.
Dim lineArray() As String = line.Split("#") '// separate by "#" character.
Dim newItem As New ListViewItem(lineArray(0)) '// add text Item.
newItem.SubItems.Add(lineArray(1)) '// add SubItem.
ListView1.Items.Add(newItem) '// add Item to ListView.
Next
End If
On form close it saves my entries:
Dim myWriter As New IO.StreamWriter(myCoolFile)
For Each myItem As ListViewItem In ListView1.Items
myWriter.WriteLine(myItem.Text & "#" & myItem.SubItems(1).Text) '// write Item and SubItem.
Next
myWriter.Close()

Open, Launch or Show a file for the user to read or write in vb.net

It sounds very simple but I have searched and cannot seem to find a way to open a log file which the user just created from my windows form app. The file exits I just want to open it after it is created.
I have a Dim path As String = TextBox1.Text and once the user names and clicks ok on the savefiledialog I have a msgbox that says "Done" and when you hit OK I have tried this
FileOpen(FreeFile, path, OpenMode.Input) but nothing happens. I just want it to open the log and show it to the user so they can edit or save it again or anything.
This is where I got the above code.
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.filesystem.fileopen.aspx
Searching is difficult because everyone is trying to "Open" a file and process it during runtime. I am just trying to Show a file by Launching it like someone just double clicked it.
Here is the entire Export Button click Sub. It basically writes listbox items to file.
Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExport.Click
Dim sfd As New SaveFileDialog
Dim path As String = TextBox1.Text
Dim arypath() As String = Split(TextBox1.Text, "\")
Dim pathDate As String
Dim foldername As String
foldername = arypath(arypath.Length - 1)
pathDate = Now.ToString("yyyy-MM-dd") & "_" & Now.ToString("hh;mm")
sfd.FileName = "FileScannerResults " & Chr(39) & foldername & Chr(39) & " " & pathDate
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
sfd.Filter = "Text files (*.txt)|*.txt|CSV Files (*.csv)|*.csv"
sfd.ShowDialog()
path = sfd.FileName
Using SW As New IO.StreamWriter(path)
If CkbxFolder.Checked = True Then
SW.WriteLine("Folders")
For Each itm As String In ListBox1.Items
SW.WriteLine(itm)
Next
End If
If CkbxFiles.Checked = True Then
SW.WriteLine("Files")
For Each itm As String In ListBox2.Items
SW.WriteLine(itm)
Next
End If
End Using
MsgBox("Done...")
FileOpen(FreeFile, path, OpenMode.Input) 'Why can't I open a file for you...
End Sub
Do not use the old VB6 methods. They are still here for compatibility reason, the new code should use the more powerful methods in the System.IO namespace.
However, as said in comments, FileOpen don't show anything for you, just opens the file
You coud write
Using sr = new StreamReader(path)
Dim line = sr.ReadLine()
if !string.IsNullOrEmpty(line) Then
textBoxForLog.AppendText(line)
End If
End Using
or simply (if the file is not too big)
Dim myLogText = File.ReadAllText(path)
textBoxForLog.Text = myLogText
As alternative, you could ask the operating system to run the program associated with the file extension and show the file for you
Process.Start(path)
To get the same behavior as if the user double-clicked it, just use System.Diagnostics.Process, and pass the filename to it's Start method:
Process.Start(path)
This will open the file using whatever the default application is for that filename based on its extension, just like Explorer does when you double-click it.