Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Monday, November 27, 2017 4:42 PM
I am building a project using Visual Basic in Visual Studio 2013 and I can’t get me.close to work for me. I have two forms, a main form and a second form. I launch my second form from my main form. In the second form I have placed a me.close in several routines as a way to error out of the second form and get back to the main form. None of these me.close statements work, the program just keeps chugging along. I also placed a me.close in a routine that handles the "DONE" button in the second form (this is the only me.close that works). What am I doing wrong? Why doesn’t me.close work (except for the instance of the DONE button).
Can anyone help me understand what is going on?
All replies (31)
Wednesday, November 29, 2017 6:28 PM ✅Answered
Think that through and see if you can apply some of it to your own?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Frank. Thanks very much for your help and the time you spent building this simplified version of a dual form project. It helped me immensely. I built this, tested it and then made a few modifications to the code to help me understand how the Me.Close() method actually works (since I can’t find anything explicitly written to explain the behavior) and its impact on Form2.
Here is the modified code and forms. I added a button in Form1 to simulate passing bad data to Form2 and I added a button in button in Form2 to simulate generating an error in Form2. To follow what was going on in the project I used various messages to indicate the path through the code and I also used break points and the “Step Into” debug feature of Visual Studio. The code segments that I added to what you sent me are labeled with “I added this TJB“ In this way I could restructure the code by commenting out and/or uncommenting various code segments and quickly rerunning it to observe the results.
Form1 Code:
Public Class Form1
Public Shared ErrorFlg As Boolean = False
Private Sub btnSelectTheColor_Click(sender As Object, e As EventArgs) Handles btnSelectTheColor.Click
Dim colors() As Color = _
{Color.Red, Color.Green, Color.Blue}
ErrorFlg = False 'I added this TJB
Me.Hide() 'I added this TJB
Using f2 As New Form2(colors)
f2.ShowDialog()
If Not f2.UserCancel Then
If f2.UserSelection IsNot Nothing Then
MessageBox.Show("The user selected the color " & _
f2.UserSelection.ToString)
End If
End If
End Using
Me.Show() 'I added this TJB
End Sub
Private Sub btnCheckForError_Click(sender As Object, e As EventArgs) Handles btnCheckForError.Click 'I added this Sub TJB
Dim colors() As Color = _
{Color.Red, Color.Green, Color.Blue}
ErrorFlg = True
Me.Hide()
Using f2 As New Form2(colors)
f2.ShowDialog()
If Not f2.UserCancel Then
If f2.UserSelection IsNot Nothing Then
MessageBox.Show("The user selected the color " & _
f2.UserSelection.ToString)
End If
End If
End Using
Me.Show()
ErrorFlg = False
End Sub
Private Sub btnEXIT_Click(sender As Object, e As EventArgs) Handles btnEXIT.Click 'I added this TJB
End
End Sub
End Class
Form 2 Code:
Public Class Form2
Private _colorChoices As IEnumerable(Of Color)
Private _userCancel As Boolean = True
Private _userSelection As Nullable(Of Color)
Dim YouGotAnError As Boolean = False
Public Sub New(ByVal colors As IEnumerable(Of Color))
InitializeComponent()
If colors Is Nothing OrElse colors.Count <> 3 Then
Me.Close()
Else
_colorChoices = colors
End If
End Sub
Private Sub _
Form2_Load(sender As System.Object, _
e As System.EventArgs) _
Handles MyBase.Load
With Me
.AcceptButton = btn_OK
.CancelButton = btn_Cancel
End With
btnRed.Text = _colorChoices(0).ToString
btnGreen.Text = _colorChoices(1).ToString
btnBlue.Text = _colorChoices(2).ToString
'Go check to see if I have an error - I added this TJB
CheckForPassingAnError()
MsgBox("You checked for an error by calling CheckForPassingAnError() in the Form2_Load Sub")
If YouGotAnError = True Then
'Me.Close()
'MsgBox("This is after the Me.Close in the Form2_Load Sub")
End If
MsgBox("This is just before the End Sub in the Form2_Load Sub")
End Sub
Private Sub _
Form2_Shown(sender As Object, _
e As System.EventArgs) _
Handles Me.Shown
btnRed.Checked = False
btnGreen.Checked = False
btnBlue.Checked = False
btn_OK.Enabled = False
End Sub
Private Sub _
CheckedChanged(sender As Object, _
e As System.EventArgs) Handles _
btnRed.CheckedChanged, _
btnGreen.CheckedChanged, _
btnBlue.CheckedChanged
If btnRed.Checked Then
_userSelection = _colorChoices(0)
ElseIf btnGreen.Checked Then
_userSelection = _colorChoices(1)
ElseIf btnBlue.Checked Then
_userSelection = _colorChoices(2)
End If
btn_OK.Enabled = True
End Sub
Private Sub _
btn_OK_Click(sender As System.Object, _
e As System.EventArgs) _
Handles btn_OK.Click
If _userSelection.HasValue Then
_userCancel = False
Me.Close()
End If
End Sub
Private Sub _
btn_Cancel_Click(sender As System.Object, _
e As System.EventArgs) _
Handles btn_Cancel.Click
Me.Close()
End Sub
Public ReadOnly Property UserCancel As Boolean
Get
Return _userCancel
End Get
End Property
Public ReadOnly Property UserSelection As Nullable(Of Color)
Get
Return _userSelection
End Get
End Property
Private Sub btnError_CheckedChanged(sender As Object, e As EventArgs) Handles btnError.CheckedChanged 'I added this TJB
MsgBox("You know this is not a valid selection")
Me.Close()
'Me.Refresh()
MsgBox("This is after the Me.Close() in the Other - An Error button handler")
End Sub
Private Sub CheckForPassingAnError() 'I added this TJB
If Form1.ErrorFlg = True Then
MsgBox("You have an error. Correct this")
YouGotAnError = True
'MsgBox("This is before the Me.Close to test the Exit.Sub statement")
Me.Close()
MsgBox("This is after the Me.Close in the CheckForPassingAnError Sub")
Exit Sub
MsgBox("This is after the Me.Close and Exit Sub in the CheckForPassingAnError Sub")
End If
End Sub
End Class
What I found is that the Me.Close() statement does not immediately force a close of the form and therefore cannot be used to close the form in the middle of a subroutine.
The best way I can explain this is to think of my project as two parts. These parts are the “Form” presentation view and the “Project Code”. The Project Code is what I wrote to perform the functions I need. That code is executed when I press a button on the Form. After the Project Code is executed the project goes back to an idle state passing control back to the Form waiting for me to again press a button.
The Form is what I see on the screen. The Form sits idle monitoring the buttons for presses and when it detects those presses it transfers control to my Project Code to execute the code that I have written and when my Project Code has finished executing, control is transferred back to the Form.
In this way I can think of the Me.Close() method as simply setting a flag that the Form monitors and acts on when control is passed to it.
The issue I had was an incomplete understanding of how the Me.Close() actually works. So with that in mind I need to go back to my original project and refactor some of the routines.
I also hope this helps anyone else that is scratching their head about the Me.Close() behavior.
Monday, November 27, 2017 4:46 PM
Hi
Saying 'a way to error out of the form' doesn't sound quite like a good idea to me.
Put a break point at each of the Me.Close statements and see if they are actually being reached.
Regards Les, Livingston, Scotland
Monday, November 27, 2017 5:11 PM
In windows forms, means Me.Close that the class object closes and gives control back to the class object that did call it.
As you know that the application framework contains a startup module which does
1.Run the main Form and gives the control to it
2.Exit application.
Then it should be easy to understand what you would do.
Be aware that exit the application from the application framework is the only right way to do.
Success
Cor
Monday, November 27, 2017 5:15 PM
I am building a project using Visual Basic in Visual Studio 2013 and I can’t get me.close to work for me. I have two forms, a main form and a second form. I launch my second form from my main form. In the second form I have placed a me.close in several routines as a way to error out of the second form and get back to the main form. None of these me.close statements work, the program just keeps chugging along. I also placed a me.close in a routine that handles the "DONE" button in the second form (this is the only me.close that works). What am I doing wrong? Why doesn’t me.close work (except for the instance of the DONE button).
Can anyone help me understand what is going on?
Are you showing the other form modally or modelessly?
Can you show some of the relevant code?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Monday, November 27, 2017 5:17 PM
Yes I did that and I have followed through the code step by step once it hits the breack by using the "step into" in the debug mode. I also placed msgbox statements in the code to signify when I reach certain points to test where it is going in the code. I also tried putting a btnDone.PerformClick() in place of the me.close thinking it would go to the btnDone handler and then close but that does not work either (yes it gets to the btnDone handler but it does not close). The only time it closes is when I click the DONE button.
Monday, November 27, 2017 5:27 PM
Hi
So, you still want to keep the code you have secret! You are asking us to guess.
Regards Les, Livingston, Scotland
Monday, November 27, 2017 5:50 PM
I am building a project using Visual Basic in Visual Studio 2013 and I can’t get me.close to work for me. I have two forms, a main form and a second form. I launch my second form from my main form. In the second form I have placed a me.close in several routines as a way to error out of the second form and get back to the main form. None of these me.close statements work, the program just keeps chugging along. I also placed a me.close in a routine that handles the "DONE" button in the second form (this is the only me.close that works). What am I doing wrong? Why doesn’t me.close work (except for the instance of the DONE button).
Can anyone help me understand what is going on?
Are you showing the other form modally or modelessly?
Can you show some of the relevant code?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Hi Charles. It shows the second form as a modal dialog box. I'm not sure what the difference is.
Monday, November 27, 2017 5:54 PM
Hi Charles. It shows the second form as a modal dialog box. I'm not sure what the difference is.
I'm Frank. ;-)
*****
That's good then.
What you'll want to do is to create a NEW instance of that second form and pass in anything that it needs through the constructor and pass out anything that the calling form needs back.
Normally I'll set a class-scoped boolean named "_userCancel" that I default to true. It's only false in the handler for the "OK" button and the code controls whether or not that button is enabled.
I don't know if this helps or not but if you want to explain what your program does then maybe a bit of refactoring might be in order here?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Monday, November 27, 2017 6:15 PM
Hi
So, you still want to keep the code you have secret! You are asking us to guess.
Regards Les, Livingston, Scotland
Hi Les
So here is some of the relevant code segments:
This first segment is the call to the second form (called ImgPreviewForm) from the main form (called MainFDForm). This calls the public Class coverView (in the second form). When I click the DONE button in the second form it closes the second form and returns to the main form and I get the message “returned from preview”
Private Sub BtnReviewCovers_Click(sender As Object, e As EventArgs) Handles btnReviewCovers.Click
'TODO: Done 078: Fix an unhandled exception error if there is no Path Specified in hilevelfolder txtbxFolderPath. Coded in 1.5.2.1g
'TODO: 093: Fix this so that if it points to a folder that does not exist it will flag the error In v1.5.3.0a it is an unhandled exception error
'TODO: 097: Add a From To check to set bounds for displaying Images
If txtbxFolderPath.Text <> "" Then
Dim viewCovers As New coverView()
viewCovers.HiLvlImgFldr = txtbxFolderPath.Text 'Sets the HiLvlImgFldr variable in the viewCovers Class
viewCovers.DupsReviewFlg = DupliFoldersFlg
viewCovers.HiLvlImgFldrRcv = txtbxDestFldr.Text 'Sets the folder for where the duplicates are located TD070
Me.Hide()
viewCovers.ShowDialog()
MsgBox("returned from preview") 'Part of debugging TD109
Me.Show()
Else
MsgBox("You need to provide a path for the images")
End If
End Sub
This code segment is from the second form and is an example of using me.close that does not work. I have used the debug on this code segment and found that it ignores the me.close and just keeps chugging through the code. I do get the "Closed the form with tststring 1 = ” message but it does not close and keeps right on through the code.
Private Sub LoadImgsInfoToArrays(ByVal fldrPntr)
Dim i As Integer
tooManyImgsFlg = False
i = 0
While i <= imgNamesCnt(fldrPntr) 'Clear The Image arrays first
imgNames(fldrPntr, i) = Nothing
imgStatsArray(fldrPntr, i, 0) = 0
imgStatsArray(fldrPntr, i, 1) = 0
imgStatsArray(fldrPntr, i, 2) = 0
i += 1
End While
foundImgCount = 0
For Each foundImg As String In My.Computer.FileSystem.GetFiles(imgFldrs(fldrPntr, 0))
Dim foundImgStats As New System.IO.FileInfo(foundImg)
If XPRN_File_Discovery.XPRNFilDis.extensionsImages.Contains(foundImgStats.Extension.ToLower) Then
imgNames(fldrPntr, foundImgCount) = foundImgStats.Name
foundImgCount += 1
If foundImgCount > 1000 Then
tooManyImgsFlg = True
tooLargeSetFldrName = imgFldrs(fldrPntr, 0)
End If
End If
Next
imgDispPnt(fldrPntr) = 1
imgNamesCnt(fldrPntr) = foundImgCount
If foundImgCount = 0 Then 'You have no Images in this folder. Error out and quit
'TODO: 109: Need to debug the system error that occurs when I get this "no images in " message
tstString1 = imgFldrs(fldrPntr, 0) 'for TD109 Debug
MsgBox("There are no images in " & imgFldrs(fldrPntr, 0) & " to set up for image previews. Please correct this and try again", MsgBoxStyle.Critical)
'btnDone.PerformClick() 'test for TD109 see if it closes by going to DONE
Me.Close()
MsgBox("Closed the form with tststring 1 = " & tstString1) 'debug for TD109
End If
End Sub
I also have several other places where I try to use Me.Close they don't work either.
This code segment is from the second form and is the DONE button handler (that works when I click the DONE button the second form) That is it closes the second form and returns me to the first form:
Private Sub BtnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click 'Close out all the Images before exiting
Grp0PictBxImgDispose()
Grp1PictBxImgDispose()
Me.Close()
End Sub
Still scratching my head over this me.close conundrum. Any suggestions?
Monday, November 27, 2017 6:23 PM
Hi
Try changing the
viewCovers.ShowDialog()
to
viewCovers.Show()
and see if the .Close lines work then.
Regards Les, Livingston, Scotland
Monday, November 27, 2017 6:57 PM
Sorry Les that did not work. It now hides the first form, opens the second form performs some of the functions and right away it goes back to the first form and redisplays the first form without hitting any of the me.close statements (I put a break point at every me.close statement). I am now left with two forms open (displayed) where I only wanted one or the other.
Monday, November 27, 2017 6:58 PM
Sorry Les that did not work. It now hides the first form, opens the second form performs some of the functions and right away is goes back to the first form and redisplays the first form without hitting any of the me.close statements (I put a break point at every me.close statement). I am now left with two forms open (displayed) where I only wanted one or the other.
Now you know the difference between modal and modeless. ;-)
"A problem well stated is a problem half solved.” - Charles F. Kettering
Monday, November 27, 2017 7:08 PM
You obviously did not read what I wrote.
If you click on the second form as done then it returns control to the first form.
That is 100% correct as it should be.
Set before that close the dialogresult of that dialogform to dialogresult.cancel
Me.DialogResult = DialogResult.Cancel
and use this code on your mainform.
If txtbxFolderPath.Text = "" Then
MsgBox("You need to provide a path for the images")
Return
End If
Me.Hide()
Using viewCovers As New coverView()
viewCovers.HiLvlImgFldr = txtbxFolderPath.Text 'Sets the HiLvlImgFldr variable in the viewCovers Class
viewCovers.DupsReviewFlg = DupliFoldersFlg
viewCovers.HiLvlImgFldrRcv = txtbxDestFldr.Text 'Sets the folder for where the duplicates are located TD070
If viewCovers.ShowDialog <> dialogresult.Cancel Then
Me.Close()
End If
End Using
Success
Cor
Monday, November 27, 2017 7:16 PM
Show some details about viewCovers.ShowDialog() and about the calling of LoadImgsInfoToArrays. Maybe there are several unneeded instances of ImgPreviewForm.
Monday, November 27, 2017 7:18 PM
TJB - here is an example that might help. The main form (Form1) has two buttons, and the other form (Form2) has one button.
Form2 code
Public Class Form2
Public Sub New(CloseType As DialogResult)
InitializeComponent()
Me._close = CloseType
End Sub
Public _close As DialogResult
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Close()
End Sub
Private Sub Form2_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
Me.DialogResult = _close
End Sub
End Class
Form1 code
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' ShowDialog version
Static f2 As Form2
f2 = New Form2(Windows.Forms.DialogResult.OK)
Dim dr As DialogResult = f2.ShowDialog()
Debug.Write(f2.IsDisposed)
Debug.WriteLine(dr)
f2.Dispose()
dr = Nothing
End Sub
Private f2Task As Task
Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
' Show version
If f2Task IsNot Nothing Then Exit Sub
f2Task = F2Show()
Await f2Task
' Stop
f2Task.Dispose()
f2Task = Nothing
End Sub
Private Async Function F2Show() As Task
Dim f2 As Form2
Dim t As Task = Task.Run(Sub()
f2 = New Form2(Windows.Forms.DialogResult.OK)
Me.Invoke(Sub()
f2.Show()
End Sub)
While f2._close <> f2.DialogResult
Threading.Thread.Sleep(100)
End While
End Sub)
Await t
' Stop
End Function
End Class
Give it a try and see if it helps. Both button 1 and two do the same thing, show one instance of the form.
"Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it" - MSDN User JohnWein
Multics - An OS ahead of its time. Serial Port Info
Monday, November 27, 2017 7:18 PM
Show some details about viewCovers.ShowDialog() and about the calling of LoadImgsInfoToArrays. Maybe there are several instances of ImgPreviewForm.
Why about that the OP wrote all there is in my perception. The problem is obvious. It will never close only because of a close in a child form it returns control to the higher class.
Success
Cor
Monday, November 27, 2017 7:21 PM
This seems very strange.
Try this in a new project to rule out stuff interfering with this small demo. Project should have two forms, Form1 and Form2.
Form1 has a single button with the following code
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim f As New Form2
Try
Hide()
f.ShowDialog()
Finally
Show()
f.Dispose()
End Try
End Sub
End Class
Form 2 has two buttons, first button in the property window set DialogResult to Ok, in the second button Close.
Both button1 and button2 will close the child form and display the caller (form1)
If you do this in your project (following the pattern above) and still have issues there is something we have not seen causing the issue.
Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
VB Forums - moderator
Monday, November 27, 2017 7:33 PM
Hi Charles. It shows the second form as a modal dialog box. I'm not sure what the difference is.
I'm Frank. ;-)
*****
That's good then.
What you'll want to do is to create a NEW instance of that second form and pass in anything that it needs through the constructor and pass out anything that the calling form needs back.
Normally I'll set a class-scoped boolean named "_userCancel" that I default to true. It's only false in the handler for the "OK" button and the code controls whether or not that button is enabled.
I don't know if this helps or not but if you want to explain what your program does then maybe a bit of refactoring might be in order here?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Sorry about that Frank.
I have placed a couple of code segments in this thread to show what I am trying to do. In my project I am working with Images and Image folders. Right now I have two forms. I only want to display and work on one form at a time. The first form allows me to specify where the image folders are on my disk, web, etc. and allows me to extract images from rar files, modify (rescale) images and/or modify some of the image meta data. With my project I managed to launch a second form that I use to display thumbnails of images allowing me to scroll through images, rename images or delete images and/or folders. I launch this second form when I want to preview images from folders or when I encounter duplicate images or duplicate folders allowing me to delete images or folders.
There are instances in the second form when I want to stop any further processing in the second form and immediately exit back to the first form. These are instances where I:
- Found no images to display in the folders (or the rar files) (this is an error condition)
- Completed the disposition of duplicates (this is not an error just the end of the disposition process).
There are a few other instances and/or error conditions. But the key here is that the only way to get back to the first form is by clicking on the second form’s DONE button (ie: the me.close does not work unless it is executed from the btnDone handler).
I am up for refactoring code if I could understand how to get back to the first form immediately from the code not from a button click.
Monday, November 27, 2017 7:40 PM
Hi Charles. It shows the second form as a modal dialog box. I'm not sure what the
Sorry about that Frank.
I have placed a couple of code segments in this thread to show what I am trying to do. In my project I am working with Images and Image folders. Right now I have two forms. I only want to display and work on one form at a time. The first form allows me to specify where the image folders are on my disk, web, etc. and allows me to extract images from rar files, modify (rescale) images and/or modify some of the image meta data. With my project I managed to launch a second form that I use to display thumbnails of images allowing me to scroll through images, rename images or delete images and/or folders. I launch this second form when I want to preview images from folders or when I encounter duplicate images or duplicate folders allowing me to delete images or folders.
There are instances in the second form when I want to stop any further processing in the second form and immediately exit back to the first form. These are instances where I:
- Found no images to display in the folders (or the rar files) (this is an error condition)
- Completed the disposition of duplicates (this is not an error just the end of the disposition process).
There are a few other instances and/or error conditions. But the key here is that the only way to get back to the first form is by clicking on the second form’s DONE button (ie: the me.close does not work unless it is executed from the btnDone handler).
I am up for refactoring code if I could understand how to get back to the first form immediately from the code not from a button click.
That definitely sounds like you want to use a modal form them, not a modelss.
Like I said earlier, I'd strongly suggest that you create a NEW instance of that other form; instead of .ShowDialog, you'll do something like this (in the calling form):
Using f2 As New Form2()
f2.ShowDialog
End Using
That's a shortcut that will close/dispose things when the "End Using" exits. You can pass things in (and it sounds like you will need to) and pass things out (which you probably want to do).
There are a lot of replies here and I'm sure that it'll all get confusing after a while, but once you want to let's re-work that second form, then let me know and I'll help you with that (if you want).
If you'd like for me to show you what I mean about a constructor, passing things in, and passing things out, we can start there -- just let me know.
"A problem well stated is a problem half solved.” - Charles F. Kettering
Monday, November 27, 2017 7:41 PM
You obviously did not read what I wrote.
If you click on the second form as done then it returns control to the first form.
That is 100% correct as it should be.
Set before that close the dialogresult of that dialogform to dialogresult.cancel
Me.DialogResult = DialogResult.Cancel
and use this code on your mainform.
If txtbxFolderPath.Text = "" Then MsgBox("You need to provide a path for the images") Return End If Me.Hide() Using viewCovers As New coverView() viewCovers.HiLvlImgFldr = txtbxFolderPath.Text 'Sets the HiLvlImgFldr variable in the viewCovers Class viewCovers.DupsReviewFlg = DupliFoldersFlg viewCovers.HiLvlImgFldrRcv = txtbxDestFldr.Text 'Sets the folder for where the duplicates are located TD070 If viewCovers.ShowDialog <> dialogresult.Cancel Then Me.Close() End If End Using
Success
Cor
Hi Cor. I read what you wrote but I did not understand it and after this I still don't.
Monday, November 27, 2017 8:07 PM
Frank, that would be great, I would welcome your help. I don’t think I have a problem passing things in and out as currently I am using public shared variables or I use Statements like:
viewCovers.HiLvlImgFldr = txtbxFolderPath.Text 'Sets the HiLvlImgFldr variable in the viewCovers Class
viewCovers.DupsReviewFlg = DupliFoldersFlg
viewCovers.HiLvlImgFldrRcv = txtbxDestFldr.Text 'Sets the folder for where the duplicates are located TD070
to set variables in the second form.
I know I could pass those through in the viewCovers.ShowDialog() statement as byval but that does not seem to be the issue (since all the variables are set correctly when I get to the second Form). I am just stumped as to how to get the second form code to stop executing, close the second form and return to the first when I use “me.close” in the code (other than when I press the DONE button).
Monday, November 27, 2017 8:10 PM
Frank, that would be great, I would welcome your help. I don’t think I have a problem passing things in and out as currently I am using public shared variables or I use Statements like:
viewCovers.HiLvlImgFldr = txtbxFolderPath.Text 'Sets the HiLvlImgFldr variable in the viewCovers Class viewCovers.DupsReviewFlg = DupliFoldersFlg viewCovers.HiLvlImgFldrRcv = txtbxDestFldr.Text 'Sets the folder for where the duplicates are located TD070
to set variables in the second form.
I know I could pass those through in the viewCovers.ShowDialog() statement as byval but that does not seem to be the issue (since all the variables are set correctly when I get to the second Form). I am just stumped as to how to get the second form code to stop executing, close the second form and return to the first when I use “me.close” in the code (other than when I press the DONE button).
Give me a little while and I'll put together an example that has nothing to do with what you're doing other than I'll use a second form.
Doing it like that, you won't get confused about your actual application and can instead just focus on this little one.
I think that once you "get it" with the little one, you'll start to see what's going on in your larger one.
"A problem well stated is a problem half solved.” - Charles F. Kettering
Monday, November 27, 2017 8:23 PM
Frank, that would be great, I would welcome your help. I don’t think I have a problem passing things in and out as currently I am using public shared variables or I use Statements like:
viewCovers.HiLvlImgFldr = txtbxFolderPath.Text 'Sets the HiLvlImgFldr variable in the viewCovers Class viewCovers.DupsReviewFlg = DupliFoldersFlg viewCovers.HiLvlImgFldrRcv = txtbxDestFldr.Text 'Sets the folder for where the duplicates are located TD070
to set variables in the second form.
I know I could pass those through in the viewCovers.ShowDialog() statement as byval but that does not seem to be the issue (since all the variables are set correctly when I get to the second Form). I am just stumped as to how to get the second form code to stop executing, close the second form and return to the first when I use “me.close” in the code (other than when I press the DONE button).
Give me a little while and I'll put together an example that has nothing to do with what you're doing other than I'll use a second form.
Doing it like that, you won't get confused about your actual application and can instead just focus on this little one.
I think that once you "get it" with the little one, you'll start to see what's going on in your larger one.
"A problem well stated is a problem half solved.” - Charles F. Kettering
Frank, that would help immensely. Thank You
Monday, November 27, 2017 8:34 PM
Hi Cor. I read what you wrote but I did not understand it and after this I still don't.
This is the rference:
"Unlike non-modal forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property."
https://msdn.microsoft.com/en-us/library/c7ykbedk%28v=vs.110%29.aspx
So the problem is not that the form is failing to close, it is failing to hide. You need to look for something in the form that prevents it from hiding. Or, dispose of the form after control returns to the calling form.
Monday, November 27, 2017 8:39 PM
Frank, that would be great, I would welcome your help.
Ok,
This is what I have, nonsensical though it is. I've got a main form (Form1.vb) and with the click of a button I'm going to pass in three colors which are defined in a collection. My auxiliary form (Form2.vb) will take these three colors and populate the text of three RadioButtons. The second form also has an "OK" button and a "Cancel" button:
The thing to keep up with here is that Form2 is shown modally; Form1's code won't resume until after Form2 has been dismissed so here's the code for Form1:
Public Class Form1
Private Sub _
Form1_Load(sender As System.Object, _
e As System.EventArgs) _
Handles MyBase.Load
' Initialization here if applicable...
End Sub
Private Sub _
btn_SelectColor_Click(sender As System.Object, _
e As System.EventArgs) _
Handles btn_SelectColor.Click
Dim colors() As Color = _
{Color.Red, Color.Green, Color.Blue}
Using f2 As New Form2(colors)
f2.ShowDialog()
If Not f2.UserCancel Then
If f2.UserSelection IsNot Nothing Then
MessageBox.Show("The user selected the color " & _
f2.UserSelection.ToString)
End If
End If
End Using
End Sub
End Class
What I want you to recognize above is that I'm creating a NEW instance of Form2, I'm passing in the colors and Form2 is shown modally. At that point, Form1 waits; the rest of the code won't be executed yet -- not until Form2 is dismissed.
Given that, let's have a look at the code for Form2:
Public Class Form2
Private _colorChoices As IEnumerable(Of Color)
Private _userCancel As Boolean = True
Private _userSelection As Nullable(Of Color)
Public Sub New(ByVal colors As IEnumerable(Of Color))
InitializeComponent()
If colors Is Nothing OrElse colors.Count <> 3 Then
Close()
Else
_colorChoices = colors
End If
End Sub
Private Sub _
Form2_Load(sender As System.Object, _
e As System.EventArgs) _
Handles MyBase.Load
With Me
.AcceptButton = btn_OK
.CancelButton = btn_Cancel
End With
RadioButton1.Text = _colorChoices(0).ToString
RadioButton2.Text = _colorChoices(1).ToString
RadioButton3.Text = _colorChoices(2).ToString
End Sub
Private Sub _
Form2_Shown(sender As Object, _
e As System.EventArgs) _
Handles Me.Shown
RadioButton1.Checked = False
RadioButton2.Checked = False
RadioButton3.Checked = False
btn_OK.Enabled = False
End Sub
Private Sub _
CheckedChanged(sender As Object, _
e As System.EventArgs) Handles _
RadioButton1.CheckedChanged, _
RadioButton2.CheckedChanged, _
RadioButton3.CheckedChanged
If RadioButton1.Checked Then
_userSelection = _colorChoices(0)
ElseIf RadioButton2.Checked Then
_userSelection = _colorChoices(1)
ElseIf RadioButton3.Checked Then
_userSelection = _colorChoices(2)
End If
btn_OK.Enabled = True
End Sub
Private Sub _
btn_OK_Click(sender As System.Object, _
e As System.EventArgs) _
Handles btn_OK.Click
If _userSelection.HasValue Then
_userCancel = False
Close()
End If
End Sub
Private Sub _
btn_Cancel_Click(sender As System.Object, _
e As System.EventArgs) _
Handles btn_Cancel.Click
Close()
End Sub
Public ReadOnly Property UserCancel As Boolean
Get
Return _userCancel
End Get
End Property
Public ReadOnly Property UserSelection As Nullable(Of Color)
Get
Return _userSelection
End Get
End Property
End Class
A few things here: The colors to show the names of is being passed in as an IEnumerable(Of Color) -- that's an easy way that I can set it up to accept a generic List(Of Color), an array (of color), etc..
Also, the user's selection is a nullable type. I'm using that because a color is a structure (so it's a value type). By default it's null.
Now let's proceed and see what happens here:
In form1 I'll click the button:
That passes in the three colors and form2 is shown, displaying those colors and the three choices:
Note here that the "OK" button is disabled. I won't enable it until the user selects a color. Once they do, the fact that they're radiobuttons means that one will always be selected from that point on so I don't have to worry about that part.
I'll pick the middle one:
Now that I've chosen a color, the "OK" button is enabled. At any point they can "quit" but closing the form ("X") or clicking the cancel button but only when they click the "OK" will the returning boolean named "UserCancel" be true. That way I can be sure that I know whether they meant to cancel it or not.
Continuing now, I'll click the "OK" button there and code execution is returned to Form1 where it's instructed to show a messagebox:
Think that through and see if you can apply some of it to your own?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Monday, November 27, 2017 8:49 PM
This is the rference:
"Unlike non-modal forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property."
https://msdn.microsoft.com/en-us/library/c7ykbedk%28v=vs.110%29.aspxSo the problem is not that the form is failing to close, it is failing to hide. You need to look for something in the form that prevents it from hiding. Or, dispose of the form after control returns to the calling form.
Hi Acmar. As I understand the references you mention, that is not the problem I have having. My second form absolutely closes when I click the DONE button (or the close of the dialog box). The issue I have is that the form does not close when it encounters a “Me.Close()” in any other part of the code in the second form. I am trying to use Me.Close() in my code to immediately get out of the second form and back to the first form.
Monday, November 27, 2017 9:03 PM
Hi Cor. I read what you wrote but I did not understand it and after this I still don't.
Hi TJBlues, I read what you wrote, but I do not understand it and after this I still don't, maybe better to tell what you did not understand.
Your problem is so simple but many don't understand the way it is done in VB. That lies in the fact that currently the application framework in windows forms since version VB8 incorporates the Program module.
That was to help VB6 programmers to make it easier, but that help had in fact reverse side effect. It does not exist in that way in other VB templates then Windows Forms and is in the other .Net programs completely not.
Mainly try to look at what I wrote in my first message. And know that if you open a form with ShowDialog it is the same extras as with VB6. If you click on the close button of that, it does return a dialog result of OK and that makes it even more confusing.
Success
Cor
Monday, November 27, 2017 9:14 PM
Me.Close does not have effect on form that is not displayed, and it does not prevent the form to be displayed when ImgPreviewForm.ShowDialog is called after ImgPreviewForm.LoadImgsInfoToArrays (inside unclear coverView.ShowDialog, for example).
Monday, November 27, 2017 10:12 PM
Me.Close does not have effect on form that is not displayed, and it does not prevent the form to be displayed when ImgPreviewForm.ShowDialog is called after ImgPreviewForm.LoadImgsInfoToArrays (inside unclear coverView.ShowDialog, for example).
Sorry Viorel,
I really don't understand what you write.
It is so simple, try this code. Simply 2 forms and one button. Direct done using VB and not first C# and then convert.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Hide()
Using DubForm As New Form2
If DubForm.ShowDialog <> DialogResult.Cancel Then
Close()
Else
Show()
End If
End Using
End Sub
End Class
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
DialogResult = DialogResult.Cancel
End Sub
End Class
Success
Cor
Wednesday, November 29, 2017 3:41 PM
I made a sample, new project with 2 forms.
Form1 Code:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Using F2 As New Form2
F2.ShowDialog()
End Using
End Sub
End Class
Form2 Code:
Public Class Form2
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim Numerator As Decimal
Dim Denominator As Decimal
Dim Result As Decimal
Try
Numerator = CDec(TextBox1.Text)
Denominator = CDec(TextBox2.Text)
Result = Numerator / Denominator
TextBox3.Text = Result.ToString
Catch ex As Exception
MessageBox.Show("Division Error" & vbNewLine & ex.Message)
Me.Close()
End Try
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Me.Close()
End Sub
End Class
Once Form2 is open, if you leave either Numerator or Denominator Blank, or enter something that's not a number, or 0 for Denominator, the program shows an error message and closes.
Wednesday, November 29, 2017 6:34 PM
Frank. Thanks very much for your help and the time you spent building this simplified version of a dual form project. It helped me immensely.
I'm glad that it helped.
There's nothing like stepping into the code and watching what does what.
:)
"A problem well stated is a problem half solved.” - Charles F. Kettering