How Show a Form on top of other? - vb.net

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

Related

Label won't update from separate form

I have 2 forms in my program. Form1 has a tab control on it, and on one of these tabs there are a load of labels. Form2 has a few textboxes and dropdown lists on it. Form1 has a button on it that opens Form2 on top of it as a normal form, not as a dialog.
There is code in Form1 that on loading populates the labels on it from a MySQL database. This code is in a separate public sub in the form that is called when the form loads.
What I am trying to do is fill in some of the boxes on Form2, when this Form closes it updates the database with these values (Works fine) and then those values are displayed on Form1. I can get Form2 to run the code in Form1 that populates the labels, but the problem is that the labels on Form1 never actually change. I have tried multiple things, including calling refresh on the labels, trying to change the labels from within Form2 instead of Form1, but they just never update. The .text value of the labels is being updated to the new value, I have checked this via debugging and stopping at the correct points to see what the value is.
Any ideas anyone?? I think it might be to do with the fact that it's Form2 calling the code and for some reason it doesn't have access to change the labels on Form1.
Code:
Form1 (AECSurveyForm)
Private Sub AECSurvey_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadMeterData()
End Sub
Public Sub LoadMeterData()
Dim AECMeteringDataAdapter As New AECMeteringDataTableAdapter
Dim AECMeteringData As AECMeteringDataDataTable
AECMeteringData = AECMeteringDataAdapter.GetAECMeterDataBySurveyUniqueIdentifier(AECGlobalValues.CurrentSurveyUniqueIdentifier)
'utility
Meter1UtilityLabel.Text = AECMeteringData(0)("Utility1")
End Sub
Private Sub MeterButton1_Click(sender As Object, e As EventArgs) Handles Meter1Button.Click
If Not Application.OpenForms().OfType(Of AECMeteringDataForm).Any Then
AECMeteringDataForm.GetData(AECGlobalValues.CurrentSurveyUniqueIdentifier, 1)
AECMeteringDataForm.Show()
End If
End Sub
Form2 (AECMeteringDataForm)
Private Sub AECMeteringDataForm_FormClosing(sender As Object, e As EventArgs) Handles MyBase.Closing
Dim AECMeteringDataAdapter As New AECMeteringDataTableAdapter
Dim AECMeteringData As AECMeteringDataDataTable
AECMeteringData = AECMeteringDataAdapter.GetAECMeterDataBySurveyUniqueIdentifier(AECGlobalValues.CurrentSurveyUniqueIdentifier)
AECMeteringData(0)("Utility1") = UtilityComboBox.SelectedItem.ToString
AECMeteringDataAdapter.Update(AECMeteringData)
AECSurveyForm.LoadMeterData()
End Sub

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).

Passing variables between windows forms in VS 2010

I have two forms. Form 1 allows the user to pick an employee from a dropdown combo box. That employee is then passed onto Form 2 where the user enters additional information regarding that employee. That data will then be passed into a SQL table.
On form 1 I have:
Dim ChangeJobInfo As New Form2(Employee)
ChangeJobInfo.Show()
On Form 2 I have:
Public Sub New(ByVal Employee As String)
MsgBox(Employee)
End Sub
The variable passes just fine. The issue is that nothing shows up on the new form. When I setup Form2, I added a combobox, date picker, two text boxes, submit button, etc., but when the form loads it is completely blank. No errors, the MsgBox returns the right result, but none of my gui elements show up. If I change the code on form 1 to Form2.show() I see the form as laid out in the designer.
Any ideas on how to get those items to show up?
Change your code in Form2.vb for the New sub to this:
Public Sub New(ByVal Employee As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
MsgBox(Employee)
End Sub
If you don't call InitializeComponent(), your complete GUI is not going to render.
You don't even have to use the InitializeComponent or New functions.
I have made an example to show how easily this can be done.
Clicking "Show Form" results in the below:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Form2.Show()
End Sub
which is simply used to display the second form.
By clicking "Pass Data" results in the following code:
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Form2.Label1.Text = TextBox1.Text
End Sub
As shown above you can pass the data directly from control to control. The same idea can be used with variables too.
I am late but I think this answer can help.
For example, Form1 named "menu" opens and passes variable to Form2 named "ordine".
The variable to pass is "hotel"
In menu on button_click
Dim ordinef As New Ordine()
If ordinef Is Nothing Then
'control that form is not opened yet if open close before
ordinef = New Ordine()
Else
ordinef.Close()
ordinef = New Ordine()
End If
ordinef.hotel = hotel
ordinef.Show()
In Form2 (Ordine):
Private Sub Ordine_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
public hotel as string
msgbox hotel
That's it!!

Check if any dialog is open

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.

Using Variables Across Forms - VB

I've got a fairly simple question (I think) on passing variables between forms using Visual Basic.
I've got a program with 2 forms (Form1 and Form2). Form1 has 3 radio buttons, which the user has to select one of and then loads Form2.
Now I've made it so that if radiobutton1 is picked, the Public Variable "radio_select" will equal "radiobutton1", if radiobutton2 is picked, "radio_select" will equal "radiobutton2".
But whenever I try call "radio_select" in my second form, it comes up blank. Why could this be? And how can I fix it.
I've tried using if form1.radiobutton1.checked = true but I keep getting the first radiobutton, regardless of the radio button I've selected.
I think the form is being unloaded, or there is an issue somewhere there, as it appears none of the variables get passed to the second form, once it has been initialized. Also note, the first form is hidden Me.Hide() when the second form is called.
Have you considered a slight re-design whereby you create a property on Form2 called RadioSelect and then set this from Form1 before showing Form2:
Class Form2
Public Property RadioSelect As String
...
End Class
...
Dim f2 as new Form2()
f2.RadioSelect = "radiobutton2"
f2.Show() ' Or f2.ShowDialog()
This gets you away from an unnecessary public variable and should also ensure Form2 can see what it needs from Form1, or whoever calls it.
Edit:
The following works for me:
Public Class Form1
Public Test As String
Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Test = "I'm Here"
Me.Hide()
Form2.ShowDialog()
End Sub
End Class
Public Class Form2
Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Text = Form1.Test
End Sub
End Class