Showdialog disappears when using alt + tab - vb.net

I have a MDI container and also I use my own custom class MsgBox called ShowMsg which I use mostly on the child forms, so far it worked fine until I realized that the Showmsg (which is a ShowDialog) did not stick to the parent form (MDIContainer).
In a child form, I use a thread to run a process and show a progress bar, if the user switch to another program using alt+tab while the process is working and finishes, when user returns to my app using Alt+Tab, the ShowMsg is not there, it disappears and there's nothing I can do to bring it back, so my app becomes useless.
This only happens when calling it from a different thread than the Form itself, I am pulling my hair off with this, why disappears????
This is part of the code:
Public Function ShowMsg(ByVal Text As String, ByVal Icon As ShowMsgImage, ByVal Title As String) As DialogResult
Dim SMF As New ShowMsgForm
'Set the title bar
SMF.Text = Title
'Select an image and sound based on the Icon parameter
Select Case Icon
Case ShowMsgImage.Alert
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_Warning
SMF.Sound = Media.SystemSounds.Asterisk
Case ShowMsgImage.Confirm
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_Confirm
SMF.Sound = Media.SystemSounds.Question
Case ShowMsgImage.Critical
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_NotAllowed
SMF.Sound = Media.SystemSounds.Hand
Case ShowMsgImage.Info
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_Info
SMF.Sound = Media.SystemSounds.Asterisk
Case ShowMsgImage.Security
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_Lock
SMF.Sound = Media.SystemSounds.Beep
Case ShowMsgImage.UnderConstruction
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_NotAllowed
SMF.Sound = Media.SystemSounds.Asterisk
Case ShowMsgImage.Ok
SMF.MessagePictureBox.Image = My.Resources.ico_showmsg_ok
SMF.Sound = Media.SystemSounds.Asterisk
End Select
'Set other properties
SMF.TextLabel.Text = Text
SMF.QuestionTextLabel.Text = ""
SMF.Button1.Visible = True
SMF.Button1.Text = "OK"
SMF.Button1.DialogResult = DialogResult.OK
SMF.Button2.Visible = False
SMF.Button3.Visible = False
'Resize the form
SMF.SizeForm()
'Set its starting position
SMF.StartPosition = FormStartPosition.CenterScreen
'Display the form modally and return its DialogResult
Try
Return SMF.ShowDialog()
Catch ex As Exception
End Try
End Function
Sample on the child:
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
Dim backgroundThread As New Thread(AddressOf Processdata)
backgroundThread.Start()
End Sub
Sub ShowMsgDelegate(msg As String)
ShowMsg(msg, ShowMsgImage.Ok, "")
End Sub
Delegate Sub MyDelegate(ByVal msg As String)
Private Sub Processdata()
'Do stuff and when finished...
Me.Invoke(New MyDelegate(AddressOf ShowMsgDelegate), New Object() {"Done"})
End Sub

After several days and tests, I think I found the answer.
I added:
TopLevel = True when showing
Paramenter ParentForm
SMF.TopLevel = True
Return SMF.ShowDialog(**frm**)
Where frm is the form that calls ShowMsg

Related

Creating a confirmation which switches back to previous radio button if user cancels

