Stop form from closing conditionally - vb.net

My problem is that I don't know a suitable command to stop my code from running. If I use a return statement, like below, the code in the subroutine btnClose will keep running causing the program to close on an error. The form must not close if an error on saving occurs.
Private Sub Save_Customer()
If txtName.text = "" then
msgbox("Error")
return
End If
End sub
Private Sub btnClose_Click(sender As System.Object, e As System.EventArgs) Handles btnClose.Click
save_Customer()
Me.Close()
End Sub

Change the Sub to a Function, then evaluate the return:
Private Function Save_Customer() As Boolean
If txtName.text = "" then
msgbox("Error")
return False
Else
Return True
End If
End sub
Private Sub btnClose_Click(sender As System.Object,
e As System.EventArgs) Handles btnClose.Click
' evaluate the return:
If save_Customer() Then
Me.Close()
End IF
End Sub

You should better intercept Closing event, and Cancel closing via e.Cancel = True. Doing it otherwise would result in too much plumbing. (You can close the form not only via btnClose, right)? Also ALT+F4, Mouse click on X button etc. Be careful though, not to leave your user in a deadlock, where they cannot close your form, and have to fall back to using task manager.

That is probably not the best way around your problem, but you could solve it like this:
Private Function Save_Customer()
If txtName.Text = "" Then
MsgBox("Error")
Return False
Else
Return True
End If
End sub
Private Sub btnClose_Click(sender As System.Object, e As System.EventArgs) Handles btnClose.Click
If Save_Customer() = False Then
Exit Sub
Else
Me.Close()
End if
End Sub
End Class

Related

Alternatives for 'Handles Me.FormClosing' in modules

