Check if any dialog is open - vb.net

Does anybody see my mistake here?
I am unable to recognize if a form is shown as a dialog in my app.
Public Class Form1
Private m As Form2
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
Me.Text = DateTime.Now.ToLongTimeString & " " & IsAnyDialogShown()
End Sub
Public Function IsAnyDialogShown() As Boolean
For Each f As Form In Me.OwnedForms
If f.Owner Is Me Then
Return True
End If
Next
End Function
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
m = New Form2
m.ShowDialog()
End Sub
End Class

What you are looking is for the property modal.
Check if the form's modal property is true (that is meaning that the form is showed with ShowDialog)
For Each f As Form In Me.OwnedForms
If f.Modal=True Then
'your code here
End If
Next
Now for your mistake (I haven't visual studio to try it right now) but your IsAnyDialogShown(), it seems that it returns always true :
For Each f As Form In Me.OwnedForms ' (So f belongs to Me)
If f.Owner Is Me Then 'f.Owner is always me because you are seaching in forms that have as owner the Me form
Return True
End If
Next
Hope I helped a little.
Tell me if I can do something more
So after your comments.
Try this:
For Each frm as Form In Application.OpenForms
If frm.Modal=True Then
'do something
'Actually you should have only one form because only one can be in modal state
end if
Next

You need to check Visible property of the form, which is the boolean.
If it is true, then form is shown, else it's hidden.

That's just doing forms owned by Me. Nothing to do with whether they are dialog forms.
ie.e it will pick up normal forms.
Also if you want this to work as expected , you should use the overload where you pass the owner.
as in m.ShowDialog(Me);
Not something I've ever done but if Owner isn't me in Me.OwnedForms I want my money back.

Related

When a ComboBox value is selected, output particular text (Visual Basic)

I'm creating a decision interface for clinical support with numerous amounts of combo boxes with boolean values 'Yes|No". However I want it so if the user choses either yes or no, a button can be clicked at the bottom and then another windows form appears and says whether they have cancer or not.
For example, if the user clicks 'yes' in the comboBox and then clicks the 'submit' button, another form will appear and the text box will say whether they have cancer or not. Would anyone be able to supply an example of how this would work? I have the form with the combo boxes, a button that links to another form, and a textbox inside the second form....but I can't get the information between the two forms.
The code I have at the moment is
Private Sub submit_Click(sender As Object, e As EventArgs) Handles submit.Click
If (RectalBleeding.SelectedItem = "Yes") Then Outcome.OutcomeBox.Text = "you have cancer" End If Outcome.Show()
End Sub
Particular combo box im trying to link is called 'RectalBleeding'. The button on the decision interface form is called 'submit' the second form is called 'outcome'. The box inside outcome is called 'outcomeBox' I want it so that if 'Yes' was chosen in the comboBox, the user clicks 'submit' second form appears and in the text box it says "you have cancer"
Thanks!
You can use public properties and constructors to pass values between two forms. Below is some code that uses these tools for your purpose.
Here is the code for the main form:
Public Class Form1
Private frm As Outcome
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddDecision()
End Sub
Private Sub AddDecision()
RectalBleeding.Items.Add("Yes")
RectalBleeding.Items.Add("No")
End Sub
Private Sub Submit_Click(sender As Object, e As EventArgs) Handles Submit.Click
If RectalBleeding.Text = "Yes" Then
frm = New Outcome("You have cancer")
Else
frm = New Outcome("You don't have cancer")
End If
frm.Show()
End Sub
End Class
and here for the outcome form
Public Class Outcome
Private _Decision As String
Public Property Decision() As String
Get
Return _Decision
End Get
Set(ByVal value As String)
_Decision = value
End Set
End Property
Private Sub Outcome_Load(sender As Object, e As EventArgs) Handles MyBase.Load
FillTextBox()
End Sub
Public Sub New(ByVal results As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.Decision = results
End Sub
Private Sub FillTextBox()
outcomeBox.Text = Me.Decision
End Sub
End Class

How Show a Form on top of other?

I have a first Form that is always displayed of way:
Maximized and as content a printscreen of atual screen
Always on top
without borders
and now I want show a second Form on top this first Form, but I haven't success until this moment, in another words, this second Form don't is displayed on top. So how I can do it? All suggestions here are welcome.
Here is how I'm making for show the first Form:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each s As Screen In Screen.AllScreens
Dim Locker As New Form2(s, 0.3)
Locker.Show()
Next
End Sub
End Class
=========================================================================
Public Class Form2
Public Sub New(ByVal scrn As Screen, ByVal FrmOpacity As Double)
InitializeComponent()
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Me.StartPosition = FormStartPosition.Manual
Me.Bounds = scrn.Bounds
Me.TopMost = True
Me.Opacity = FrmOpacity
Me.ShowInTaskbar = False
Me.BackgroundImageLayout = ImageLayout.None
CaptureScreen(scrn)
End Sub
Private Sub CaptureScreen(ByVal s As Screen)
Using ScreenImg As New Bitmap(s.Bounds.Width, s.Bounds.Height)
Using g As Graphics = Graphics.FromImage(ScreenImg)
g.CopyFromScreen(s.Bounds.Location, Point.Empty, ScreenImg.Size, CopyPixelOperation.SourceCopy)
End Using
Me.BackgroundImage = New Bitmap(ScreenImg)
End Using
End Sub
End Class
You could simply set the Owner of the form2 to be form1
Public Class Form1
.....
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each s As Screen In Screen.AllScreens
Dim Locker As New Form2(s, 0.3)
Locker.Show(Me)
Next
End Sub
.....
End Class
Passing the instance of Form1 to the Show method of Form2 will set the passed instance of the Form1 as the Owner of all the Locker forms that your create in your loop. In this way the Form2 instance will be always above the Form1 instance. Of course, you could remove the setting of the TopMost=True property that could be assigned only to one form at a time (Only one form could be the TopMost)
From MSDN on Owner form property
When a form is owned by another form, it is closed or hidden with the
owner form. For example, consider a form named Form2 that is owned by
a form named Form1. If Form1 is closed or minimized, Form2 is also
closed or hidden. Owned forms are also never displayed behind their
owner form. You can use owned forms for windows such as find and
replace windows, which should not disappear when the owner form is
selected. To determine the forms that are owned by a parent form, use
the OwnedForms property.
What you want is a Modal Dialog. I don't know vb.Net, but in C# .Net if you say
NameOfFormThatShouldBeOnTop.Show();
The form will just show but not necessarily be on top. However, if you go
NameOfFormThatShouldBeOnTop.ShowDialog();
It will be forced on top. From the documentation, it looks like doing this in vb is pretty similar. I would guess it would be something like
NameOfFormThatShouldBeOnTop.ShowDialog()
If I got that syntax wrong, feel free to edit :)
You may try to load a Sub after the LOAD or SHOWN events, that will contain the below code:
private sub LeaveMeAtTop()
Me.Topmost = True
Me.TopLevel = true
Me.Activate()
Me.ResizeRedraw() = true
Me.ResumeLayout()
Me.Focus()
end sub
It will force the form to be displayed at top of all

How to call a Sub without knowing which form is loaded into panel?

On every DataGridView1_SelectionChanged event I need to run a Private Sub OnSelectionChanged() of the form that is loaded into Panel1 (see the image http://tinypic.com/r/2nu2wx/8).
Every form that can be loaded into Panel1 has the same Private Sub OnSelectionChanged() that initiates all the necessary calculations. For instance, I can load a form that calculates temperatures or I can load a form that calculates voltages. If different element is selected in the main form’s DataGridView1, either temperatures or voltages should be recalculated.
The problem is - there are many forms that can be loaded into Panel1, and I’m struggling to raise an event that would fire only once and would run the necessary Sub only in the loaded form.
Currently I’m using Shared Event:
'Main form (Form1).
Shared Event event_UpdateLoadedForm(ByVal frm_name As String)
'This is how I load forms into a panel (in this case frm_SCT).
Private Sub mnu_SCT_Click(sender As Object, e As EventArgs) Handles mnu_SCT.Click
frm_SCT.TopLevel = False
frm_SCT.Dock = DockStyle.Fill
Panel1.Controls.Add(frm_SCT)
frm_SCT.Show()
Var._loadedForm = frm_SCT.Name
RaiseEvent event_UpdateLoadedForm(Var._loadedForm)
End Sub
‘Form that is loaded into panel (Form2 or Form3 or Form4...).
Private WithEvents myEvent As New Form1
Private Sub OnEvent(ByVal frm_name As String) Handles myEvent.event_UpdateLoadedForm
‘Avoid executing code for the form that is not loaded.
If frm_name <> Me.Name Then Exit Sub
End Sub
This approach is working but I’m sure it can be done way better (I'd be thankful for any suggestions). I have tried to raise an event in the main form like this:
Public Event MyEvent As EventHandler
Protected Overridable Sub OnChange(e As EventArgs)
RaiseEvent MyEvent(Me, e)
End Sub
Private Sub DataGridView1_SelectionChanged(sender As Object, e As EventArgs) _
Handles DataGridView1.SelectionChanged
OnChange(EventArgs.Empty)
End Sub
but I don't know to subscribe to it in the loaded form.
Thank you.
Taking into account Hans Passant’s comments as well as code he posted in related thread I achieved what I wanted (see the code below).
Public Interface IOnEvent
Sub OnSelectionChange()
End Interface
Public Class Form1
' ???
Private myInterface As IOnEvent = Nothing
' Create and load form.
Private Sub DisplayForm(frm_Name As String)
' Exit if the form is already displayed.
If Panel1.Controls.Count > 0 AndAlso _
Panel1.Controls(0).GetType().Name = frm_Name Then Exit Sub
' Dispose previous form.
Do While Panel1.Controls.Count > 0
Panel1.Controls(0).Dispose()
Loop
' Create form by its full name.
Dim T As Type = Type.GetType("Namespace." & frm_Name)
Dim frm As Form = CType(Activator.CreateInstance(T), Form)
' Load form into the panel.
frm.TopLevel = False
frm.Visible = True
frm.Dock = DockStyle.Fill
Panel1.Controls.Add(frm)
' ???
myInterface = DirectCast(frm, IOnEvent)
End Sub
Private Sub DataGridView1_SelectionChanged(sender As Object, e As EventArgs) _
Handles DataGridView1.SelectionChanged
' Avoid error if the panel is empty.
If myInterface Is Nothing Then Return
' Run subroutine in the loaded form.
myInterface.OnSelectionChange()
End Sub
End Class
One last thing – it would be great if someone could take a quick look at the code (it works) and confirm that it is ok, especially the lines marked with “???” (I don’t understand them yet).

One button to control another button on many user controls

Hey and sorry for another strange question...
I have 25 UserControls with a Start_Button on each of them - this Start_Button can either be Visible or not depending on whether the UserControl is active. On my form1 I have a Start_All button.
I would like to simulate a click of all the UserControl's Start_Buttons which are visible only.
Instead of simulating click-events expose a method for the start-functionality and call this method from the Start_Button.Click-event. Then you can use this method from wherever you want. On this way your code remains readable and reusable.
You should also provide an Active property in your UserControl which you can simply link to your start-button's Visible-property.
Presuming that the user-controls are in a container-control like Panel:
Public Sub StartAll()
Dim allActiveUserControls =
From uc In controlPanel.Controls.OfType(Of MyUserControlType)()
Where uc.Active
For Each uc In allActiveUserControls
uc.Start()
Next
End Sub
Here is an example for the Active property:
Public Property Active As Boolean
Get
Return StartButton.Visible
End Get
Set(value As Boolean)
StartButton.Visible = value
End Set
End Property
and here are the Start method and the event-handlers:
Public Sub Start()
' Do Something ... '
End Sub
Private Sub StartButton_Click(sender As System.Object, e As System.EventArgs) Handles StartButton.Click
Start()
End Sub
Private Sub Start_All_Click(sender As System.Object, e As System.EventArgs) Handles Start_All.Click
StartAll()
End Sub

VB.NET Form Hiding Issue

I have a custom form, B. B is created by A, which has a handle to B.VisibleChanged.
B only has an OK and Cancel button on it, and I want to do some logic when OK is hit.
B's OK button is dealt with like this:
Me.Result = Windows.Forms.DialogResult.OK
Me.Hide()
The code in A is properly hit and run, but it never hides B. When I check the values of the properties on B, it shows me Visible = False.
Does anyone have any suggestions as to the possible cause of this issue?
Edit
This form was shown using the Show() command, as I'm making a later call to have the form flash using FlashWindow().
Not exactly sure about your question.
why not use me.Close() instead of me.Hide?
Is it OK to have multiple instances of B at a time? If not, go for ShowDialog.
If you can rephrase the question, someone can probably resolve your problem.
I suppose you want to display a messagebox with an ok & cancel button. Instead of using a form use a mesagebox.
eg:
DialogResult dgResult = MessageBox.Show("Click Yes or No", "Test App", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (DialogResult.OK == dgResult)
{
//Do what you want.
}
else
{
//Do nothing.
}
If you are going to use a form, to do that & wanted to modify the parent's form, it would be advisable to use delegates to prevent form B from modifying form A's variables.
Else: (Not recommended)
Declare form B as a member variable of form A.
when required instantiate form B.
do B.ShowDialog();
internally in OK & cancel do this.dispose();
Again when you need form B just instantiate. re - instantiation will not be too much of an overhead if you dont call it very often.
But if you only need OK Cancel, use message box instead.
The show/hide approach works for me:
Public Class frmViewChild ' your form A
Private WithEvents _edit As frmEdit
'code
Private Sub editCell()
Dim PKVal As String
Dim PKVal2 As String
Dim fieldOrdinalPos As Integer
Dim isLastField As Boolean
If _edit Is Nothing Then
_edit = New frmEdit
_edit.MdiParent = Me.MdiParent
End If
'code
_edit.init(<params>)
If Not _edit.isNothing Then
_edit.Show()
_edit.WindowState = FormWindowState.Maximized
_edit.BringToFront()
End If
End Sub
'code
Private Sub _edit_VisibleChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _edit.VisibleChanged
If Not _edit.Visible Then
WindowState = FormWindowState.Maximized ' revert after closing edit form
End If
End Sub
Public Class frmEdit ' your form B
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
Dim ret As Integer
doOK(ret)
If ret > -1 Then ' no error
Me.Hide() ' close form, but didn't cancel
End If
End Sub
HTH