So I currently have a form where I have 4 teams, each with 4 teammates. This cannot change.
my form GUI
Initially when the program starts, it automatically selects the "current value" radio button which displays labels with blank data, you can then select "edit values" which can be saved by pressing the big green apply button. This stores the data under a 2d array named stTeamName, which the labels reference whenever you select "current value" again.
There are 4 radio buttons which allow you to switch between the teams.
My problem is, when I change the radio buttons, any data put into the text labels that has not been saved will be deleted.
I solved this problem by adding a message box which will stop the data in the labels from changing unless the user gives confirmation to do so.
However, my only problem is that after I cancel this, the radio button stays at the current selection which does not help.
I solved this issue by using rbTeamName1.Checked = True (rbTeamname 1 to 4 being the radio buttons named team 1-4) to switch back to the previous state.
This of course only goes back to rbTeamname1 no matter what, so I employed an 1d array and select case to help solve this issue.
"""
Dim RadioCounter(1) As Integer
the code below simply gives the default Radio button value on load.`
Sub DeclareRadio(RadioButton)
RadioButton(1) = 1
End Sub
"""
Whenever a radio button is successfully selected, RadioCounter(1) is set to the number 1-4 respectively. Whenever a new radio button is selected, the value of RadioCounter(1) is moved to RadioCounter(0) and the current radio button's value is to RadioCounter(1).
If the user selects no, RadioCounter(0)'s value is referenced and a select case selects the radio button.
(Please note, RadioTeam() is used as a counter to store Team name and Teammate name string variables correctly within the 2d array: stTeamName. I will most likely merge this with RadioCounter as soon as I get this problem fixed)
"""
Private Sub rbTeamName1_CheckedChanged(sender As Object, e As EventArgs) Handles rbTeamName1.CheckedChanged
'note txtTeamName starts at 0, however RadioTeam starts at 1, RadioTeam = 0 has no team designated to it.
'this function is for swapping teams via radio button, each time, a confirmation is given to make sure the user saves the current team, or risk deletion of the inputted data.
RadioCounter(1) = RadioCounter(0)
stTeamname(0, RadioTeam) = txtTeamName.Text
stTeamname(1, RadioTeam) = txtMate1.Text
stTeamname(2, RadioTeam) = txtMate2.Text
stTeamname(3, RadioTeam) = txtMate3.Text
stTeamname(4, RadioTeam) = txtMate4.Text
Dim Dialog As DialogResult
Dialog = MessageBox.Show("Are you sure you want to change team? Any unsaved changes will be lost. If this box shows on starting the program, just press no", "Change team?", MessageBoxButtons.YesNo)
If Dialog = DialogResult.No Then
'need to run function to check previous result of radio button'
Select Case RadioCounter(0)
Case 1
rbTeamName1.Checked = True
Case 2
rbTeamName2.Checked = True
Case 3
rbTeamName3.Checked = True
Case 4
rbTeamName4.Checked = True
End Select
ElseIf Dialog = DialogResult.Yes Then
RadioCounter(1) = 1 'this equals the respective number for each radio button'
RadioTeam = 1
txtTeamName.Text = stTeamname(0, RadioTeam)
txtMate1.Text = stTeamname(1, RadioTeam)
txtMate2.Text = stTeamname(2, RadioTeam)
txtMate3.Text = stTeamname(3, RadioTeam)
txtMate4.Text = stTeamname(4, RadioTeam)
lblTeamName.Text = stTeamname(0, RadioTeam)
lblMate1.Text = stTeamname(1, RadioTeam)
lblMate2.Text = stTeamname(2, RadioTeam)
lblMate3.Text = stTeamname(3, RadioTeam)
lblMate4.Text = stTeamname(4, RadioTeam)
End If
End Sub
"""
....Or it should do that. But it doesnt. Im not sure why, but when I force it to check a specific radio button, by removing the select case and only running rbTeamName4.Checked = True it will work perfectly fine, theres something about the select case that simply doesnt run the code.
Also, despite stTeamname(0, RadioTeam) = txtTeamName.Text etc. being given before the messagebox shows, if I do not press the apply button to save, press another team button, then press no, it will still not save those parameters, which I find extremely weird.
What is the ideal solution to this?
To clarify:
If a user writes team names and teammates and does not press the apply button to save and then changes team by selecting another radio button, a text box should appear asking whether they want to switch team and lose the data (Yes) or stay on the previous radio button to edit and apply the data (No).
Upon pressing no, the program automatically switches the current radio button to the previous selection to make it seem as if no radio button was selected in the first place.
And im not sure if I have to make it obvious but im new to both stackoverflow and VB.net in general. Thank you in advance.
Essentially what you are asking for is dirty form checking. The basic principle is that you need to compare the value to what it was previously.
So for example:
When the TextBox values change, set a form level boolean variable to true
When you go to switch teams or current/edit you would check if that form level boolean variable is true
If the variable is true then you would display the prompt, otherwise just do the action
After the action, reset the global level boolean variable
There are some caveats, for example, when you toggle between current/edit the check changed will fire twice: once for the current radio button and once for the edit. But you just need to work around those edge cases.
Here is a largely untested example for you to go off of:
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Public Class Form1
Private _team1 As Team
Private _team2 As Team
Private _team3 As Team
Private _team4 As Team
Private _isFormDirty As Boolean = False
Private _selectedTeamRadioButton = RadioButtonTeam1
Private Sub RadioButtonCurrent_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButtonCurrent.CheckedChanged
If (RadioButtonCurrent.Checked AndAlso _isFormDirty AndAlso MessageBox.Show("By doing this, you will lose all unsaved changes. Are you sure?", "Dirty Form", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No) Then
RadioButtonEdit.Checked = True
Return
End If
If (Not RadioButtonCurrent.Checked) Then
Return
End If
TextBoxTeamName.Enabled = False
TextBoxTeammate1.Enabled = False
TextBoxTeammate2.Enabled = False
TextBoxTeammate3.Enabled = False
TextBoxTeammate4.Enabled = False
ResetTeam()
End Sub
Private Sub RadioButtonEdit_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButtonEdit.CheckedChanged
TextBoxTeamName.Enabled = True
TextBoxTeammate1.Enabled = True
TextBoxTeammate2.Enabled = True
TextBoxTeammate3.Enabled = True
TextBoxTeammate4.Enabled = True
End Sub
Private Sub RadioButtonTeamChanged(sender As Object, e As EventArgs) Handles RadioButtonTeam1.CheckedChanged, RadioButtonTeam2.CheckedChanged, RadioButtonTeam3.CheckedChanged, RadioButtonTeam4.CheckedChanged
If (_selectedTeamRadioButton IsNot DirectCast(sender, RadioButton) AndAlso _isFormDirty AndAlso MessageBox.Show("By doing this, you will lose all unsaved changes. Are you sure?", "Dirty Form", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No) Then
_selectedTeamRadioButton.Checked = True
Return
End If
If (_selectedTeamRadioButton IsNot DirectCast(sender, RadioButton)) Then
Return
End If
_selectedTeamRadioButton = DirectCast(sender, RadioButton)
ResetTeam()
End Sub
Private Sub TextBoxTeamValueChanged(sender As Object, e As EventArgs) Handles TextBoxTeamName.TextChanged, TextBoxTeammate1.TextAlignChanged, TextBoxTeammate2.TextAlignChanged, TextBoxTeammate3.TextAlignChanged, TextBoxTeammate4.TextAlignChanged
_isFormDirty = True
End Sub
Private Sub ButtonApply_Click(sender As Object, e As EventArgs) Handles ButtonApply.Click
Select Case True
Case RadioButtonTeam1.Checked
_team1 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
Case RadioButtonTeam2.Checked
_team2 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
Case RadioButtonTeam3.Checked
_team3 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
Case RadioButtonTeam4.Checked
_team4 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
End Select
_isFormDirty = False
End Sub
Private Sub ButtonDeleteTeam_Click(sender As Object, e As EventArgs) Handles ButtonDeleteTeam.Click
If (MessageBox.Show("Are you sure you want to delete this team?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No) Then
Return
End If
_isFormDirty = False
Select Case True
Case RadioButtonTeam1.Checked
_team1 = New Team()
Case RadioButtonTeam2.Checked
_team2 = New Team()
Case RadioButtonTeam3.Checked
_team3 = New Team()
Case RadioButtonTeam4.Checked
_team4 = New Team()
End Select
ResetTeam()
End Sub
Private Sub ResetTeam()
Dim selectedTeam As Team = Nothing
Select Case True
Case RadioButtonTeam1.Checked
selectedTeam = _team1
Case RadioButtonTeam2.Checked
selectedTeam = _team2
Case RadioButtonTeam3.Checked
selectedTeam = _team3
Case RadioButtonTeam4.Checked
selectedTeam = _team4
End Select
If (selectedTeam IsNot Nothing) Then
TextBoxTeamName.Text = selectedTeam.Name
TextBoxTeammate1.Text = selectedTeam.Teammate1
TextBoxTeammate2.Text = selectedTeam.Teammate2
TextBoxTeammate3.Text = selectedTeam.Teammate3
TextBoxTeammate4.Text = selectedTeam.Teammate4
Else
TextBoxTeamName.Clear()
TextBoxTeammate1.Clear()
TextBoxTeammate2.Clear()
TextBoxTeammate3.Clear()
TextBoxTeammate4.Clear()
End If
End Sub
End Class
Public Class Team
Implements INotifyPropertyChanged
Private _name As String
Public Property Name As String
Get
Return _name
End Get
Set(value As String)
If (_name <> value) Then
_name = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate1 As String
Public Property Teammate1 As String
Get
Return _teammate1
End Get
Set(value As String)
If (_teammate1 <> value) Then
_teammate1 = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate2 As String
Public Property Teammate2 As String
Get
Return _teammate2
End Get
Set(value As String)
If (_teammate2 <> value) Then
_teammate2 = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate3 As String
Public Property Teammate3 As String
Get
Return _teammate3
End Get
Set(value As String)
If (_teammate3 <> value) Then
_teammate3 = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate4 As String
Public Property Teammate4 As String
Get
Return _teammate4
End Get
Set(value As String)
If (_teammate4 <> value) Then
_teammate4 = value
NotifyPropertyChanged()
End If
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class

Windows Forms Modal Form Closes instantly when Base form is not Active

I have a Winforms Application which should notify the user when something in a database changes. For that i use Sql-Dependencys, which works fine.
When the Dependency fires i am able to show a form with some Buttons so the user can decide what he wants to do.
After one Button i want to show a Dialog, but the first Dialog always gets closed instantly.
The only fix i found until now is restoring the base form and activating it, but that is not the solution i am looking for.
For the code i am doing the Following:
This Method gets called when something changes in the Database
Private Sub NutzerBenachrichtigen(Aenderung As Aenderung)
If InvokeRequired Then
Me.BeginInvoke(New MethodInvoker(Sub()
ErzeugeBenachrichtigung(Aenderung)
End Sub))
Else
ErzeugeBenachrichtigung(Aenderung)
End If
End Sub
This Method Displays the first form (HeadsUp is taken from this here :https://github.com/glm9637/MaterialWinforms/blob/master/MaterialWinforms/Controls/HeadsUp.cs)
Private Sub ErzeugeBenachrichtigung(ByVal Aenderung As Aenderung)
If Aenderung.istAktuellerBenutzer Then
Dim objHeadsUp As New HeadsUp()
objHeadsUp.Titel = "Neue Aenderung"
If Aenderung.EventTyp.ToLower = "alter" Then
objHeadsUp.Text = String.Format("Du hast etwas an {0} {1} {2} geändert. {3}Willst du etwas dazu schreiben?", _
If(Aenderung.BetroffenesObjekt.EntitaetTyp.Name = New EntitaetTyp.Trigger().Name, "dem", "der"), _
Aenderung.BetroffenesObjekt.EntitaetTyp.Name, Aenderung.BetroffenesObjekt.Name, vbNewLine)
Else
objHeadsUp.Text = String.Format("Du hast {0} {1} {2} erstellt. {3}Willst du etwas dazu schreiben?", _
If(Aenderung.BetroffenesObjekt.EntitaetTyp.Name = New EntitaetTyp.Trigger().Name, "den", "die"), _
Aenderung.BetroffenesObjekt.EntitaetTyp.Name, Aenderung.BetroffenesObjekt.Name, vbNewLine)
End If
objHeadsUp.Tag = Aenderung.BetroffenesObjekt
Dim objButtonSchliessen = New MaterialFlatButton
objButtonSchliessen.Tag = objHeadsUp
objButtonSchliessen.Text = "Schliessen"
AddHandler objButtonSchliessen.Click, AddressOf SchliesseHeadsUp
objHeadsUp.Buttons.Add(objButtonSchliessen)
Dim objButtonHistorie = New MaterialFlatButton
objButtonHistorie.Tag = objHeadsUp
objButtonHistorie.Text = "Historieneintrag"
AddHandler objButtonHistorie.Click, AddressOf HistorienEintragHinzufuegen
objHeadsUp.Buttons.Add(objButtonSchliessen)
Dim objButtonDokumentation = New MaterialFlatButton
objButtonDokumentation.Tag = objHeadsUp
objButtonDokumentation.Text = "Dokumentation"
AddHandler objButtonDokumentation.Click, AddressOf DokumentationBearbeiten
objHeadsUp.Buttons.Add(objButtonSchliessen)
objHeadsUp.Buttons.Add(objButtonHistorie)
objHeadsUp.Buttons.Add(objButtonDokumentation)
objHeadsUp.Show()
ElseIf Aenderung.EventTyp = "CLOSE_MESSAGE" Then
Dim objHeadsUp As New HeadsUp()
objHeadsUp.Titel = "Achtung"
objHeadsUp.Text = "Die Anwendung muss für eine Aktualisierung geschlossen werden."
Dim objButtonSchliessen = New MaterialFlatButton
objButtonSchliessen.Tag = objHeadsUp
objButtonSchliessen.Text = "Anwendung Schliessen"
AddHandler objButtonSchliessen.Click, AddressOf AnwendungSchliessen
objHeadsUp.Buttons.Add(objButtonSchliessen)
objHeadsUp.Show()
Else
If mtc_UebersichtTabControl.SelectedTab.Text = "Aenderung" Then
mAenderungenUebersicht.Aktualisieren()
End If
End If
End Sub
Finally when the "Historieneintrag" Button is pressed this Method gets called:
Private Sub HistorienEintragHinzufuegen(sender As Object, e As EventArgs)
Dim blnNachDialogVerstecken As Boolean = False
Dim objFlatButton As MaterialFlatButton = sender
Dim HeadsUp As HeadsUp = objFlatButton.Tag
Dim Objekt As Entitaet = HeadsUp.Tag
Dim objOldLocation As System.Drawing.Point = Location
HeadsUp.Close()
Dim objDialogContent As New HistorienEintrag()
''Hacky: Ansonsten wird der Dialog sofort geschlossen
If WindowState = FormWindowState.Minimized Or Not Visible Then
Location = New System.Drawing.Point(-Width * 2, -Height - 2)
Me.Show()
blnNachDialogVerstecken = True
End If
Activate()
If MaterialDialog.Show("Neuer Historien Eintrag", objDialogContent, MaterialWinforms.Controls.MaterialDialog.Buttons.OKCancel, MaterialDialog.Icon.Info) = DialogResult.OK Then
Objekt.HistorieSpeichern(objDialogContent.Ergebniss)
End If
If blnNachDialogVerstecken Then
Me.Hide()
Location = objOldLocation
End If
End Sub
In here the first modal Form, so a MessageBox.Show("") or any other form closes Instantly if i don't do the show and activate part.
What am i doing wrong here?
Project > (Project) Properties > Application > Shutdown mode
change from when startup form closes to when last form closes

calling button class in a form in vb.net

I am herewith develop an application but I have created a class which calls button events(i.e. enable or visible)
Public Class ClassfrmLoad
Dim btnAdd As New Button
Dim btnEdit As New Button
Private Sub FormLoad()
Me.btnAdd.Visible = True
Me.btnAdd.Enabled = True
Me.btnEdit.Visible = True
Me.btnEdit.Enabled = False
End Sub
End Class
I am actually created the button events class(classfrmLoad) for the way which buttons should be enabled and visible when each & every form loading.
There are 6 buttons in the forms (frm1, frm2 etc.,) like btnAdd, btnEdit, btnCancel etc., i don't want to display the buttons(visible/enable) while loading the form.
Here is the question:
How can i call this class(classfrmLoad) events to alter (enable/visible) the buttons positioned in the forms(frm1, frm2, etc.,) and how to get the buttons events in those forms?
Dear Sergio,
Thanks for your immediate response. I am missing something and it is not as expected, here is my complete code for the form including yours.
This is the code you suggested for the classfrmLoad:
Public Class ClassfrmLoad
Public Shared Sub FormLoad(ByRef Target As Form)
For Each ctl As Control In Target.Controls
If Not TypeOf ctl Is Button Then Continue For
Dim btn As Button = DirectCast(ctl, Button)
Select Case btn.Name.ToLower()
Case "btnadd"
btn.Visible = True
btn.Enabled = True
Case "btnsave"
btn.Visible = False
btn.Enabled = False
Case "btnedit"
btn.Visible = True
btn.Enabled = True
Case "btncancel"
btn.Visible = True
btn.Enabled = False
Case "btnclose"
btn.Visible = True
btn.Enabled = True
Case "btnupdate"
btn.Visible = False
btn.Enabled = False
Case "btnfind"
btn.Visible = False
btn.Enabled = False
'and so on
End Select
Next
End Sub
End Class
This is the code for the formload event:
Private Sub frmCreate_Unit_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ClassfrmLoad.FormLoad(Me)
'Display software and title of the page
Me.Text = msgCap & " | " & " CREATE UNIT"
Me.lblComp.Text = CompName
Me.stBar_User.Text = frmMain.stBar_User.Text
Me.stBar_UserID.Text = frmMain.stBar_UserID.Text
Me.stBar_G_ID.Text = frmMain.stBar_G_ID.Text
Me.stBar_G_No.Text = frmMain.stBar_G_No.Text
Me.cboUnit.Visible = False
Me.txtUnit_Long.Visible = True
Me.btnfind.Visible = False
Me.txtUnit_ID.Enabled = False
Me.btnadd.Focus()
End Sub
Please help me to sort out this one. Thanks...
Every form in WinForms is a class instance, inherited from Form class.
Because of this, you cannot make static references to it's members from another class, given any Form instance.
Generic class won't cut it either because you're after specific class members.
I would take advantage of the Controls collection and would check it's name and type. Once caught, we can cast the control to button and set it's visibility and access.
For this, you should make small adjustments to your code:
Public Class ClassfrmLoad
Public Shared Sub FormLoad(ByRef Target As Form)
For Each ctl As Control In Target.Controls
If Not TypeOf ctl Is Button Then Continue For
Dim btn As Button = DirectCast(ctl, Button)
Select Case btn.Name.ToLower()
Case "btnadd", "btnedit"
btn.Visible = True
btn.Enabled = True
'and so on
End Select
Next
End Sub
End Class
Changed the FormLoad visibility and access. It should be shared so we don't need to create unnecessary instances of this class
Added a parameter, passe by reference that referrs the target form. This will assure that you can use it on any class that inherits Form class
Iterated the Controls collection and find a candidate based on it's type and name
When found, we cast it to Button and access it's properties normally.
It's just an example, based on your code.
You should now call it on every Form's formload handler, like so:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ClassfrmLoad.FormLoad(Me)
End Sub
Finally I got the solution. It is very simple and any way thanks to sergio.
Here is the complete code.
Public Class ClassfrmLoad
Public Shared Sub formLoad(ByVal btnAdd As Button, ByVal btnEdit As Button, ByVal btnSave As Button, ByVal btnCancel As Button, ByVal btnClose As Button, ByVal btnUpdate As Button, ByVal btnFind As Button)
btnAdd.Visible = True
btnAdd.Enabled = True
btnSave.Visible = False
btnSave.Enabled = False
btnCancel.Visible = True
btnCancel.Enabled = False
btnClose.Visible = True
btnClose.Enabled = True
btnEdit.Visible = True
btnEdit.Enabled = True
btnUpdate.Visible = False
btnUpdate.Enabled = False
btnFind.Visible = False
btnFind.Enabled = False
End Sub
End Class
And calling proceedure in a form like this:
Dim x As New ClassfrmLoad
ClassfrmLoad.formLoad(Me.btnAdd, Me.btnEdit, Me.btnSave, Me.btnCancel, Me.btnClose, Me.btnUpdate, Me.btnFind)

Progress Bar will not work, even when all the program does is show a Progress Bar

I have a form which, at present, is doing nothing but opening. The form has 2x controls - a 'Close' button and a Progress Bar. However, when I open the form, I get nothing. The Progress Bar just sits there doing nothing.
I've tried both Marquee (which I understand may not work in Windows 8) and Continuous, but I can't get anywhere with either.
This is how I'm showing the form when the program starts -
Sub main()
Dim ProgressForm As New formProgress
ProgressForm.ShowDialog()
End Sub
And below are the properties for the Progress Bar. Am I missing something that would get this bar working? Thanks.
Additional Information
For my full program, I did originally try using the Block style for the Progress Bar, but I kept getting the following error when trying to update the Progress Bar from a BackgroundWorker. This is why I am trying to get a simple Marquee/Continuous bar working instead.
Additional information: Cross-thread operation not valid: Control 'proWorking' accessed from a thread other than the thread it was created on.
if you use marquee style you have to set marqueeanimationspeed to some value
//
// progressBar1
//
this.progressBar1.Location = new System.Drawing.Point(91, 118);
this.progressBar1.MarqueeAnimationSpeed = 50;
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(100, 23);
this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
this.progressBar1.TabIndex = 0;
and use continuous style with marqueeanimationsspeed 0 to stop it
For the Progressbar to do something (apart from the Marquee Style) you need to set the Value property. If you have .Minimum=0 and .Maximum=100 then a .Value of 50 means that the Progressbar is half full. If you should use Continuous or Blocks Style depends on the Visual Styles settings and doesn't make a real difference here on Win 7 (maybe it does for example under Win XP).
The Marquee style means that you don't know how far your task has proceeded. The Progressbar then shows a continously moving piece (is only visible at runtime!!). I just tested it in Win 7 and it works.
Here's a little boilerplate I use with a BackgroundWorker and a ProgressBar and Label.
Public Class BackgroundWorkerUI
Private args As New ProgressArgs
Private Sub bw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
'set ProgressBar style to Marquee
args.Style = ProgressBarStyle.Marquee
bw.ReportProgress(0) 'triggers the progress changed event to update UI on correct thread
'some long operation
Threading.Thread.Sleep(5000)
'Set ProgressBar style to Continuous
args.Style = ProgressBarStyle.Continuous
For i As Integer = 0 To 100
If bw.CancellationPending Then
e.Cancel = True
Exit For
End If
args.Current = i
args.Max = 100
args.Status = String.Format("({0} of {1}) Updating...", args.Current, args.Max)
bw.ReportProgress(0)
'some operation
Threading.Thread.Sleep(100)
Next
End Sub
Private Sub bw_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
lblStatus.Text = args.Status
If args.Style = ProgressBarStyle.Marquee Then
bar.Style = args.Style
bar.MarqueeAnimationSpeed = 15
Else
bar.Style = ProgressBarStyle.Continuous
bar.Minimum = args.Min
bar.Maximum = args.Max
bar.Value = args.Current
End If
End Sub
Private Sub bw_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
If e.Error IsNot Nothing Then
MessageBox.Show(e.Error.Message, "Background Worker Exception", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
If e.Cancelled Then
lblStatus.Text = "Operation canceled"
Else
lblStatus.Text = "Done"
End If
End If
End Sub
Private Sub BackgroundWorkerUI_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If bw.IsBusy Then
Dim r = MessageBox.Show("A background process is still running. Are you sure you want to quit?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If r = Windows.Forms.DialogResult.Yes Then
bw.CancelAsync()
End If
e.Cancel = True
End If
End Sub
Private Class ProgressArgs
Inherits EventArgs
Public Property Status As String
Public Property Current As Integer
Public Property Min As Integer
Public Property Max As Integer
Public Property Style As ProgressBarStyle
Public Sub New()
Status = ""
Current = 0
Min = 0
Max = 0
Style = ProgressBarStyle.Continuous
End Sub
End Class
End Class

Send value to parent then close child form, on event

I have a parent form with a combobox populated from a database, from which the user can select. The last value in the combo box is "add new", if the user selects this, a child form opens for the user to add a new value to the database. I have a button press event to add this value to the database, send the new return value to the parent and close the form. The parent should then select the new value from it's combo box and wait for the user to perform another action.
However, the code to send the return value to parent and close the form isn't working correctly. I hide the child, then call a function on it with the parent to access the return value. At this point the child form shows and the code stops before it runs another hide or close.
How can I fix this (code below)?
Parent Combobox event:
Private Sub cmbLocations_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbLocations.SelectedIndexChanged
If Not cmbLocations.SelectedIndex = -1 Then
If cmbLocations.SelectedIndex = cmbLocations.Items.Count - 1 Then
If diaAddLocation.IsAccessible = False Then diaAddLocation.Activate()
diaAddLocation.RequestSender = Me
diaAddLocation.ShowDialog()
FillLocations()
cmbLocations.SelectedIndex = LocationFromLocationName(diaAddLocation.formresult)
diaAddLocation.Close()
diaAddLocation.Dispose()
Else
bttYes.Enabled = True
End If
End If
End Sub
Child Button Press and Return value function
Public Sub bttAddLOCtoDatabase_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bttAddLOCtoDatabase.Click
Dim LocationToBeAdded As String
LocationToBeAdded = "'" & TextBox1.Text & "'"
AddLocation("'" & textbox1.Text & "'")
FormResult = textbox1.Text
GetLocations()
frmFieldMaster.InitialiseNewParameter()
Me.Hide()
End Sub
Public Function Result() As String
Return FormResult
End Function
EDIT:
code with Steve's solution implemented:
Public Sub bttAddLOCtoDatabase_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bttAddLOCtoDatabase.Click
Dim LocationToBeAdded As String
LocationToBeAdded = "'" & TextBox1.Text & "'"
AddLocation("'" & textbox1.Text & "'")
FormResult = textbox1.Text
GetLocations()
frmFieldMaster.InitialiseNewParameter()
DialogResult = Windows.Forms.DialogResult.OK
'me.Hide()
End Sub
Public Function Result() As String
Return FormResult
Me.Close()
End Function
Private Sub cmbLocations_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbLocations.SelectedIndexChanged
Dim ValueTaken As Boolean = False
If Not cmbLocations.SelectedIndex = -1 Then
If cmbLocations.SelectedIndex = cmbLocations.Items.Count - 1 Then
Using diaaddlocation = New diaAddLocation
diaaddlocation.requestsender = Me
If DialogResult.OK = diaaddlocation.showdialog Then
FillLocations()
cmbLocations.SelectedIndex = LocationFromLocationName(diaaddlocation.result)
diaaddlocation.close()
ElseIf DialogResult.Cancel = diaaddlocation.showdialog Then
cmbLocations.SelectedIndex = -1
End If
End Using
Else
bttYes.Enabled = True
End If
End If
End Sub
When I run the code it enters IF DialogResult.OK... and opens the child. Then when I close the child the parent runs the next two lines of code and get the result from the child. After this the parent runs the line IF DialogResult.OK... again and stops with the child open. The code never reaches the diaaddlocation.close line.
You don't need all of this. You could try something like this
If cmbLocations.SelectedIndex = cmbLocations.Items.Count - 1 Then
Using diaAddLocation = new diaAddLocation()
diaAddLocation.RequestSender = Me
if DialogResult.OK = diaAddLocation.ShowDialog() then
FillLocations()
cmbLocations.SelectedIndex = LocationFromLocationName(diaAddLocation.formresult)
End If
End Using
Else
.....
This requires the DialogResult property for bttAddLOCtoDatabase set to DialogResult.OK and the child form AcceptButton property set to bttAddLOCtoDatabase. Now you could remove the Hide() call inside the bttAddLOCtoDatabase_Click method
This works because, until you don't exit the Using statement, your child form is still available to read its properties (results)
EDIT: Not related to the main problem, but these lines are wrong:
ElseIf DialogResult.Cancel = diaaddlocation.showdialog Then
cmbLocations.SelectedIndex = -1
you should go with
Using diaAddLocation = new diaAddLocation()
diaAddLocation.RequestSender = Me
Dim dr = diaAddLocation.ShowDialog()
if dr = DialogResult.OK then
....
else if dr = DialogResult.Cancel then
....
end if
I don’t understand what is issue but if you are not getting value of “FormResult”
It doesn’t matter if you close from but it will be better to set DialogResult before closing it, cause you are showing it as dialog (showdialog)
Verify that diaAddLocation is instance of you window not the window class directly
If name of you form is frmdiaAddLocation then do not use it like
frmdiaAddLocation.showdialog
use it like
Dim diaAddLocation AS frmdiaAddLocation = New frmdiaAddLocation()
diaAddLocation.ShowDialog()
only using like this way will provide you result value