I would like to know of any alternatives to the 'Handles Me.FormClosing' in modules.
I have created code that will display a confirmation message upon clicking the 'X' button. The issue is, I need to put this code into a module to use on multiple forms where i can call it, however, when I attempt to do this the 'Handles Me.FormClosing' will not work.
Here is the code i am using:
Private Sub Close(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
Dim result As DialogResult = MessageBox.Show("Are you sure you want to Exit the application?", "Exit", MessageBoxButtons.YesNo)
If result = DialogResult.Yes Then
FrmLogin.Close()
Else
e.Cancel = True
End If
End Sub
Whenever you create a new form:
Dim newForm as Form = New YourFormClass()
AddHandler newForm.FormClosing, AddressOf YourModule.Close
This will route all closing events you want through that sub. Then just remove the Handles Me.Closing unless there is something you aren't showing us that makes it relevant.
Try This. I made changes to work as you want :
Module YourModule
Public Function AskFormClosing() As Boolean
Dim result As DialogResult = MessageBox.Show("Are you sure you want to Exit the application?", "Exit", MessageBoxButtons.YesNo)
If result = DialogResult.Yes Then
Return True
Else
Return False
End If
End Function
End Module
And then
Private Sub Close(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If YourModule.AskFormClosing Then
Application.Exit
Else
e.Cancel = True
End If
End Sub
One possibility ist to create a function in your module which shows the MessageBox and exits Application if "Yes" is clicked else returns False.
Module YourModule
Private dontAskAgain As Boolean
Public Function AskFormClosing() As Boolean
If dontAskAgain = False Then
Dim result As DialogResult = MessageBox.Show("Are you sure you want to Exit the application?", "Exit", MessageBoxButtons.YesNo)
If result = DialogResult.Yes Then
dontAskAgain = True
Application.Exit()
End If
End If
Return dontAskAgain
End Function
End Module
And then you only need to set e.Cancel to the inverted result of the function.
Private Sub Close(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
e.Cancel = Not YourModule.AskFormClosing
End Sub
If you prefer to use AddHandler as suggested by other people, you could use the following method that will lead to the same result.
Module YourModule
Public Sub AskFormClosing(sender As Object, e As FormClosingEventArgs)
If dontAskAgain = False Then
Dim result As DialogResult = MessageBox.Show("Are you sure you want to Exit the application?", "Exit", MessageBoxButtons.YesNo)
If result = DialogResult.Yes Then
dontAskAgain = True
Application.Exit()
Else
e.Cancel = True
End If
End If
End Sub
End Module
And then add the Handler like this:
Dim newForm as Form = New YourFormClass()
AddHandler newForm.FormClosing, AddressOf YourModule.AskFormClosing
But for your main-Form you will need to add the Handler in the Loading Event, like this:
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler Me.FormClosing, AddressOf YourModule.AskFormClosing
End Sub
Rather than placing this code in a module for reuse, consider create a base Form that has the behaviour you wish to share and then have you other forms inherit from this base Form (rather than from System.Windows.Forms.Form).
See How to: Inherit Windows Forms on the Microsoft website.

Closing Excel in a Background worker

I have the following code that is supposed to run in a background worker when I hit the red X button to close the form:
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
picLoading.Visible = True
tblMain.Visible = False
bwQuitNoSave.RunWorkerAsync()
End Sub
Private Sub bwQuitNoSave_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwQuitNoSave.DoWork
'If at least one sheet has been opened, close the workbook
If FirstLoad = 2 Then
worksheet.Cells(1, 31).Value = ""
workbook.Save()
workbook.Close(False)
End If
End Sub
Private Sub bwQuitNoSave_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bwQuitNoSave.RunWorkerCompleted
'Exit the application
APP.Quit()
End Sub
So what's supposed to happen is that the application checks to see if an integer = 2, and if it is, it saves the workbook, closes it, and then quits the application. However when I run this code, even when the application is closed, the excel process stays open.
In a previous iteration of my application, I was using this code which functioned correctly (e.g. closed out the excel process):
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
picLoading.Visible = True
tblMain.Visible = False
'If at least one sheet has been opened, close the workbook
If FirstLoad = 2 Then
worksheet.Cells(1, 31).Value = ""
workbook.Save()
workbook.Close(False)
End If
'Exit the application
APP.Quit()
End Sub
Does anyone see what I'm missing?
I've also tried this, and the process still remains open:
Private Sub bwQuitNoSave_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwQuitNoSave.DoWork
'If at least one sheet has been opened, close the workbook
If FirstLoad = 2 Then
worksheet.Cells(1, 31).Value = ""
workbook.Save()
workbook.Close(False)
End If
Try
workbook.Close(False)
APP.Quit()
Catch
APP.Quit()
End Try
End Sub
Private Sub bwQuitNoSave_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bwQuitNoSave.RunWorkerCompleted
'Exit the application
releaseMemory(APP)
releaseMemory(worksheet)
releaseMemory(workbook)
End Sub
Private Sub releaseMemory(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Solved it after many, many tries:
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If e.CloseReason = CloseReason.UserClosing Then
e.Cancel = True
picLoading.Visible = True
tblMain.Visible = False
If FirstLoad = 2 Then
worksheet.Cells(1, 31).Value = ""
bwQuitNoSave.RunWorkerAsync()
Else
Quit()
End If
End If
End Sub
Public Sub Quit()
APP.Quit()
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
Application.Exit()
End Sub
Private Sub bwQuitNoSave_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwQuitNoSave.DoWork
'If at least one sheet has been opened, close the workbook
workbook.Save()
End Sub
Private Sub bwQuitNoSave_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bwQuitNoSave.RunWorkerCompleted
Quit()
End Sub
Turns out the key was to have the exit via the red X canceled and manually close out the application.

Expression is not a method

Hello Coders Im trying to code a Anti virus and the following problem was here!
Im trying to add MsgBoxStyle.YesNo and will the problem in this...
So im trying to add a Question for delete file or no with MsgBox.
My code:
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub Label1_Click(sender As System.Object, e As System.EventArgs)
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
If My.Settings.ifTmpR = True Then
For Each aF In Directory.GetFiles(My.Computer.FileSystem.SpecialDirectories.Temp)
Try
MsgBoxStyle.YesNo()
MsgBox("Biztosan törli: " + aF)
IO.File.Delete(aF)
MsgBox("Temp kiürítése: " + aF)
MsgBox(aF + "kitötrölve")
Catch ex As Exception
End Try
Next
End If
If My.Settings.ifTmpR = False Then
Try
MsgBox("Kérlek kapcsold be a TEMP Queryt!")
Catch ex As Exception
End Try
End If
End Sub
Private Sub RadioButton1_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles RadioButton1.CheckedChanged
If RadioButton1.Checked = True Then
My.Settings.ifTmpR = True
End If
End Sub
Private Sub RadioButton2_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles RadioButton2.CheckedChanged
If RadioButton2.Checked = False Then
My.Settings.ifTmpR = False
End If
End Sub
End Class
And what the problem?
Help?
So you're coding an Anti-Virus application but you seem to have no basic knowledge about how to use methods and parameters.
You are supposed to include MsgBoxStyle.YesNo as one of the parameters to the MsgBox() method. You cannot call it like you do since it's simply an Integer value.
As Steve suggested you should use MessageBox.Show() instead, due to that MsgBox only exists for backwards compability.
The first parameter is the message you want it to show, and the second parameter is what title the window should have. They're just plain strings.
The third parameter however is the one you pass to tell the method what buttons to include in the MessageBox, and it should be passed like this:
MessageBox.Show("I am a message", "I am a title", MessageBoxButtons.YesNo)
This will show a message box with the buttons "Yes" and "No" inside it.
Now to get use out of this you should put your MessageBox in an If-statement, otherwise the application won't care if you press either Yes or No.
If MessageBox.Show("Are you sure you want to delete this file?", "Confirmation", MessageBoxButtons.YesNo) = DialogResult.Yes Then
'Delete code here.
End If
There. Now I suggest that you would have started with something like a "Hello World"-application instead of an Anti-Virus application, as Anti-Virus is pretty much harder than just showing a simple MessageBox.

How to close first form?

I have 2 forms in my project. Users cannot exit from the first from, frmOptometry. I have this implemented this way:
Private Sub frmOptometry_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
MessageBox.Show("You can only close the application from the receipt screen!")
e.Cancel = True
End Sub
The second form, frmReceipt can be exited from. I have it implemented this way:
Private Sub frmReceipt_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If MessageBox.Show("Are you sure you want to quit?",
"Obi-Wan Optometry Closing",
MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation) =
DialogResult.No Then
e.Cancel = True
Else
frmOptometry.Close()
End If
End Sub
Right now, it does not close the program completely because it goes to the frmOptometry_FormClosing and prevents it. What should I do to fix this? Is there anyway to figure out where the user is trying to shut down the program and then decide from there?
One way to solve this is by introducing a flag (say, called FromReceipt) which indicates who asks the frmOptometry to close itself.
Something like this on frmOptometry will do:
Public FromReceipt As Boolean = False 'Add this
Private Sub frmOptometry_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If Not FromReceipt Then 'add this condition
MessageBox.Show("You can only close the application from the receipt screen!")
e.Cancel = True
End If
End Sub
And then on the frmReceipt:
Private Sub frmReceipt_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If MessageBox.Show("Are you sure you want to quit?",
"Obi-Wan Optometry Closing",
MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation) =
DialogResult.No Then
e.Cancel = True
Else
frmOptometry.FromReceipt = True 'Add this line to tell the frmOptometry: this time you can really close it
frmOptometry.Close()
End If
End Sub

How to break a loop with a single button click

I am using VB.NET and I have:
a Start button
a Stop button
a While loop
When the Start button is pressed, the While loop begins. I want to stop the loop when the Stop button is pressed.
I had tried to use Applications.DoEvents, but the loop stops when the Stop button is pressed twice.
Below is my code using Applications.DoEvents
Dim stopclick As Boolean = False
Private Sub btnPlay_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnPlay.Click
btnForward.Enabled = False
btnStop.Enabled = True
While
' Perform the while statements
If stopclick = True Then
stopclick = False
Application.DoEvents()
Exit While
End If
End While
End Sub
Private Sub btnStop_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStop.Click
stopClick = True
End Sub
Have I used Application.DoEvents incorrectly?
What are the other options besides Application.DoEvents? How can I stop the loop with a single Stop button click?
You need to put the call to Application.DoEvents outside of your If statement, like this:
While True
Application.DoEvents()
' Perform the while statements
If stopclick Then
stopclick = False
Exit While
End If
End While
The Stop_Click won't have a chance to be processed until you call DoEvents, so, with the way you had it, stopClick would never get set to True.
However, the larger issue, here, is that calling DoEvents, at all, is very bad practice and can lead to some very difficult-to-fix bugs if you aren't very careful. It would be far better if the loop was performed in a background thread. Check out the BackgroundWorker component for an easy to implement threading mechanism for WinForm projects. You'll find it in the tool box of your form designer.
Here's an example of how to do it with the BackgroundWorker component:
Dim stopclick As Boolean = False
Private Sub btnPlay_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnPlay.Click
btnForward.Enabled = False
btnStop.Enabled = True
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub btnStop_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStop.Click
stopClick = True
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
stopClick = False
While Not stopClick
' Perform the while statements
End While
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
btnForward.Enabled = True
btnStop.Enabled = False
End Sub
You can simplify your while loop significantly by using stopClick as your condition:
While Not stopClick
Application.DoEvents()
End While
I know this is an old thread, but I found a simple workaround. Add a CheckBox to the form (it can even be "off the side of the form," if that made sense).
Private Sub btnStopLoop_Click(sender As System.Object, e As System.EventArgs) Handles btnStopLoop.Click
chkEndLoop.CheckState = CheckState.Checked
End Sub
Then, in the Loop you wish to exit:
Do Until chkEndLoop.CheckState = CheckState.Checked
'Do Stuff Here
Loop
As long as the CheckBox.CheckState = CheckState.Unchecked, the Loop will continue, but when the CheckBox becomes Checked, the Loop will Exit
You have to use btnstop.focus() at the start of the loop. This will be sure to solve your problem.
Example:
Dim stopclick As Boolean = False
Private Sub btnPlay_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnPlay.Click
btnForward.Enabled = False
btnStop.Enabled = True
btnStop.Focus() ' new code---------------------
While
' Perform the while statements
If stopclick = True Then
stopclick = False
Application.DoEvents()
Exit While
End If
End While
End Sub
Private Sub btnStop_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStop.Click
stopClick = True
End Sub